Merge branch 'master' of /home/davem/src/GIT/linux-2.6/

Conflicts:
	drivers/net/wimax/i2400m/usb-notif.c
diff --git a/CREDITS b/CREDITS
index 5e07367..e8b7d366 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3738,7 +3738,7 @@
 S: Germany
 
 N: Gertjan van Wingerde
-E: gwingerde@home.nl
+E: gwingerde@gmail.com
 D: Ralink rt2x00 WLAN driver
 D: Minix V2 file-system
 D: Misc fixes
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
new file mode 100644
index 0000000..6434f0d
--- /dev/null
+++ b/Documentation/ABI/testing/ima_policy
@@ -0,0 +1,61 @@
+What:		security/ima/policy
+Date:		May 2008
+Contact:	Mimi Zohar <zohar@us.ibm.com>
+Description:
+		The Trusted Computing Group(TCG) runtime Integrity
+		Measurement Architecture(IMA) maintains a list of hash
+		values of executables and other sensitive system files
+		loaded into the run-time of this system.  At runtime,
+		the policy can be constrained based on LSM specific data.
+		Policies are loaded into the securityfs file ima/policy
+		by opening the file, writing the rules one at a time and
+		then closing the file.  The new policy takes effect after
+		the file ima/policy is closed.
+
+		rule format: action [condition ...]
+
+		action: measure | dont_measure
+		condition:= base | lsm
+			base:	[[func=] [mask=] [fsmagic=] [uid=]]
+			lsm:	[[subj_user=] [subj_role=] [subj_type=]
+				 [obj_user=] [obj_role=] [obj_type=]]
+
+		base: 	func:= [BPRM_CHECK][FILE_MMAP][INODE_PERMISSION]
+			mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
+			fsmagic:= hex value
+			uid:= decimal value
+		lsm:  	are LSM specific
+
+		default policy:
+			# PROC_SUPER_MAGIC
+			dont_measure fsmagic=0x9fa0
+			# SYSFS_MAGIC
+			dont_measure fsmagic=0x62656572
+			# DEBUGFS_MAGIC
+			dont_measure fsmagic=0x64626720
+			# TMPFS_MAGIC
+			dont_measure fsmagic=0x01021994
+			# SECURITYFS_MAGIC
+			dont_measure fsmagic=0x73636673
+
+			measure func=BPRM_CHECK
+			measure func=FILE_MMAP mask=MAY_EXEC
+			measure func=INODE_PERM mask=MAY_READ uid=0
+
+		The default policy measures all executables in bprm_check,
+		all files mmapped executable in file_mmap, and all files
+		open for read by root in inode_permission.
+
+		Examples of LSM specific definitions:
+
+		SELinux:
+			# SELINUX_MAGIC
+			dont_measure fsmagic=0xF97CFF8C
+
+			dont_measure obj_type=var_log_t
+			dont_measure obj_type=auditd_log_t
+			measure subj_user=system_u func=INODE_PERM mask=MAY_READ
+			measure subj_role=system_r func=INODE_PERM mask=MAY_READ
+
+		Smack:
+			measure subj_user=_ func=INODE_PERM mask=MAY_READ
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 1462ed8..a3a83d3 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -12,7 +12,8 @@
 	    kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
 	    gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
-	    mac80211.xml debugobjects.xml sh.xml regulator.xml
+	    mac80211.xml debugobjects.xml sh.xml regulator.xml \
+	    alsa-driver-api.xml writing-an-alsa-driver.xml
 
 ###
 # The build process is as follows (targets):
diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/DocBook/alsa-driver-api.tmpl
similarity index 87%
rename from Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
rename to Documentation/DocBook/alsa-driver-api.tmpl
index 9d644f7..0230a96 100644
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ b/Documentation/DocBook/alsa-driver-api.tmpl
@@ -1,11 +1,11 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
-
-<book>
-<?dbhtml filename="index.html">
+<?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" []>
 
 <!-- ****************************************************** -->
 <!-- Header  -->
 <!-- ****************************************************** -->
+<book id="ALSA-Driver-API">
   <bookinfo>
     <title>The ALSA Driver API</title>
 
@@ -35,6 +35,8 @@
 
   </bookinfo>
 
+<toc></toc>
+
   <chapter><title>Management of Cards and Devices</title>
      <sect1><title>Card Management</title>
 !Esound/core/init.c
@@ -71,6 +73,10 @@
 !Esound/pci/ac97/ac97_codec.c
 !Esound/pci/ac97/ac97_pcm.c
      </sect1>
+     <sect1><title>Virtual Master Control API</title>
+!Esound/core/vmaster.c
+!Iinclude/sound/control.h
+     </sect1>
   </chapter>
   <chapter><title>MIDI API</title>
      <sect1><title>Raw MIDI API</title>
@@ -89,6 +95,9 @@
      <sect1><title>Hardware-Dependent Devices API</title>
 !Esound/core/hwdep.c
      </sect1>
+     <sect1><title>Jack Abstraction Layer API</title>
+!Esound/core/jack.c
+     </sect1>
      <sect1><title>ISA DMA Helpers</title>
 !Esound/core/isadma.c
      </sect1>
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
index 52e1b79..8f6e3b2 100644
--- a/Documentation/DocBook/uio-howto.tmpl
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -42,6 +42,13 @@
 
 <revhistory>
 	<revision>
+	<revnumber>0.8</revnumber>
+	<date>2008-12-24</date>
+	<authorinitials>hjk</authorinitials>
+	<revremark>Added name attributes in mem and portio sysfs directories.
+		</revremark>
+	</revision>
+	<revision>
 	<revnumber>0.7</revnumber>
 	<date>2008-12-23</date>
 	<authorinitials>hjk</authorinitials>
@@ -303,12 +310,19 @@
 	appear if the size of the mapping is not 0.
 </para>
 <para>
-	Each <filename>mapX/</filename> directory contains two read-only files
-	that show start address and size of the memory:
+	Each <filename>mapX/</filename> directory contains four read-only files
+	that show attributes of the memory:
 </para>
 <itemizedlist>
 <listitem>
 	<para>
+	<filename>name</filename>: A string identifier for this mapping. This
+	is optional, the string can be empty. Drivers can set this to make it
+	easier for userspace to find the correct mapping.
+	</para>
+</listitem>
+<listitem>
+	<para>
 	<filename>addr</filename>: The address of memory that can be mapped.
 	</para>
 </listitem>
@@ -366,12 +380,19 @@
 	<filename>/sys/class/uio/uioX/portio/</filename>.
 </para>
 <para>
-	Each <filename>portX/</filename> directory contains three read-only
-	files that show start, size, and type of the port region:
+	Each <filename>portX/</filename> directory contains four read-only
+	files that show name, start, size, and type of the port region:
 </para>
 <itemizedlist>
 <listitem>
 	<para>
+	<filename>name</filename>: A string identifier for this port region.
+	The string is optional and can be empty. Drivers can set it to make it
+	easier for userspace to find a certain port region.
+	</para>
+</listitem>
+<listitem>
+	<para>
 	<filename>start</filename>: The first port of this region.
 	</para>
 </listitem>
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl
similarity index 98%
rename from Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
rename to Documentation/DocBook/writing-an-alsa-driver.tmpl
index 87a7c07a..46b08fe 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl
@@ -1,11 +1,11 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
-
-<book>
-<?dbhtml filename="index.html">
+<?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" []>
 
 <!-- ****************************************************** -->
 <!-- Header  -->
 <!-- ****************************************************** -->
+<book id="Writing-an-ALSA-Driver">
   <bookinfo>
     <title>Writing an ALSA Driver</title>
     <author>
@@ -492,9 +492,9 @@
           }
 
           /* (2) */
-          card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-          if (card == NULL)
-                  return -ENOMEM;
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+          if (err < 0)
+                  return err;
 
           /* (3) */
           err = snd_mychip_create(card, pci, &chip);
@@ -590,8 +590,9 @@
             <programlisting>
 <![CDATA[
   struct snd_card *card;
+  int err;
   ....
-  card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
 ]]>
             </programlisting>
           </informalexample>
@@ -809,26 +810,28 @@
 
       <para>
         As mentioned above, to create a card instance, call
-      <function>snd_card_new()</function>.
+      <function>snd_card_create()</function>.
 
         <informalexample>
           <programlisting>
 <![CDATA[
   struct snd_card *card;
-  card = snd_card_new(index, id, module, extra_size);
+  int err;
+  err = snd_card_create(index, id, module, extra_size, &card);
 ]]>
           </programlisting>
         </informalexample>
       </para>
 
       <para>
-        The function takes four arguments, the card-index number, the
+        The function takes five arguments, the card-index number, the
         id string, the module pointer (usually
         <constant>THIS_MODULE</constant>),
-        and the size of extra-data space.  The last argument is used to
+        the size of extra-data space, and the pointer to return the
+        card instance.  The extra_size argument is used to
         allocate card-&gt;private_data for the
         chip-specific data.  Note that these data
-        are allocated by <function>snd_card_new()</function>.
+        are allocated by <function>snd_card_create()</function>.
       </para>
     </section>
 
@@ -915,15 +918,16 @@
       </para>
 
       <section id="card-management-chip-specific-snd-card-new">
-        <title>1. Allocating via <function>snd_card_new()</function>.</title>
+        <title>1. Allocating via <function>snd_card_create()</function>.</title>
         <para>
           As mentioned above, you can pass the extra-data-length
-	  to the 4th argument of <function>snd_card_new()</function>, i.e.
+	  to the 4th argument of <function>snd_card_create()</function>, i.e.
 
           <informalexample>
             <programlisting>
 <![CDATA[
-  card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct mychip));
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+                        sizeof(struct mychip), &card);
 ]]>
             </programlisting>
           </informalexample>
@@ -952,8 +956,8 @@
 
         <para>
           After allocating a card instance via
-          <function>snd_card_new()</function> (with
-          <constant>NULL</constant> on the 4th arg), call
+          <function>snd_card_create()</function> (with
+          <constant>0</constant> on the 4th arg), call
           <function>kzalloc()</function>. 
 
           <informalexample>
@@ -961,7 +965,7 @@
 <![CDATA[
   struct snd_card *card;
   struct mychip *chip;
-  card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
   .....
   chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 ]]>
@@ -5750,8 +5754,9 @@
           ....
           struct snd_card *card;
           struct mychip *chip;
+          int err;
           ....
-          card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
           ....
           chip = kzalloc(sizeof(*chip), GFP_KERNEL);
           ....
@@ -5763,7 +5768,7 @@
       </informalexample>
 
 	When you created the chip data with
-	<function>snd_card_new()</function>, it's anyway accessible
+	<function>snd_card_create()</function>, it's anyway accessible
 	via <structfield>private_data</structfield> field.
 
       <informalexample>
@@ -5775,9 +5780,10 @@
           ....
           struct snd_card *card;
           struct mychip *chip;
+          int err;
           ....
-          card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-                              sizeof(struct mychip));
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+                                sizeof(struct mychip), &card);
           ....
           chip = card->private_data;
           ....
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 6e25340..accfe2f 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -298,3 +298,15 @@
 
 	Note that, rcu_assign_pointer() and rcu_dereference() relate to
 	SRCU just as they do to other forms of RCU.
+
+15.	The whole point of call_rcu(), synchronize_rcu(), and friends
+	is to wait until all pre-existing readers have finished before
+	carrying out some otherwise-destructive operation.  It is
+	therefore critically important to -first- remove any path
+	that readers can follow that could be affected by the
+	destructive operation, and -only- -then- invoke call_rcu(),
+	synchronize_rcu(), or friends.
+
+	Because these primitives only wait for pre-existing readers,
+	it is the caller's responsibility to guarantee safety to
+	any subsequent readers.
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 5b0cfa6..ce73f3eb 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -117,10 +117,28 @@
 sampling_rate: measured in uS (10^-6 seconds), this is how often you
 want the kernel to look at the CPU usage and to make decisions on
 what to do about the frequency.  Typically this is set to values of
-around '10000' or more.
+around '10000' or more. It's default value is (cmp. with users-guide.txt):
+transition_latency * 1000
+The lowest value you can set is:
+transition_latency * 100 or it may get restricted to a value where it
+makes not sense for the kernel anymore to poll that often which depends
+on your HZ config variable (HZ=1000: max=20000us, HZ=250: max=5000).
+Be aware that transition latency is in ns and sampling_rate is in us, so you
+get the same sysfs value by default.
+Sampling rate should always get adjusted considering the transition latency
+To set the sampling rate 750 times as high as the transition latency
+in the bash (as said, 1000 is default), do:
+echo `$(($(cat cpuinfo_transition_latency) * 750 / 1000)) \
+    >ondemand/sampling_rate
 
-show_sampling_rate_(min|max): the minimum and maximum sampling rates
-available that you may set 'sampling_rate' to.
+show_sampling_rate_(min|max): THIS INTERFACE IS DEPRECATED, DON'T USE IT.
+You can use wider ranges now and the general
+cpuinfo_transition_latency variable (cmp. with user-guide.txt) can be
+used to obtain exactly the same info:
+show_sampling_rate_min = transtition_latency * 500    / 1000
+show_sampling_rate_max = transtition_latency * 500000 / 1000
+(divided by 1000 is to illustrate that sampling rate is in us and
+transition latency is exported ns).
 
 up_threshold: defines what the average CPU usage between the samplings
 of 'sampling_rate' needs to be for the kernel to make a decision on
diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
index 917918f..75f4119 100644
--- a/Documentation/cpu-freq/user-guide.txt
+++ b/Documentation/cpu-freq/user-guide.txt
@@ -152,6 +152,18 @@
 				frequency the processor can run at(in kHz) 
 cpuinfo_max_freq :		this file shows the maximum operating
 				frequency the processor can run at(in kHz) 
+cpuinfo_transition_latency	The time it takes on this CPU to
+				switch between two frequencies in nano
+				seconds. If unknown or known to be
+				that high that the driver does not
+				work with the ondemand governor, -1
+				(CPUFREQ_ETERNAL) will be returned.
+				Using this information can be useful
+				to choose an appropriate polling
+				frequency for a kernel governor or
+				userspace daemon. Make sure to not
+				switch the frequency too often
+				resulting in performance loss.
 scaling_driver :		this file shows what cpufreq driver is
 				used to set the frequency on this CPU
 
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt
new file mode 100644
index 0000000..674c566
--- /dev/null
+++ b/Documentation/dynamic-debug-howto.txt
@@ -0,0 +1,240 @@
+
+Introduction
+============
+
+This document describes how to use the dynamic debug (ddebug) feature.
+
+Dynamic debug is designed to allow you to dynamically enable/disable kernel
+code to obtain additional kernel information. Currently, if
+CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_debug() calls can be
+dynamically enabled per-callsite.
+
+Dynamic debug has even more useful features:
+
+ * Simple query language allows turning on and off debugging statements by
+   matching any combination of:
+
+   - source filename
+   - function name
+   - line number (including ranges of line numbers)
+   - module name
+   - format string
+
+ * Provides a debugfs control file: <debugfs>/dynamic_debug/control which can be
+   read to display the complete list of known debug statements, to help guide you
+
+Controlling dynamic debug Behaviour
+===============================
+
+The behaviour of pr_debug()/dev_debug()s are controlled via writing to a
+control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
+filesystem, in order to make use of this feature. Subsequently, we refer to the
+control file as: <debugfs>/dynamic_debug/control. For example, if you want to
+enable printing from source file 'svcsock.c', line 1603 you simply do:
+
+nullarbor:~ # echo 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+
+If you make a mistake with the syntax, the write will fail thus:
+
+nullarbor:~ # echo 'file svcsock.c wtf 1 +p' >
+				<debugfs>/dynamic_debug/control
+-bash: echo: write error: Invalid argument
+
+Viewing Dynamic Debug Behaviour
+===========================
+
+You can view the currently configured behaviour of all the debug statements
+via:
+
+nullarbor:~ # cat <debugfs>/dynamic_debug/control
+# filename:lineno [module]function flags format
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA Module Removed, deregister RPC RDMA transport\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline       : %d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth         : %d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests     : %d\012"
+...
+
+
+You can also apply standard Unix text manipulation filters to this
+data, e.g.
+
+nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control  | wc -l
+62
+
+nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l
+42
+
+Note in particular that the third column shows the enabled behaviour
+flags for each debug statement callsite (see below for definitions of the
+flags).  The default value, no extra behaviour enabled, is "-".  So
+you can view all the debug statement callsites with any non-default flags:
+
+nullarbor:~ # awk '$3 != "-"' <debugfs>/dynamic_debug/control
+# filename:lineno [module]function flags format
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012"
+
+
+Command Language Reference
+==========================
+
+At the lexical level, a command comprises a sequence of words separated
+by whitespace characters.  Note that newlines are treated as word
+separators and do *not* end a command or allow multiple commands to
+be done together.  So these are all equivalent:
+
+nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+nullarbor:~ # echo -c '  file   svcsock.c     line  1603 +p  ' >
+				<debugfs>/dynamic_debug/control
+nullarbor:~ # echo -c 'file svcsock.c\nline 1603 +p' >
+				<debugfs>/dynamic_debug/control
+nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+
+Commands are bounded by a write() system call.  If you want to do
+multiple commands you need to do a separate "echo" for each, like:
+
+nullarbor:~ # echo 'file svcsock.c line 1603 +p' > /proc/dprintk ;\
+> echo 'file svcsock.c line 1563 +p' > /proc/dprintk
+
+or even like:
+
+nullarbor:~ # (
+> echo 'file svcsock.c line 1603 +p' ;\
+> echo 'file svcsock.c line 1563 +p' ;\
+> ) > /proc/dprintk
+
+At the syntactical level, a command comprises a sequence of match
+specifications, followed by a flags change specification.
+
+command ::= match-spec* flags-spec
+
+The match-spec's are used to choose a subset of the known dprintk()
+callsites to which to apply the flags-spec.  Think of them as a query
+with implicit ANDs between each pair.  Note that an empty list of
+match-specs is possible, but is not very useful because it will not
+match any debug statement callsites.
+
+A match specification comprises a keyword, which controls the attribute
+of the callsite to be compared, and a value to compare against.  Possible
+keywords are:
+
+match-spec ::= 'func' string |
+	       'file' string |
+	       'module' string |
+	       'format' string |
+	       'line' line-range
+
+line-range ::= lineno |
+	       '-'lineno |
+	       lineno'-' |
+	       lineno'-'lineno
+// Note: line-range cannot contain space, e.g.
+// "1-30" is valid range but "1 - 30" is not.
+
+lineno ::= unsigned-int
+
+The meanings of each keyword are:
+
+func
+    The given string is compared against the function name
+    of each callsite.  Example:
+
+    func svc_tcp_accept
+
+file
+    The given string is compared against either the full
+    pathname or the basename of the source file of each
+    callsite.  Examples:
+
+    file svcsock.c
+    file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c
+
+module
+    The given string is compared against the module name
+    of each callsite.  The module name is the string as
+    seen in "lsmod", i.e. without the directory or the .ko
+    suffix and with '-' changed to '_'.  Examples:
+
+    module sunrpc
+    module nfsd
+
+format
+    The given string is searched for in the dynamic debug format
+    string.  Note that the string does not need to match the
+    entire format, only some part.  Whitespace and other
+    special characters can be escaped using C octal character
+    escape \ooo notation, e.g. the space character is \040.
+    Alternatively, the string can be enclosed in double quote
+    characters (") or single quote characters (').
+    Examples:
+
+    format svcrdma:	    // many of the NFS/RDMA server dprintks
+    format readahead	    // some dprintks in the readahead cache
+    format nfsd:\040SETATTR // one way to match a format with whitespace
+    format "nfsd: SETATTR"  // a neater way to match a format with whitespace
+    format 'nfsd: SETATTR'  // yet another way to match a format with whitespace
+
+line
+    The given line number or range of line numbers is compared
+    against the line number of each dprintk() callsite.  A single
+    line number matches the callsite line number exactly.  A
+    range of line numbers matches any callsite between the first
+    and last line number inclusive.  An empty first number means
+    the first line in the file, an empty line number means the
+    last number in the file.  Examples:
+
+    line 1603	    // exactly line 1603
+    line 1600-1605  // the six lines from line 1600 to line 1605
+    line -1605	    // the 1605 lines from line 1 to line 1605
+    line 1600-	    // all lines from line 1600 to the end of the file
+
+The flags specification comprises a change operation followed
+by one or more flag characters.  The change operation is one
+of the characters:
+
+-
+    remove the given flags
+
++
+    add the given flags
+
+=
+    set the flags to the given flags
+
+The flags are:
+
+p
+    Causes a printk() message to be emitted to dmesg
+
+Note the regexp ^[-+=][scp]+$ matches a flags specification.
+Note also that there is no convenient syntax to remove all
+the flags at once, you need to use "-psc".
+
+Examples
+========
+
+// enable the message at line 1603 of file svcsock.c
+nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+
+// enable all the messages in file svcsock.c
+nullarbor:~ # echo -n 'file svcsock.c +p' >
+				<debugfs>/dynamic_debug/control
+
+// enable all the messages in the NFS server module
+nullarbor:~ # echo -n 'module nfsd +p' >
+				<debugfs>/dynamic_debug/control
+
+// enable all 12 messages in the function svc_process()
+nullarbor:~ # echo -n 'func svc_process +p' >
+				<debugfs>/dynamic_debug/control
+
+// disable all 12 messages in the function svc_process()
+nullarbor:~ # echo -n 'func svc_process -p' >
+				<debugfs>/dynamic_debug/control
+
+// enable messages for NFS calls READ, READLINK, READDIR and READDIR+.
+nullarbor:~ # echo -n 'format "nfsd: READ" +p' >
+				<debugfs>/dynamic_debug/control
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index ac98851..802c6fd 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -337,3 +337,12 @@
 	Secmark, it is time to deprecate the older mechanism and start the
 	process of removing the old code.
 Who:	Paul Moore <paul.moore@hp.com>
+---------------------------
+
+What:	sysfs ui for changing p4-clockmod parameters
+When:	September 2009
+Why:	See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and
+	e088e4c9cdb618675874becb91b2fd581ee707e6.
+	Removal is subject to fixing any remaining bugs in ACPI which may
+	cause the thermal throttling not to happen at the right time.
+Who:	Dave Jones <davej@redhat.com>, Matthew Garrett <mjg@redhat.com>
diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt
index 4333e83..e055acb 100644
--- a/Documentation/filesystems/ext2.txt
+++ b/Documentation/filesystems/ext2.txt
@@ -373,10 +373,11 @@
 Compression (*)		http://e2compr.sourceforge.net/
 
 Implementations for:
-Windows 95/98/NT/2000	http://uranus.it.swin.edu.au/~jn/linux/Explore2fs.htm
-Windows 95 (*)		http://www.yipton.demon.co.uk/content.html#FSDEXT2
+Windows 95/98/NT/2000	http://www.chrysocome.net/explore2fs
+Windows 95 (*)		http://www.yipton.net/content.html#FSDEXT2
 DOS client (*)		ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2/
-OS/2			http://perso.wanadoo.fr/matthieu.willm/ext2-os2/
-RISC OS client		ftp://ftp.barnet.ac.uk/pub/acorn/armlinux/iscafs/
+OS/2 (+)		ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2/
+RISC OS client		http://www.esw-heim.tu-clausthal.de/~marco/smorbrod/IscaFS/
 
 (*) no longer actively developed/supported (as of Apr 2001)
+(+) no longer actively developed/supported (as of Mar 2009)
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 9dd2a3bb..e5f3833 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -198,5 +198,5 @@
 programs: 	http://e2fsprogs.sourceforge.net/
 		http://ext2resize.sourceforge.net
 
-useful links:	http://www-106.ibm.com/developerworks/linux/library/l-fs7/
-		http://www-106.ibm.com/developerworks/linux/library/l-fs8/
+useful links:	http://www.ibm.com/developerworks/library/l-fs7.html
+		http://www.ibm.com/developerworks/library/l-fs8.html
diff --git a/Documentation/filesystems/squashfs.txt b/Documentation/filesystems/squashfs.txt
index 3e79e4a..b324c03 100644
--- a/Documentation/filesystems/squashfs.txt
+++ b/Documentation/filesystems/squashfs.txt
@@ -22,7 +22,7 @@
 
 				Squashfs		Cramfs
 
-Max filesystem size:		2^64			16 MiB
+Max filesystem size:		2^64			256 MiB
 Max file size:			~ 2 TiB			16 MiB
 Max files:			unlimited		unlimited
 Max directories:		unlimited		unlimited
diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90
index 0e84117..93d8e3d 100644
--- a/Documentation/hwmon/lm90
+++ b/Documentation/hwmon/lm90
@@ -42,6 +42,11 @@
     Addresses scanned: I2C 0x4e
     Datasheet: Publicly available at the Maxim website
                http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3497
+  * Maxim MAX6648
+    Prefix: 'max6646'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3500
   * Maxim MAX6649
     Prefix: 'max6646'
     Addresses scanned: I2C 0x4c
@@ -74,6 +79,11 @@
                            0x4c, 0x4d and 0x4e
     Datasheet: Publicly available at the Maxim website
                http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3370
+  * Maxim MAX6692
+    Prefix: 'max6646'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3500
 
 
 Author: Jean Delvare <khali@linux-fr.org>
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 54f21a5..1a29ff3 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -44,6 +44,7 @@
 	FB	The frame buffer device is enabled.
 	HW	Appropriate hardware is enabled.
 	IA-64	IA-64 architecture is enabled.
+	IMA     Integrity measurement architecture is enabled.
 	IOSCHED	More than one I/O scheduler is enabled.
 	IP_PNP	IP DHCP, BOOTP, or RARP is enabled.
 	ISAPNP	ISA PnP code is enabled.
@@ -902,6 +903,15 @@
 	ihash_entries=	[KNL]
 			Set number of hash buckets for inode cache.
 
+	ima_audit=	[IMA]
+			Format: { "0" | "1" }
+			0 -- integrity auditing messages. (Default)
+			1 -- enable informational integrity auditing messages.
+
+	ima_hash=	[IMA]
+			Formt: { "sha1" | "md5" }
+			default: "sha1"
+
 	in2000=		[HW,SCSI]
 			See header of drivers/scsi/in2000.c.
 
@@ -1816,11 +1826,6 @@
 			autoconfiguration.
 			Ranges are in pairs (memory base and size).
 
-	dynamic_printk	Enables pr_debug()/dev_dbg() calls if
-			CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled.
-			These can also be switched on/off via
-			<debugfs>/dynamic_printk/modules
-
 	print-fatal-signals=
 			[KNL] debug: print fatal signals
 			print-fatal-signals=1: print segfault info to
diff --git a/Documentation/logo.gif b/Documentation/logo.gif
deleted file mode 100644
index 2eae75f..0000000
--- a/Documentation/logo.gif
+++ /dev/null
Binary files differ
diff --git a/Documentation/logo.svg b/Documentation/logo.svg
new file mode 100644
index 0000000..cb9e485
--- /dev/null
+++ b/Documentation/logo.svg
@@ -0,0 +1,2911 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="1771.6534"
+   height="1417.3228"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="tuz.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0"
+   style="display:inline;enable-background:new"
+   inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_final.png"
+   inkscape:export-xdpi="100.03588"
+   inkscape:export-ydpi="100.03588">
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.25"
+     inkscape:cx="-174.7931"
+     inkscape:cy="784.26325"
+     inkscape:document-units="px"
+     inkscape:current-layer="svg2"
+     showgrid="false"
+     inkscape:window-width="1280"
+     inkscape:window-height="823"
+     inkscape:window-x="-4"
+     inkscape:window-y="25"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     units="mm" />
+  <defs
+     id="defs4">
+    <filter
+       inkscape:collect="always"
+       x="-0.084654994"
+       width="1.16931"
+       y="-0.36592469"
+       height="1.7318494"
+       id="filter11361">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="4.5740586"
+         id="feGaussianBlur11363" />
+    </filter>
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 564.0976 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="1445.8591 : 564.0976 : 1"
+       inkscape:persp3d-origin="722.92957 : 376.06506 : 1"
+       id="perspective8145" />
+    <linearGradient
+       id="linearGradient7622">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop7624" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop7626" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4113">
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="0"
+         id="stop4115" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop4117" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3660">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3662" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3664" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3627">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3629" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop3631" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2843">
+      <stop
+         id="stop2845"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0.02188784"
+         id="stop2847" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0.75866222"
+         id="stop2849" />
+      <stop
+         id="stop2851"
+         offset="0.88508981"
+         style="stop-color:#232323;stop-opacity:1;" />
+      <stop
+         id="stop2853"
+         offset="1"
+         style="stop-color:#595959;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient8964">
+      <stop
+         style="stop-color:#1a1a1a;stop-opacity:1;"
+         offset="0"
+         id="stop8966" />
+      <stop
+         style="stop-color:#1a1a1a;stop-opacity:0;"
+         offset="1"
+         id="stop8968" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient8952">
+      <stop
+         style="stop-color:#0a0c0c;stop-opacity:1;"
+         offset="0"
+         id="stop8954" />
+      <stop
+         style="stop-color:#1f2727;stop-opacity:0;"
+         offset="1"
+         id="stop8956" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient8430">
+      <stop
+         style="stop-color:#1e2323;stop-opacity:1;"
+         offset="0"
+         id="stop8432" />
+      <stop
+         id="stop8438"
+         offset="0.55992389"
+         style="stop-color:#181d1d;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop8434" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient8398">
+      <stop
+         style="stop-color:#283131;stop-opacity:0;"
+         offset="0"
+         id="stop8400" />
+      <stop
+         id="stop8402"
+         offset="0.5125587"
+         style="stop-color:#1e2424;stop-opacity:0;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop8404" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4870">
+      <stop
+         style="stop-color:#c7bd80;stop-opacity:1;"
+         offset="0"
+         id="stop4872" />
+      <stop
+         style="stop-color:#c7bd80;stop-opacity:0;"
+         offset="1"
+         id="stop4874" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4862">
+      <stop
+         style="stop-color:#e2e2e2;stop-opacity:1;"
+         offset="0"
+         id="stop4864" />
+      <stop
+         style="stop-color:#e2e2e2;stop-opacity:0;"
+         offset="1"
+         id="stop4866" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4478">
+      <stop
+         style="stop-color:#f9eed3;stop-opacity:1;"
+         offset="0"
+         id="stop4480" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4482" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4106">
+      <stop
+         style="stop-color:#d9e002;stop-opacity:1;"
+         offset="0"
+         id="stop4108" />
+      <stop
+         id="stop4114"
+         offset="0.5"
+         style="stop-color:#a9ae01;stop-opacity:1;" />
+      <stop
+         style="stop-color:#717501;stop-opacity:1;"
+         offset="1"
+         id="stop4110" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4084">
+      <stop
+         style="stop-color:#7d7d00;stop-opacity:1;"
+         offset="0"
+         id="stop4086" />
+      <stop
+         id="stop4088"
+         offset="0.3636601"
+         style="stop-color:#c6c700;stop-opacity:1;" />
+      <stop
+         style="stop-color:#f6f800;stop-opacity:1;"
+         offset="1"
+         id="stop4090" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4041">
+      <stop
+         id="stop4043"
+         offset="0"
+         style="stop-color:#ffff00;stop-opacity:1;" />
+      <stop
+         id="stop4045"
+         offset="1"
+         style="stop-color:#ffff00;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4025">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4027" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4031" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4013">
+      <stop
+         style="stop-color:#ffff00;stop-opacity:1;"
+         offset="0"
+         id="stop4015" />
+      <stop
+         style="stop-color:#b2b200;stop-opacity:1;"
+         offset="1"
+         id="stop4017" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3985">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3987" />
+      <stop
+         style="stop-color:#1d1d1d;stop-opacity:1;"
+         offset="1"
+         id="stop3989" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3961">
+      <stop
+         style="stop-color:#283131;stop-opacity:0;"
+         offset="0"
+         id="stop3963" />
+      <stop
+         id="stop3965"
+         offset="0.5"
+         style="stop-color:#1e2424;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop3967" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3951">
+      <stop
+         id="stop3953"
+         offset="0"
+         style="stop-color:#344040;stop-opacity:1;" />
+      <stop
+         style="stop-color:#222929;stop-opacity:1;"
+         offset="0.5"
+         id="stop3955" />
+      <stop
+         id="stop3957"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3909">
+      <stop
+         style="stop-color:#283131;stop-opacity:1;"
+         offset="0"
+         id="stop3911" />
+      <stop
+         id="stop3917"
+         offset="0.5"
+         style="stop-color:#1e2424;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop3913" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3537">
+      <stop
+         style="stop-color:#ada469;stop-opacity:1;"
+         offset="0"
+         id="stop3539" />
+      <stop
+         id="stop3545"
+         offset="0.81132078"
+         style="stop-color:#ada469;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="1"
+         id="stop3541" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3317">
+      <stop
+         style="stop-color:#cfc690;stop-opacity:1"
+         offset="0"
+         id="stop3319" />
+      <stop
+         id="stop3321"
+         offset="0.21161865"
+         style="stop-color:#afa775;stop-opacity:1;" />
+      <stop
+         id="stop3323"
+         offset="0.53408515"
+         style="stop-color:#615c3a;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0.76504093"
+         id="stop3325" />
+      <stop
+         id="stop3327"
+         offset="1"
+         style="stop-color:#403518;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3239">
+      <stop
+         id="stop3251"
+         offset="0"
+         style="stop-color:#cfc690;stop-opacity:1;" />
+      <stop
+         style="stop-color:#afa775;stop-opacity:1;"
+         offset="0.21161865"
+         id="stop3267" />
+      <stop
+         style="stop-color:#615c3a;stop-opacity:1;"
+         offset="0.53408515"
+         id="stop3261" />
+      <stop
+         id="stop3265"
+         offset="0.76504093"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         style="stop-color:#403518;stop-opacity:1;"
+         offset="1"
+         id="stop3243" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3239"
+       id="radialGradient3281"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.5480423,1.7414304,-1.9683515,1.7497638,-1130.5586,-1872.5121)"
+       spreadMethod="pad"
+       cx="806.52582"
+       cy="212.68117"
+       fx="806.52582"
+       fy="212.68117"
+       r="48.363216" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3317"
+       id="radialGradient3315"
+       cx="543.6698"
+       cy="147.3131"
+       fx="543.6698"
+       fy="147.3131"
+       r="47.863216"
+       gradientTransform="matrix(2.1382256,0,0,2.3382884,-77.03847,-101.68704)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3537"
+       id="radialGradient3543"
+       cx="385"
+       cy="237.00504"
+       fx="385"
+       fy="237.00504"
+       r="86.928574"
+       gradientTransform="matrix(1,0,0,0.8562038,0,34.080427)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3909"
+       id="radialGradient3915"
+       cx="418.30365"
+       cy="342.47794"
+       fx="418.30365"
+       fy="342.47794"
+       r="131.4509"
+       gradientTransform="matrix(1.3957347,0.6211056,-0.4244067,0.9537174,-15.061913,-227.96711)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3951"
+       id="radialGradient3933"
+       cx="397.16388"
+       cy="336.95245"
+       fx="397.16388"
+       fy="336.95245"
+       r="36.75"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.9449972,2.4894837e-7,-2.4894833e-7,1.9449969,-375.31868,-318.41912)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3961"
+       id="linearGradient3959"
+       x1="398.21429"
+       y1="343.52289"
+       x2="379.28571"
+       y2="265.30862"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(450.03125,73.843964)" />
+    <filter
+       inkscape:collect="always"
+       id="filter3981"
+       x="-0.30000001"
+       width="1.6"
+       y="-0.30000001"
+       height="1.6">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2"
+         id="feGaussianBlur3983" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3985"
+       id="radialGradient3991"
+       cx="402.48898"
+       cy="317.23578"
+       fx="402.48898"
+       fy="317.23578"
+       r="23.714285"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(4.3776616,0,0,4.3776616,-1358.3025,-1070.7357)" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3999">
+      <path
+         style="opacity:1;fill:#f5ff04;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+         d="M 179.64286,267.36218 C 157.23242,307.0651 119.02676,383.14247 110.35715,417.00504 C 101.70994,450.78014 101.58516,483.42158 110,503.43362 C 118.3602,523.31575 136.16398,539.06642 150.71428,544.86218 C 150.1179,530.48631 165.08723,501.57635 223.57143,472.36218 C 282.1977,443.07704 301.95306,445.23132 327.14285,425.21932 C 352.77291,404.85756 339.75316,358.17469 330.35714,331.29075 C 320.9229,304.29747 295.38973,272.16627 263.92857,261.6479 C 232.8953,251.27258 198.91081,256.79953 179.64286,267.36218 z"
+         id="path4001"
+         sodipodi:nodetypes="czzczzzzc" />
+    </clipPath>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4013"
+       id="radialGradient4056"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+       cx="228.81355"
+       cy="440.26971"
+       fx="228.81355"
+       fy="440.26971"
+       r="119.17509" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4041"
+       id="radialGradient4060"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(5.911206e-2,2.6869855,-0.7234268,1.5914947e-2,408.72779,-424.56452)"
+       cx="275.4422"
+       cy="335.34866"
+       fx="275.4422"
+       fy="335.34866"
+       r="36.75" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4025"
+       id="radialGradient4062"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(5.911206e-2,2.6869855,-0.7234268,1.5914947e-2,408.72779,-424.56452)"
+       cx="275.4422"
+       cy="335.34866"
+       fx="275.4422"
+       fy="335.34866"
+       r="36.75" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4084"
+       id="linearGradient4082"
+       gradientUnits="userSpaceOnUse"
+       x1="182.35046"
+       y1="256.11136"
+       x2="145.53348"
+       y2="542.20502" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4100">
+      <path
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.9000755px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="M 265.93541,126.68393 L 247.1682,295.54701 L 421.27363,222.42633 L 483.22803,311.08516 L 541.11243,279.09486 L 503.57801,99.035183 L 265.93541,126.68393 z"
+         id="path4102"
+         sodipodi:nodetypes="ccccccc" />
+    </clipPath>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4106"
+       id="radialGradient4112"
+       cx="250.22678"
+       cy="475.09763"
+       fx="250.22678"
+       fy="475.09763"
+       r="95.98877"
+       gradientTransform="matrix(1.2259004,-0.7077739,0.1413989,0.2449102,322.22326,608.91815)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4484"
+       x1="412.08926"
+       y1="404.91574"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4486"
+       x1="411.91071"
+       y1="404.91577"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4488"
+       x1="411.91071"
+       y1="405.54077"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4490"
+       x1="412.08926"
+       y1="405.54077"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4492"
+       x1="411.73212"
+       y1="405.54077"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4862"
+       id="radialGradient4868"
+       cx="429.56738"
+       cy="377.42877"
+       fx="429.56738"
+       fy="377.42877"
+       r="72.079735"
+       gradientTransform="matrix(1,0,0,0.618034,0,144.16496)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4870"
+       id="radialGradient4876"
+       cx="437.6991"
+       cy="391.21735"
+       fx="437.6991"
+       fy="391.21735"
+       r="36.611931"
+       gradientTransform="matrix(1,0,0,0.618034,0,149.43174)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4013"
+       id="radialGradient3585"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+       cx="228.81355"
+       cy="440.26971"
+       fx="228.81355"
+       fy="440.26971"
+       r="119.17509" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4084"
+       id="linearGradient3587"
+       gradientUnits="userSpaceOnUse"
+       x1="182.35046"
+       y1="256.11136"
+       x2="145.53348"
+       y2="542.20502" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3317"
+       id="radialGradient8410"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.0036478,-1.0345492e-7,1.7124628e-7,1.6613125,-753.99632,-302.76972)"
+       cx="317.78754"
+       cy="129.65378"
+       fx="317.78754"
+       fy="129.65378"
+       r="47.863216" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8398"
+       id="radialGradient8412"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.0747661,-0.1577957,0.2382425,3.1325183,-1144.2358,-272.29325)"
+       cx="325.30847"
+       cy="80.909554"
+       fx="325.30847"
+       fy="80.909554"
+       r="26.937988" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8514">
+      <path
+         style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
+         id="path8516"
+         sodipodi:nodetypes="cscccccccccccc" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8604">
+      <path
+         style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
+         id="path8606"
+         sodipodi:nodetypes="cscccccccccccc" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8610">
+      <path
+         style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
+         id="path8612"
+         sodipodi:nodetypes="cscccccccccccc" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8616">
+      <path
+         style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
+         id="path8618"
+         sodipodi:nodetypes="cscccccccccccc" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8622">
+      <path
+         style="opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+         d="M 821.64329,477.88997 C 821.64329,477.88997 844.26276,471.38316 857.38604,472.01724 C 870.50932,472.65133 888.02762,473.95586 901.09489,484.20343 C 914.16216,494.45099 926.16263,511.3435 935.20728,542.57308 C 944.25193,573.80266 936.9056,641.82509 929.03125,685.92043 C 921.1569,730.01577 900.76615,792.03341 884.03125,825.92043 C 867.29635,859.80745 834.23354,903.41563 823.46182,915.79659 C 812.0976,928.85856 767.25593,952.22276 744.03125,958.06326 C 749.33455,947.45666 792.93101,907.47442 779.03125,897.349 C 765.01228,887.13674 733.27116,943.33136 694.7381,926.38217 C 716.12041,913.25005 736.5175,875.19611 728.77871,859.78772 C 720.93846,844.17733 698.07378,908.54529 635.24317,896.8006 C 665.29521,869.27394 690.65023,825.89659 676.50587,813.8209 C 662.09071,801.51403 616.04412,868.11405 616.04412,868.11405 C 616.04412,868.11405 613.22222,826.41287 629.81732,799.50673 C 646.45667,772.52886 709.47029,717.89146 729.37045,687.80331 C 749.2706,657.71517 762.98301,621.79429 771.50587,595.28537 C 780.02873,568.77645 787.30681,518.18583 787.30681,518.18583"
+         id="path8624"
+         sodipodi:nodetypes="czzzzzzczczczczzzc" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8642">
+      <path
+         style="opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 366.88839,504.13471 C 366.88839,504.13471 337.33433,544.70776 319.03125,578.42042 C 300.72816,612.13309 260.41016,704.77736 248.67411,749.49185 C 236.91471,794.29529 186.17411,873.06329 186.17411,873.06329 L 262.24554,891.27757 C 262.24554,891.27757 274.05266,878.45422 293.31696,845.20614 C 312.58126,811.95806 353.67411,706.63471 353.67411,706.63471 L 366.88839,504.13471 z"
+         id="path8644"
+         sodipodi:nodetypes="czzcczcc" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8658">
+      <path
+         style="opacity:1;fill:#0b0b0b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 569.03125,1018.7776 C 564.74554,1019.4919 541.4031,1022.3957 511.17411,1028.7776 C 480.94512,1035.1595 411.39918,1054.7395 368.31696,1064.4919 C 325.23474,1074.2443 251.05253,1099.3079 211.40434,1091.7573 C 171.75616,1084.2067 121.88839,1027.349 121.88839,1027.349 L 126.17411,933.06329 C 126.17411,933.06329 212.05962,916.86235 238.31696,899.49186 C 264.57431,882.12137 283.89934,849.82588 297.60268,828.06329 C 311.30602,806.3007 330.45982,756.63471 330.45982,756.63471 L 569.03125,1018.7776 z"
+         id="path8660"
+         sodipodi:nodetypes="czzzcczzcc" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8802"
+       x="-0.35311759"
+       width="1.7062352"
+       y="-0.1817714"
+       height="1.3635428">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="48.038491"
+         id="feGaussianBlur8804" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8806"
+       x="-0.61142862"
+       width="2.2228572"
+       y="-0.14930232"
+       height="1.2986046">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="37.830213"
+         id="feGaussianBlur8808" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8810"
+       x="-0.23519406"
+       width="1.4703881"
+       y="-0.24500646"
+       height="1.4900129">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="58.328041"
+         id="feGaussianBlur8812" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8814"
+       x="-0.20466694"
+       width="1.4093339"
+       y="-0.29007819"
+       height="1.5801564">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="22.300169"
+         id="feGaussianBlur8816" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8818"
+       x="-0.34381232"
+       width="1.6876246"
+       y="-0.18433961"
+       height="1.3686792">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="34.542167"
+         id="feGaussianBlur8820" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8822"
+       x="-0.2742857"
+       width="1.5485713"
+       y="-0.21333334"
+       height="1.4266667">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="11.313708"
+         id="feGaussianBlur8824" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8826"
+       x="-0.25894088"
+       width="1.5178818"
+       y="-0.2236412"
+       height="1.4472824">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="19.631544"
+         id="feGaussianBlur8828" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8856"
+       x="-0.3253231"
+       width="1.6506462"
+       y="-0.19013336"
+       height="1.3802667">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="28.712591"
+         id="feGaussianBlur8858" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8860"
+       x="-0.38093024"
+       width="1.7618605"
+       y="-0.17518716"
+       height="1.3503743">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="19.304015"
+         id="feGaussianBlur8862" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8888"
+       x="-0.2112188"
+       width="1.4224375"
+       y="-0.16808605"
+       height="1.3361721">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="8.3693583"
+         id="feGaussianBlur8890" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8892"
+       x="-0.18692794"
+       width="1.3738559"
+       y="-0.23646873"
+       height="1.4729375">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="31.21228"
+         id="feGaussianBlur8894" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8906">
+      <path
+         style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 352.24553,211.99185 C 348.4411,186.72762 335.43581,161.35383 335.08873,136.46662 C 334.90247,123.1111 338.36158,109.89571 348.84426,96.912574 C 385.19128,31.616739 465.78517,12.217889 534.77892,5.447147 C 621.70131,-5.569654 719.69159,23.387219 768.15026,100.84843 C 822.27428,176.58173 824.82502,273.38755 848.7623,360.37638 C 878.20009,487.50398 903.54144,616.59052 909.15454,747.22673 C 906.09106,825.40858 900.7282,912.41088 848.65133,975.36086 C 800.62479,1025.7183 725.86486,1025.4139 661.58145,1034.3632 C 571.02606,1039.0182 477.22992,1018.2174 399.79755,970.16496 C 335.02191,932.22495 304.06736,856.68633 302.51815,784.14538 C 294.12898,704.27022 328.90967,630.33687 354.13855,556.98577 C 361.60916,474.2247 363.55141,390.73802 363.79189,307.60093 C 362.95507,275.40549 356.70236,243.7836 352.24553,211.99185 z"
+         id="path8908"
+         sodipodi:nodetypes="cscccccccccccc" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8940"
+       x="-0.25152978"
+       width="1.5030596"
+       y="-0.053035267"
+       height="1.1060705">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="13.024603"
+         id="feGaussianBlur8942" />
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8952"
+       id="linearGradient8958"
+       x1="609.31244"
+       y1="239.46866"
+       x2="560.83142"
+       y2="262.86206"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(450.03125,73.843964)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8964"
+       id="linearGradient8970"
+       x1="603.84064"
+       y1="627.85303"
+       x2="616.24396"
+       y2="585.42664"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(450.03125,73.843964)" />
+    <filter
+       inkscape:collect="always"
+       id="filter9020"
+       x="-0.32861114"
+       width="1.6572223"
+       y="-0.182"
+       height="1.364">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="20.912684"
+         id="feGaussianBlur9022" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9024"
+       x="-0.55453134"
+       width="2.1090627"
+       y="-0.51434779"
+       height="2.0286956">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="20.912684"
+         id="feGaussianBlur9026" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9044"
+       x="-0.32631579"
+       width="1.6526316"
+       y="-0.84545463"
+       height="2.6909094">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="21.92031"
+         id="feGaussianBlur9046" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9048"
+       x="-0.40879121"
+       width="1.8175824"
+       y="-0.71538466"
+       height="2.4307692">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="21.92031"
+         id="feGaussianBlur9050" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter3587"
+       x="-0.1">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="8.881432"
+         id="feGaussianBlur3589" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3602">
+      <path
+         sodipodi:nodetypes="czzzzzzczczczczzzc"
+         id="path3604"
+         d="M 647.61204,540.04601 C 647.61204,540.04601 670.23151,533.5392 683.35479,534.17328 C 696.47807,534.80737 713.99637,536.1119 727.06364,546.35947 C 740.13091,556.60703 752.13138,573.49954 761.17603,604.72912 C 770.22068,635.9587 762.87435,703.98113 755,748.07647 C 747.12565,792.17181 726.7349,854.18945 710,888.07647 C 693.2651,921.96349 660.20229,965.57167 649.43057,977.95263 C 638.06635,991.0146 593.22468,1014.3788 570,1020.2193 C 575.3033,1009.6127 618.89976,969.63046 605,959.50504 C 590.98103,949.29278 559.23991,1005.4874 520.70685,988.53821 C 542.08916,975.40609 562.48625,937.35215 554.74746,921.94376 C 546.90721,906.33337 524.04253,970.70133 461.21192,958.95664 C 491.26396,931.42998 516.61898,888.05263 502.47462,875.97694 C 488.05946,863.67007 442.01287,930.27009 442.01287,930.27009 C 442.01287,930.27009 439.19097,888.56891 455.78607,861.66277 C 472.42542,834.6849 535.43904,780.0475 555.3392,749.95935 C 575.23935,719.87121 588.95176,683.95033 597.47462,657.44141 C 605.99748,630.93249 613.27556,580.34187 613.27556,580.34187"
+         style="opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4120"
+       x="-0.2770822"
+       width="1.5541644"
+       y="-0.32482043"
+       height="1.6496409">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="19.956289"
+         id="feGaussianBlur4122" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3631">
+      <path
+         style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+         d="M 760.16396,935.83377 C 766.95806,954.73656 770.65765,969.13346 772.05426,987.04566 C 773.45088,1004.958 768.27158,1038.8465 769.1538,1057.7018 C 770.03555,1076.547 777.28749,1097.8008 796.49843,1106.6707 C 815.9173,1115.6365 845.81767,1116.882 870.61827,1103.5251 C 895.41887,1090.1681 928.01929,1033.1996 941.59253,1006.2164 C 955.21638,979.13246 980.3536,891.71903 986.25333,856.44781 C 992.15306,821.1766 988.80387,815.14704 981.63585,807.39232 C 984.27615,779.55217 980.13613,752.45689 994.74554,720.20614 C 964.49653,732.03184 957.36325,760.36684 946.42665,785.71122 C 938.42574,734.77829 946.63581,714.43803 949.74554,684.49186 C 920.68078,699.26977 906.88403,731.60588 904.74554,777.349 C 893.82159,776.0448 883.3541,772.91477 871.17411,776.63471 C 870.91007,730.61137 869.71055,699.7453 880.08474,662.42822 C 826.82927,683.45508 817.13746,769.02232 824.03125,775.20614 C 813.14843,775.74114 802.66017,773.90884 791.17411,778.06329 C 791.81303,735.49194 790.91365,693.15468 761.17411,655.20614 C 761.17411,655.20614 730.21605,736.12848 729.74554,758.77757 C 729.27503,781.42666 739.19713,798.94345 739.19713,798.94345 C 739.19713,798.94345 730.62906,835.68396 732.89854,857.17568 C 735.19439,878.91714 753.34144,916.85185 760.16396,935.83377 z"
+         id="path3633"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3665">
+      <path
+         sodipodi:nodetypes="czzcczcc"
+         id="path3667"
+         d="M 366.88839,504.13471 C 366.88839,504.13471 337.33433,544.70776 319.03125,578.42042 C 300.72816,612.13309 260.41016,704.77736 248.67411,749.49185 C 236.91471,794.29529 186.17411,873.06329 186.17411,873.06329 L 262.24554,891.27757 C 262.24554,891.27757 274.05266,878.45422 293.31696,845.20614 C 312.58126,811.95806 353.67411,706.63471 353.67411,706.63471 L 366.88839,504.13471 z"
+         style="opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3677">
+      <path
+         style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+         d="M 586.13271,997.98981 C 592.92681,1016.8926 596.6264,1031.2895 598.02301,1049.2017 C 599.41963,1067.114 594.24033,1101.0025 595.12255,1119.8578 C 596.0043,1138.703 603.25624,1159.9568 622.46718,1168.8267 C 641.88605,1177.7925 671.78642,1179.038 696.58702,1165.6811 C 721.38762,1152.3241 753.98804,1095.3556 767.56128,1068.3724 C 781.18513,1041.2885 806.32235,953.87507 812.22208,918.60385 C 818.12181,883.33264 814.77262,877.30308 807.6046,869.54836 C 810.2449,841.70821 806.10488,814.61293 820.71429,782.36218 C 790.46528,794.18788 783.332,822.52288 772.3954,847.86726 C 764.39449,796.93433 772.60456,776.59407 775.71429,746.6479 C 746.64953,761.42581 732.85278,793.76192 730.71429,839.50504 C 719.79034,838.20084 709.32285,835.07081 697.14286,838.79075 C 696.87882,792.76741 695.6793,761.90134 706.05349,724.58426 C 652.79802,745.61112 643.10621,831.17836 650,837.36218 C 639.11718,837.89718 628.62892,836.06488 617.14286,840.21933 C 617.78178,797.64798 616.8824,755.31072 587.14286,717.36218 C 587.14286,717.36218 556.1848,798.28452 555.71429,820.93361 C 555.24378,843.5827 565.16588,861.09949 565.16588,861.09949 C 565.16588,861.09949 556.59781,897.84 558.86729,919.33172 C 561.16314,941.07318 579.31019,979.00789 586.13271,997.98981 z"
+         id="path3679"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter3898">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="10.892985"
+         id="feGaussianBlur3900" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4130"
+       x="-0.49509686"
+       width="1.9901937"
+       y="-0.26708817"
+       height="1.5341763">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="10.730622"
+         id="feGaussianBlur4132" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4141"
+       x="-0.40611032"
+       width="1.8122206"
+       y="-0.30260596"
+       height="1.6052119">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="9.8586086"
+         id="feGaussianBlur4143" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4177">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path4179"
+         d="M 586.13271,997.98981 C 592.92681,1016.8926 596.6264,1031.2895 598.02301,1049.2017 C 599.41963,1067.114 594.24033,1101.0025 595.12255,1119.8578 C 596.0043,1138.703 603.25624,1159.9568 622.46718,1168.8267 C 641.88605,1177.7925 671.78642,1179.038 696.58702,1165.6811 C 721.38762,1152.3241 753.98804,1095.3556 767.56128,1068.3724 C 781.18513,1041.2885 806.32235,953.87507 812.22208,918.60385 C 818.12181,883.33264 814.77262,877.30308 807.6046,869.54836 C 810.2449,841.70821 806.10488,814.61293 820.71429,782.36218 C 790.46528,794.18788 783.332,822.52288 772.3954,847.86726 C 764.39449,796.93433 772.60456,776.59407 775.71429,746.6479 C 746.64953,761.42581 732.85278,793.76192 730.71429,839.50504 C 719.79034,838.20084 709.32285,835.07081 697.14286,838.79075 C 696.87882,792.76741 695.6793,761.90134 706.05349,724.58426 C 652.79802,745.61112 643.10621,831.17836 650,837.36218 C 639.11718,837.89718 628.62892,836.06488 617.14286,840.21933 C 617.78178,797.64798 616.8824,755.31072 587.14286,717.36218 C 587.14286,717.36218 556.1848,798.28452 555.71429,820.93361 C 555.24378,843.5827 565.16588,861.09949 565.16588,861.09949 C 565.16588,861.09949 556.59781,897.84 558.86729,919.33172 C 561.16314,941.07318 579.31019,979.00789 586.13271,997.98981 z"
+         style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4185">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="3.6164709"
+         id="feGaussianBlur4187" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4105">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="3.8640966"
+         id="feGaussianBlur4107" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath2833">
+      <path
+         style="opacity:1;fill:#292929;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 569.03125,1018.7776 C 564.74554,1019.4919 541.4031,1022.3957 511.17411,1028.7776 C 480.94512,1035.1595 453.86016,1033.7437 375.38803,1046.1072 C 295.53625,1058.688 281.32367,1088.6495 267.26578,1093.1715 C 252.56564,1097.9001 121.88839,1027.349 121.88839,1027.349 L 126.17411,933.06329 C 126.17411,933.06329 212.05962,916.86235 238.31696,899.49186 C 264.57431,882.12137 283.89934,849.82588 297.60268,828.06329 C 311.30602,806.3007 330.45982,756.63471 330.45982,756.63471 L 569.03125,1018.7776 z"
+         id="path2835"
+         sodipodi:nodetypes="czzzcczzcc" />
+    </clipPath>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2843"
+       id="linearGradient2841"
+       gradientUnits="userSpaceOnUse"
+       x1="347.89655"
+       y1="1070.2124"
+       x2="275.58191"
+       y2="867.97992" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3627"
+       id="linearGradient3688"
+       gradientUnits="userSpaceOnUse"
+       x1="699.32867"
+       y1="269.76755"
+       x2="698.97504"
+       y2="346.1351" />
+    <mask
+       maskUnits="userSpaceOnUse"
+       id="mask3684">
+      <path
+         sodipodi:type="arc"
+         style="opacity:1;fill:url(#linearGradient3688);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.43724918px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         id="path3686"
+         sodipodi:cx="579.474"
+         sodipodi:cy="260.57516"
+         sodipodi:rx="192.6866"
+         sodipodi:ry="164.04877"
+         d="M 772.1606,260.57516 A 192.6866,164.04877 0 1 1 386.7874,260.57516 A 192.6866,164.04877 0 1 1 772.1606,260.57516 z"
+         transform="translate(-174.03125,62.156036)" />
+    </mask>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3622">
+      <path
+         style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+         d="M 266.27183,924.57186 C 264.86456,943.37307 265.12693,957.32289 268.35357,973.87514 C 271.58022,990.42748 284.75965,1019.7825 288.68797,1037.0589 C 292.61419,1054.326 291.3821,1075.3685 276.22853,1088.2071 C 260.91092,1101.1845 234.17726,1109.806 208.39623,1103.9409 C 182.61517,1098.0756 138.84716,1054.7175 119.80604,1033.7126 C 100.6939,1012.6293 56.045183,939.86194 41.867508,909.43681 C 27.689836,879.01169 29.207903,872.71824 33.747793,863.90708 C 24.381071,839.38658 21.334081,813.84027 0.035335518,788.33044 C 30.360815,791.44488 43.915625,815.28677 60.161025,835.47019 C 54.631129,787.39416 42.10631,771.05369 31.787073,744.74589 C 61.781368,750.82755 82.366433,776.61829 95.766856,817.45839 C 105.32101,813.54048 114.00462,808.08545 125.95427,808.39719 C 114.65677,766.70139 108.00481,738.48135 89.267015,707.32725 C 142.70898,712.99758 172.92404,787.96657 168.23844,795.28805 C 178.21641,793.04406 187.24409,788.75767 198.67497,789.63638 C 187.42601,751.28936 177.62716,712.76848 195.01526,670.9882 C 195.01526,670.9882 243.30204,736.42507 249.40492,756.79397 C 255.50779,777.16288 250.92373,795.49449 250.92373,795.49449 C 250.92373,795.49449 267.8833,826.57978 271.21765,846.58862 C 274.59075,866.82997 267.68496,905.69194 266.27183,924.57186 z"
+         id="path3624"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3636">
+      <path
+         style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+         d="M 760.16396,935.83377 C 766.95806,954.73656 770.65765,969.13346 772.05426,987.04566 C 773.45088,1004.958 768.27158,1038.8465 769.1538,1057.7018 C 770.03555,1076.547 777.28749,1097.8008 796.49843,1106.6707 C 815.9173,1115.6365 845.81767,1116.882 870.61827,1103.5251 C 895.41887,1090.1681 928.01929,1033.1996 941.59253,1006.2164 C 955.21638,979.13246 980.3536,891.71903 986.25333,856.44781 C 992.15306,821.1766 988.80387,815.14704 981.63585,807.39232 C 984.27615,779.55217 980.13613,752.45689 994.74554,720.20614 C 964.49653,732.03184 957.36325,760.36684 946.42665,785.71122 C 938.42574,734.77829 946.63581,714.43803 949.74554,684.49186 C 920.68078,699.26977 906.88403,731.60588 904.74554,777.349 C 893.82159,776.0448 883.3541,772.91477 871.17411,776.63471 C 870.91007,730.61137 869.71055,699.7453 880.08474,662.42822 C 826.82927,683.45508 817.13746,769.02232 824.03125,775.20614 C 813.14843,775.74114 802.66017,773.90884 791.17411,778.06329 C 791.81303,735.49194 790.91365,693.15468 761.17411,655.20614 C 761.17411,655.20614 730.21605,736.12848 729.74554,758.77757 C 729.27503,781.42666 739.19713,798.94345 739.19713,798.94345 C 739.19713,798.94345 730.62906,835.68396 732.89854,857.17568 C 735.19439,878.91714 753.34144,916.85185 760.16396,935.83377 z"
+         id="path3638"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+    </clipPath>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3660"
+       id="linearGradient3666"
+       x1="1255.7386"
+       y1="667.09216"
+       x2="893.69995"
+       y2="858.01099"
+       gradientUnits="userSpaceOnUse" />
+    <filter
+       inkscape:collect="always"
+       id="filter3779"
+       x="-0.087980822"
+       width="1.1759616"
+       y="-0.17728332"
+       height="1.3545666">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="16.340344"
+         id="feGaussianBlur3781" />
+    </filter>
+    <filter
+       id="filter3785"
+       inkscape:label="White Fur">
+      <feTurbulence
+         id="feTurbulence3787"
+         in="SourceAlpha"
+         type="fractalNoise"
+         baseFrequency="0.24044943820224721"
+         numOctaves="10"
+         seed="655"
+         result="result0" />
+      <feDisplacementMap
+         id="feDisplacementMap3789"
+         in="SourceGraphic"
+         in2="result0"
+         scale="62"
+         xChannelSelector="B"
+         yChannelSelector="G" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter3677">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2.0397518"
+         id="feGaussianBlur3679" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3722">
+      <path
+         style="opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 709.28572,844.50504 C 763.57143,843.07647 835.32072,829.45305 879.28572,817.71932 C 923.33843,805.96218 1005.172,781.37208 1054.6428,759.86218 C 1103.9821,738.40946 1168.2465,700.58058 1208.9286,667.71933 C 1249.4367,634.99864 1261.3185,611.89952 1269.6429,634.1479 C 1278.012,656.51569 1253.2359,690.47352 1231.7857,715.21933 C 1210.1816,740.14273 1179.0544,767.92466 1132.8571,804.50504 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 C 862.93394,960.20183 791.79666,991.31489 747.85714,1005.5765 C 703.91762,1019.8381 616.42857,1036.6479 616.42857,1036.6479 L 709.28572,844.50504 z"
+         id="path3724"
+         sodipodi:nodetypes="czzzzzzzzcc" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3986">
+      <path
+         style="opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 709.28572,844.50504 C 763.57143,843.07647 835.32072,829.45305 879.28572,817.71932 C 923.33843,805.96218 1005.172,781.37208 1054.6428,759.86218 C 1103.9821,738.40946 1168.2465,700.58058 1208.9286,667.71933 C 1249.4367,634.99864 1261.3185,611.89952 1269.6429,634.1479 C 1278.012,656.51569 1253.2359,690.47352 1231.7857,715.21933 C 1210.1816,740.14273 1179.0544,767.92466 1132.8571,804.50504 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 C 862.93394,960.20183 791.79666,991.31489 747.85714,1005.5765 C 703.91762,1019.8381 616.42857,1036.6479 616.42857,1036.6479 L 709.28572,844.50504 z"
+         id="path3988"
+         sodipodi:nodetypes="czzzzzzzzcc" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3992">
+      <path
+         style="opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 709.28572,844.50504 C 763.57143,843.07647 835.32072,829.45305 879.28572,817.71932 C 923.33843,805.96218 1005.172,781.37208 1054.6428,759.86218 C 1103.9821,738.40946 1168.2465,700.58058 1208.9286,667.71933 C 1249.4367,634.99864 1261.3185,611.89952 1269.6429,634.1479 C 1278.012,656.51569 1253.2359,690.47352 1231.7857,715.21933 C 1210.1816,740.14273 1179.0544,767.92466 1132.8571,804.50504 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 C 862.93394,960.20183 791.79666,991.31489 747.85714,1005.5765 C 703.91762,1019.8381 616.42857,1036.6479 616.42857,1036.6479 L 709.28572,844.50504 z"
+         id="path3994"
+         sodipodi:nodetypes="czzzzzzzzcc" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3998">
+      <path
+         style="opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         d="M 178.21428,274.14789 C 174.40985,248.88366 161.40456,223.50987 161.05748,198.62266 C 160.87122,185.26714 164.33033,172.05175 174.81301,159.06861 C 211.16003,93.772775 291.75392,74.373925 360.74767,67.603183 C 447.67006,56.586382 545.66034,85.543255 594.11901,163.00447 C 648.24303,238.73777 650.79377,335.54359 674.73105,422.53242 C 704.16884,549.66002 729.51019,678.74656 735.12329,809.38277 C 732.05981,887.56462 726.69695,974.56692 674.62008,1037.5169 C 626.59354,1087.8743 551.83361,1087.5699 487.5502,1096.5192 C 396.99481,1101.1742 303.19867,1080.3734 225.7663,1032.321 C 160.99066,994.38099 130.03611,918.84237 128.4869,846.30142 C 120.09773,766.42626 154.87842,692.49291 180.1073,619.14181 C 187.57791,536.38074 189.52016,452.89406 189.76064,369.75697 C 188.92382,337.56153 182.67111,305.93964 178.21428,274.14789 z"
+         id="path4000"
+         sodipodi:nodetypes="cscccccccccccc" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4002"
+       x="-0.24334238"
+       width="1.4866848"
+       y="-0.39104807"
+       height="1.7820961">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="14.589518"
+         id="feGaussianBlur4004" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4010"
+       x="-0.14577261"
+       width="1.2915452"
+       y="-0.23523259"
+       height="1.4704652">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="4.4442907"
+         id="feGaussianBlur4012" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4053">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.6062947"
+         id="feGaussianBlur4055" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4079">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="6.5887624"
+         id="feGaussianBlur4081" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4083">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.5052066"
+         id="feGaussianBlur4085" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4113"
+       id="radialGradient4119"
+       cx="296.33783"
+       cy="427.17749"
+       fx="296.33783"
+       fy="427.17749"
+       r="19.704132"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.9797125,0,0,2.9797125,-599.28727,-827.0855)" />
+    <filter
+       inkscape:collect="always"
+       id="filter6949"
+       x="-0.10294895"
+       width="1.2058979"
+       y="-0.34224695"
+       height="1.6844939">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6951" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6953"
+       x="-0.098320946"
+       width="1.1966419"
+       y="-0.19750816"
+       height="1.3950163">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6955" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6957"
+       x="-0.098213427"
+       width="1.1964267"
+       y="-0.19838208"
+       height="1.3967642">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6959" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6961"
+       x="-0.09919104"
+       width="1.1983821"
+       y="-0.22643611"
+       height="1.4528722">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6963" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6965"
+       x="-0.099081434"
+       width="1.1981629"
+       y="-0.22529824"
+       height="1.4505965">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6967" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6969"
+       x="-0.10450897"
+       width="1.2090179"
+       y="-0.40468886"
+       height="1.8093777">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6971" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6973"
+       x="-0.10330495"
+       width="1.2066098"
+       y="-0.36439717"
+       height="1.7287945">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6975" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6977"
+       x="-0.10224481"
+       width="1.2044896"
+       y="-0.32371372"
+       height="1.6474274">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6979" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6981"
+       x="-0.10052545"
+       width="1.2010509"
+       y="-0.2742162"
+       height="1.5484324">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6983" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6985"
+       x="-0.098428868"
+       width="1.1968577"
+       y="-0.20853186"
+       height="1.4170637">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6987" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6989"
+       x="-0.098428868"
+       width="1.1968577"
+       y="-0.20287035"
+       height="1.4057407">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6991" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6993"
+       x="-0.098213255"
+       width="1.1964265"
+       y="-0.19838208"
+       height="1.3967642">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6995" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6997">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6999" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7001">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur7003" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7285"
+       x="-0.030884685"
+       width="1.0617694"
+       y="-0.10267408"
+       height="1.2053483">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7287" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7289">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7291" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7293">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7295" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7297">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7299" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7301">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7303" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7305">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7307" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7309">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7311" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7313">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7315" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7317">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7319" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7321">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7323" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7325"
+       x="-0.031352691"
+       width="1.0627054"
+       y="-0.12140666"
+       height="1.2428133">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7327" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7329"
+       x="-0.030991485"
+       width="1.061983"
+       y="-0.10931916"
+       height="1.2186383">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7331" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7333">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7335" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7337">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7339" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7345">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.7233839"
+         id="feGaussianBlur7347" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath7421">
+      <path
+         sodipodi:type="inkscape:offset"
+         inkscape:radius="0"
+         inkscape:original="M 1111.4062 -285.9375 L 1107.4688 -284.0625 C 1107.4283 -284.05228 1107.3692 -284.04201 1107.3438 -284.03125 C 1106.925 -283.8184 1107.1791 -283.93067 1106.6875 -283.71875 C 1106.2014 -283.50919 1104.9499 -283.13456 1102.5938 -282.25 C 1099.2626 -280.99942 1096.7895 -280.10016 1095.5938 -279.1875 C 1094.0576 -279.16623 1091.8733 -278.95419 1089.9375 -278.46875 C 1086.956 -277.72108 1085.0823 -277.29474 1083.1875 -276.875 C 1081.2927 -276.45527 1081.512 -276.23281 1080.3125 -276 C 1079.0159 -275.74833 1078.5911 -276.00899 1074.875 -275.21875 C 1071.3851 -274.4766 1065.9802 -273.28768 1064.7188 -272.53125 C 1063.1348 -272.71203 1060.8513 -272.85303 1058.875 -272.5625 C 1055.8346 -272.11554 1053.9588 -271.88974 1052.0312 -271.65625 C 1051.3758 -271.57687 1050.9902 -271.45547 1050.6875 -271.375 C 1050.2613 -271.24334 1050.0017 -271.11498 1049.3125 -271.03125 C 1048.0009 -270.87188 1047.5503 -271.18808 1043.7812 -270.75 C 1040.2273 -270.33691 1034.7758 -269.47718 1033.5312 -268.8125 C 1031.9322 -269.10979 1029.6735 -269.34669 1027.6875 -269.15625 C 1024.6287 -268.86293 1022.7155 -268.67226 1020.7812 -268.5 C 1018.847 -268.32773 1019.0926 -268.07763 1017.875 -267.96875 C 1016.5588 -267.85105 1016.1152 -268.13238 1012.3438 -267.71875 C 1008.8017 -267.3303 1003.3359 -266.50948 1002.0625 -265.84375 C 1000.4636 -266.13844 998.1753 -266.35076 996.1875 -266.15625 C 993.12921 -265.857 991.2463 -265.67601 989.3125 -265.5 C 988.65501 -265.44015 988.27245 -265.32144 987.96875 -265.25 C 987.54105 -265.13104 987.28525 -265.03193 986.59375 -264.96875 C 985.27775 -264.84849 984.834 -265.16363 981.0625 -264.75 C 977.50631 -264.35998 972.0569 -263.51084 970.8125 -262.84375 C 969.21381 -263.13793 966.95265 -263.36747 964.96875 -263.15625 C 961.91305 -262.83092 959.9947 -262.63001 958.0625 -262.4375 C 956.13031 -262.24499 956.37275 -261.99662 955.15625 -261.875 C 953.84137 -261.74353 953.3932 -262.03954 949.625 -261.59375 C 946.08611 -261.17509 940.6473 -260.30158 939.375 -259.625 C 937.77741 -259.90604 935.51505 -260.04543 933.53125 -259.8125 C 930.47927 -259.45413 928.58625 -259.24464 926.65625 -259.03125 C 926.00007 -258.95869 925.6156 -258.85856 925.3125 -258.78125 C 924.88571 -258.65402 924.6276 -258.51405 923.9375 -258.4375 C 922.62411 -258.29181 922.17015 -258.61152 918.40625 -258.125 C 914.85737 -257.66624 909.4276 -256.70598 908.1875 -256 C 906.59441 -256.24424 904.3537 -256.38135 902.375 -256.125 C 899.32741 -255.73018 897.4243 -255.47655 895.5 -255.21875 C 893.57571 -254.96096 893.7739 -254.72522 892.5625 -254.5625 C 891.25301 -254.3866 890.8153 -254.66688 887.0625 -254.09375 C 883.53821 -253.55551 878.1393 -252.39458 876.875 -251.65625 C 875.28751 -251.85979 873.0295 -251.91098 871.0625 -251.5625 C 868.03631 -251.02638 866.1636 -250.70081 864.25 -250.375 C 863.59941 -250.26423 863.2363 -250.10406 862.9375 -250 C 862.51681 -249.83512 862.27405 -249.6687 861.59375 -249.53125 C 860.29905 -249.26966 859.86665 -249.53745 856.15625 -248.71875 C 852.65777 -247.9468 847.31035 -246.33582 846.09375 -245.5 C 844.53085 -245.57745 842.33625 -245.41472 840.40625 -244.90625 C 837.43387 -244.12312 835.58855 -243.67416 833.71875 -243.15625 C 831.84875 -242.63835 832.0521 -242.38897 830.875 -242.0625 C 829.60251 -241.7096 829.17795 -241.95541 825.53125 -240.875 C 822.10657 -239.86037 816.88185 -237.94183 815.65625 -237.03125 C 814.11747 -237.01851 811.93645 -236.75903 810.03125 -236.15625 C 807.10027 -235.22891 805.2809 -234.69783 803.4375 -234.09375 C 802.81071 -233.88837 802.44585 -233.70117 802.15625 -233.5625 C 801.74867 -233.34889 801.50295 -233.15375 800.84375 -232.9375 C 799.58925 -232.52596 799.1576 -232.74846 795.5625 -231.5 C 792.17261 -230.32283 786.96755 -228.2863 785.78125 -227.34375 C 784.25737 -227.28408 782.1312 -226.94888 780.25 -226.28125 C 777.35261 -225.25296 775.55095 -224.60577 773.71875 -223.96875 C 771.88655 -223.33174 772.0909 -223.12021 770.9375 -222.71875 C 769.69071 -222.28479 769.27395 -222.51903 765.71875 -221.15625 C 762.38005 -219.87645 757.23165 -217.6737 756.03125 -216.6875 C 754.52407 -216.57981 752.39555 -216.1887 750.53125 -215.46875 C 747.66307 -214.36115 745.90735 -213.68719 744.09375 -213 C 743.47705 -212.76637 743.0973 -212.55797 742.8125 -212.40625 C 742.81251 -212.40625 742.8125 -212.37673 742.8125 -212.375 L 734.8125 -209.1875 L 736.625 -194.46875 C 736.36701 -194.52956 742.8125 -191.15625 742.8125 -191.15625 C 743.03891 -191.30093 743.26145 -191.42886 743.53125 -191.53125 C 744.61177 -191.94123 745.70285 -191.74702 749.53125 -193.21875 C 753.35977 -194.69049 754.7553 -195.22373 755.4375 -195.625 C 756.11711 -196.02478 757.04925 -196.50437 757.65625 -197.15625 C 759.48317 -197.294 761.22705 -197.64948 762.59375 -198.15625 C 765.56175 -199.25677 767.4691 -199.96244 769.375 -200.625 C 771.28081 -201.28754 771.72915 -202.03987 772.78125 -202.40625 C 773.87287 -202.78636 774.97635 -202.57163 778.84375 -203.9375 C 782.71115 -205.30336 784.1269 -205.76458 784.8125 -206.15625 C 785.51361 -206.55677 786.5133 -207.08923 787.125 -207.75 C 789.09581 -207.80466 790.94195 -208.13463 792.40625 -208.625 C 795.40777 -209.63008 797.3324 -210.24671 799.25 -210.875 C 800.78861 -211.3791 801.42415 -211.92177 802.15625 -212.3125 C 802.38647 -212.44681 802.63215 -212.56623 802.90625 -212.65625 C 804.00457 -213.01673 805.0877 -212.73762 809 -213.96875 C 812.91231 -215.19988 814.366 -215.6417 815.0625 -216 C 815.75641 -216.35697 816.6926 -216.79261 817.3125 -217.40625 C 819.17771 -217.42891 820.94835 -217.67308 822.34375 -218.09375 C 825.37415 -219.00729 827.33615 -219.52385 829.28125 -220.0625 C 831.22637 -220.60114 831.70745 -221.32702 832.78125 -221.625 C 833.89527 -221.93415 835.00125 -221.61761 838.96875 -222.65625 C 842.93625 -223.69488 844.38625 -224.08898 845.09375 -224.40625 C 845.82855 -224.73584 846.90765 -225.15997 847.53125 -225.78125 C 849.52907 -225.66525 851.3887 -225.80134 852.875 -226.15625 C 855.95311 -226.89125 857.9584 -227.25719 859.9375 -227.65625 C 861.52541 -227.97643 862.1818 -228.4468 862.9375 -228.75 C 863.17501 -228.8568 863.4044 -228.94276 863.6875 -229 C 864.82091 -229.22919 865.99215 -228.79107 870.03125 -229.5 C 874.07067 -230.20893 875.5315 -230.42709 876.25 -230.6875 C 876.96581 -230.94694 877.95435 -231.25474 878.59375 -231.78125 C 880.51795 -231.54176 882.34165 -231.55672 883.78125 -231.78125 C 886.90767 -232.26887 888.9358 -232.48192 890.9375 -232.75 C 892.93921 -233.01807 893.42625 -233.69514 894.53125 -233.84375 C 895.67767 -233.99793 896.8071 -233.54218 900.875 -234.0625 C 904.94281 -234.58282 906.43525 -234.75823 907.15625 -235 C 907.89337 -235.24714 908.95435 -235.58623 909.59375 -236.125 C 911.64375 -235.78947 913.56745 -235.72704 915.09375 -235.90625 C 918.23595 -236.27521 920.27375 -236.46561 922.28125 -236.6875 C 923.89207 -236.86552 924.5459 -237.2957 925.3125 -237.53125 C 925.55341 -237.61677 925.80655 -237.68685 926.09375 -237.71875 C 927.24345 -237.84647 928.39505 -237.3721 932.46875 -237.84375 C 936.54245 -238.3154 938.0278 -238.45435 938.75 -238.6875 C 939.46941 -238.91977 940.45025 -239.16096 941.09375 -239.65625 C 943.03005 -239.32279 944.8638 -239.25201 946.3125 -239.40625 C 949.45851 -239.7412 951.49 -239.92484 953.5 -240.125 C 955.50991 -240.32514 955.98415 -240.95139 957.09375 -241.0625 C 958.24485 -241.17778 959.39025 -240.69744 963.46875 -241.125 C 967.54725 -241.55256 969.05765 -241.68709 969.78125 -241.90625 C 970.52047 -242.13011 971.57685 -242.4195 972.21875 -242.9375 C 974.27575 -242.53883 976.2206 -242.4441 977.75 -242.59375 C 980.89871 -242.90185 982.9258 -243.067 984.9375 -243.25 C 986.55151 -243.39682 987.20055 -243.81055 987.96875 -244.03125 C 988.21005 -244.11211 988.4623 -244.16116 988.75 -244.1875 C 989.90211 -244.29295 991.0429 -243.79475 995.125 -244.1875 C 999.20711 -244.58025 1000.7139 -244.71834 1001.4375 -244.9375 C 1002.1584 -245.15583 1003.1371 -245.3852 1003.7812 -245.875 C 1005.7193 -245.52501 1007.5501 -245.42062 1009 -245.5625 C 1012.1487 -245.8706 1014.1758 -246.03575 1016.1875 -246.21875 C 1018.1991 -246.40174 1018.7017 -247.05677 1019.8125 -247.15625 C 1020.9648 -247.25948 1022.1047 -246.77142 1026.1875 -247.15625 C 1030.2704 -247.54107 1031.7762 -247.65725 1032.5 -247.875 C 1033.2393 -248.09743 1034.2956 -248.38949 1034.9375 -248.90625 C 1036.9949 -248.50448 1038.9404 -248.40292 1040.4688 -248.5625 C 1043.6153 -248.89102 1045.6458 -249.0852 1047.6562 -249.28125 C 1049.2692 -249.43854 1049.9219 -249.91273 1050.6875 -250.15625 C 1050.9282 -250.24429 1051.1507 -250.27762 1051.4375 -250.3125 C 1052.5858 -250.4522 1053.7542 -249.97259 1057.8125 -250.5625 C 1061.8708 -251.15242 1063.3743 -251.33964 1064.0938 -251.59375 C 1064.8104 -251.84691 1065.7684 -252.15182 1066.4062 -252.6875 C 1068.3259 -252.47556 1070.1262 -252.53609 1071.5625 -252.78125 C 1074.6816 -253.31365 1076.6741 -253.70986 1078.6562 -254.09375 C 1080.6383 -254.47762 1081.1305 -255.1334 1082.2188 -255.375 C 1083.3475 -255.62566 1084.489 -255.25871 1088.4688 -256.25 C 1092.4483 -257.24127 1093.8983 -257.6693 1094.5938 -258.03125 C 1095.316 -258.40725 1096.3555 -258.90183 1096.9688 -259.5625 C 1098.9317 -259.57454 1100.7625 -259.85355 1102.1875 -260.40625 C 1105.1387 -261.55085 1107.0607 -262.27567 1108.875 -263.15625 C 1110.3307 -263.86277 1111.1941 -264.85828 1111.4062 -265.15625 C 1111.6185 -265.4542 1111.5051 -265.8848 1111.5312 -265.90625 C 1111.5742 -265.94148 1111.8716 -266.00028 1112.0312 -266.34375 C 1112.8902 -268.19082 1114.3544 -271.97139 1114.4688 -272.65625 C 1114.5825 -273.33839 1114.6368 -274.00902 1114.6875 -274.40625 C 1114.7169 -274.63575 1114.5404 -275.28515 1114.5625 -275.34375 C 1114.5934 -275.42579 1114.8508 -275.59432 1114.9062 -275.84375 C 1115.1725 -277.04206 1114.9953 -278.05111 1114.7812 -279.46875 C 1114.5673 -280.88638 1113.8096 -284.08338 1113.1562 -284.9375 C 1112.4973 -285.79922 1111.9314 -285.94801 1111.4062 -285.9375 z "
+         style="fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+         id="path7423"
+         d="M 1111.4062,-285.9375 L 1107.4688,-284.0625 C 1107.4283,-284.05228 1107.3692,-284.04201 1107.3438,-284.03125 C 1106.925,-283.8184 1107.1791,-283.93067 1106.6875,-283.71875 C 1106.2014,-283.50919 1104.9499,-283.13456 1102.5938,-282.25 C 1099.2626,-280.99942 1096.7895,-280.10016 1095.5938,-279.1875 C 1094.0576,-279.16623 1091.8733,-278.95419 1089.9375,-278.46875 C 1086.956,-277.72108 1085.0823,-277.29474 1083.1875,-276.875 C 1081.2927,-276.45527 1081.512,-276.23281 1080.3125,-276 C 1079.0159,-275.74833 1078.5911,-276.00899 1074.875,-275.21875 C 1071.3851,-274.4766 1065.9802,-273.28768 1064.7188,-272.53125 C 1063.1348,-272.71203 1060.8513,-272.85303 1058.875,-272.5625 C 1055.8346,-272.11554 1053.9588,-271.88974 1052.0312,-271.65625 C 1051.3758,-271.57687 1050.9902,-271.45547 1050.6875,-271.375 C 1050.2613,-271.24334 1050.0017,-271.11498 1049.3125,-271.03125 C 1048.0009,-270.87188 1047.5503,-271.18808 1043.7812,-270.75 C 1040.2273,-270.33691 1034.7758,-269.47718 1033.5312,-268.8125 C 1031.9322,-269.10979 1029.6735,-269.34669 1027.6875,-269.15625 C 1024.6287,-268.86293 1022.7155,-268.67226 1020.7812,-268.5 C 1018.847,-268.32773 1019.0926,-268.07763 1017.875,-267.96875 C 1016.5588,-267.85105 1016.1152,-268.13238 1012.3438,-267.71875 C 1008.8017,-267.3303 1003.3359,-266.50948 1002.0625,-265.84375 C 1000.4636,-266.13844 998.1753,-266.35076 996.1875,-266.15625 C 993.12921,-265.857 991.2463,-265.67601 989.3125,-265.5 C 988.65501,-265.44015 988.27245,-265.32144 987.96875,-265.25 C 987.54105,-265.13104 987.28525,-265.03193 986.59375,-264.96875 C 985.27775,-264.84849 984.834,-265.16363 981.0625,-264.75 C 977.50631,-264.35998 972.0569,-263.51084 970.8125,-262.84375 C 969.21381,-263.13793 966.95265,-263.36747 964.96875,-263.15625 C 961.91305,-262.83092 959.9947,-262.63001 958.0625,-262.4375 C 956.13031,-262.24499 956.37275,-261.99662 955.15625,-261.875 C 953.84137,-261.74353 953.3932,-262.03954 949.625,-261.59375 C 946.08611,-261.17509 940.6473,-260.30158 939.375,-259.625 C 937.77741,-259.90604 935.51505,-260.04543 933.53125,-259.8125 C 930.47927,-259.45413 928.58625,-259.24464 926.65625,-259.03125 C 926.00007,-258.95869 925.6156,-258.85856 925.3125,-258.78125 C 924.88571,-258.65402 924.6276,-258.51405 923.9375,-258.4375 C 922.62411,-258.29181 922.17015,-258.61152 918.40625,-258.125 C 914.85737,-257.66624 909.4276,-256.70598 908.1875,-256 C 906.59441,-256.24424 904.3537,-256.38135 902.375,-256.125 C 899.32741,-255.73018 897.4243,-255.47655 895.5,-255.21875 C 893.57571,-254.96096 893.7739,-254.72522 892.5625,-254.5625 C 891.25301,-254.3866 890.8153,-254.66688 887.0625,-254.09375 C 883.53821,-253.55551 878.1393,-252.39458 876.875,-251.65625 C 875.28751,-251.85979 873.0295,-251.91098 871.0625,-251.5625 C 868.03631,-251.02638 866.1636,-250.70081 864.25,-250.375 C 863.59941,-250.26423 863.2363,-250.10406 862.9375,-250 C 862.51681,-249.83512 862.27405,-249.6687 861.59375,-249.53125 C 860.29905,-249.26966 859.86665,-249.53745 856.15625,-248.71875 C 852.65777,-247.9468 847.31035,-246.33582 846.09375,-245.5 C 844.53085,-245.57745 842.33625,-245.41472 840.40625,-244.90625 C 837.43387,-244.12312 835.58855,-243.67416 833.71875,-243.15625 C 831.84875,-242.63835 832.0521,-242.38897 830.875,-242.0625 C 829.60251,-241.7096 829.17795,-241.95541 825.53125,-240.875 C 822.10657,-239.86037 816.88185,-237.94183 815.65625,-237.03125 C 814.11747,-237.01851 811.93645,-236.75903 810.03125,-236.15625 C 807.10027,-235.22891 805.2809,-234.69783 803.4375,-234.09375 C 802.81071,-233.88837 802.44585,-233.70117 802.15625,-233.5625 C 801.74867,-233.34889 801.50295,-233.15375 800.84375,-232.9375 C 799.58925,-232.52596 799.1576,-232.74846 795.5625,-231.5 C 792.17261,-230.32283 786.96755,-228.2863 785.78125,-227.34375 C 784.25737,-227.28408 782.1312,-226.94888 780.25,-226.28125 C 777.35261,-225.25296 775.55095,-224.60577 773.71875,-223.96875 C 771.88655,-223.33174 772.0909,-223.12021 770.9375,-222.71875 C 769.69071,-222.28479 769.27395,-222.51903 765.71875,-221.15625 C 762.38005,-219.87645 757.23165,-217.6737 756.03125,-216.6875 C 754.52407,-216.57981 752.39555,-216.1887 750.53125,-215.46875 C 747.66307,-214.36115 745.90735,-213.68719 744.09375,-213 C 743.47705,-212.76637 743.0973,-212.55797 742.8125,-212.40625 C 742.81251,-212.40625 742.8125,-212.37673 742.8125,-212.375 L 734.8125,-209.1875 L 736.625,-194.46875 C 736.36701,-194.52956 742.8125,-191.15625 742.8125,-191.15625 C 743.03891,-191.30093 743.26145,-191.42886 743.53125,-191.53125 C 744.61177,-191.94123 745.70285,-191.74702 749.53125,-193.21875 C 753.35977,-194.69049 754.7553,-195.22373 755.4375,-195.625 C 756.11711,-196.02478 757.04925,-196.50437 757.65625,-197.15625 C 759.48317,-197.294 761.22705,-197.64948 762.59375,-198.15625 C 765.56175,-199.25677 767.4691,-199.96244 769.375,-200.625 C 771.28081,-201.28754 771.72915,-202.03987 772.78125,-202.40625 C 773.87287,-202.78636 774.97635,-202.57163 778.84375,-203.9375 C 782.71115,-205.30336 784.1269,-205.76458 784.8125,-206.15625 C 785.51361,-206.55677 786.5133,-207.08923 787.125,-207.75 C 789.09581,-207.80466 790.94195,-208.13463 792.40625,-208.625 C 795.40777,-209.63008 797.3324,-210.24671 799.25,-210.875 C 800.78861,-211.3791 801.42415,-211.92177 802.15625,-212.3125 C 802.38647,-212.44681 802.63215,-212.56623 802.90625,-212.65625 C 804.00457,-213.01673 805.0877,-212.73762 809,-213.96875 C 812.91231,-215.19988 814.366,-215.6417 815.0625,-216 C 815.75641,-216.35697 816.6926,-216.79261 817.3125,-217.40625 C 819.17771,-217.42891 820.94835,-217.67308 822.34375,-218.09375 C 825.37415,-219.00729 827.33615,-219.52385 829.28125,-220.0625 C 831.22637,-220.60114 831.70745,-221.32702 832.78125,-221.625 C 833.89527,-221.93415 835.00125,-221.61761 838.96875,-222.65625 C 842.93625,-223.69488 844.38625,-224.08898 845.09375,-224.40625 C 845.82855,-224.73584 846.90765,-225.15997 847.53125,-225.78125 C 849.52907,-225.66525 851.3887,-225.80134 852.875,-226.15625 C 855.95311,-226.89125 857.9584,-227.25719 859.9375,-227.65625 C 861.52541,-227.97643 862.1818,-228.4468 862.9375,-228.75 C 863.17501,-228.8568 863.4044,-228.94276 863.6875,-229 C 864.82091,-229.22919 865.99215,-228.79107 870.03125,-229.5 C 874.07067,-230.20893 875.5315,-230.42709 876.25,-230.6875 C 876.96581,-230.94694 877.95435,-231.25474 878.59375,-231.78125 C 880.51795,-231.54176 882.34165,-231.55672 883.78125,-231.78125 C 886.90767,-232.26887 888.9358,-232.48192 890.9375,-232.75 C 892.93921,-233.01807 893.42625,-233.69514 894.53125,-233.84375 C 895.67767,-233.99793 896.8071,-233.54218 900.875,-234.0625 C 904.94281,-234.58282 906.43525,-234.75823 907.15625,-235 C 907.89337,-235.24714 908.95435,-235.58623 909.59375,-236.125 C 911.64375,-235.78947 913.56745,-235.72704 915.09375,-235.90625 C 918.23595,-236.27521 920.27375,-236.46561 922.28125,-236.6875 C 923.89207,-236.86552 924.5459,-237.2957 925.3125,-237.53125 C 925.55341,-237.61677 925.80655,-237.68685 926.09375,-237.71875 C 927.24345,-237.84647 928.39505,-237.3721 932.46875,-237.84375 C 936.54245,-238.3154 938.0278,-238.45435 938.75,-238.6875 C 939.46941,-238.91977 940.45025,-239.16096 941.09375,-239.65625 C 943.03005,-239.32279 944.8638,-239.25201 946.3125,-239.40625 C 949.45851,-239.7412 951.49,-239.92484 953.5,-240.125 C 955.50991,-240.32514 955.98415,-240.95139 957.09375,-241.0625 C 958.24485,-241.17778 959.39025,-240.69744 963.46875,-241.125 C 967.54725,-241.55256 969.05765,-241.68709 969.78125,-241.90625 C 970.52047,-242.13011 971.57685,-242.4195 972.21875,-242.9375 C 974.27575,-242.53883 976.2206,-242.4441 977.75,-242.59375 C 980.89871,-242.90185 982.9258,-243.067 984.9375,-243.25 C 986.55151,-243.39682 987.20055,-243.81055 987.96875,-244.03125 C 988.21005,-244.11211 988.4623,-244.16116 988.75,-244.1875 C 989.90211,-244.29295 991.0429,-243.79475 995.125,-244.1875 C 999.20711,-244.58025 1000.7139,-244.71834 1001.4375,-244.9375 C 1002.1584,-245.15583 1003.1371,-245.3852 1003.7812,-245.875 C 1005.7193,-245.52501 1007.5501,-245.42062 1009,-245.5625 C 1012.1487,-245.8706 1014.1758,-246.03575 1016.1875,-246.21875 C 1018.1991,-246.40174 1018.7017,-247.05677 1019.8125,-247.15625 C 1020.9648,-247.25948 1022.1047,-246.77142 1026.1875,-247.15625 C 1030.2704,-247.54107 1031.7762,-247.65725 1032.5,-247.875 C 1033.2393,-248.09743 1034.2956,-248.38949 1034.9375,-248.90625 C 1036.9949,-248.50448 1038.9404,-248.40292 1040.4688,-248.5625 C 1043.6153,-248.89102 1045.6458,-249.0852 1047.6562,-249.28125 C 1049.2692,-249.43854 1049.9219,-249.91273 1050.6875,-250.15625 C 1050.9282,-250.24429 1051.1507,-250.27762 1051.4375,-250.3125 C 1052.5858,-250.4522 1053.7542,-249.97259 1057.8125,-250.5625 C 1061.8708,-251.15242 1063.3743,-251.33964 1064.0938,-251.59375 C 1064.8104,-251.84691 1065.7684,-252.15182 1066.4062,-252.6875 C 1068.3259,-252.47556 1070.1262,-252.53609 1071.5625,-252.78125 C 1074.6816,-253.31365 1076.6741,-253.70986 1078.6562,-254.09375 C 1080.6383,-254.47762 1081.1305,-255.1334 1082.2188,-255.375 C 1083.3475,-255.62566 1084.489,-255.25871 1088.4688,-256.25 C 1092.4483,-257.24127 1093.8983,-257.6693 1094.5938,-258.03125 C 1095.316,-258.40725 1096.3555,-258.90183 1096.9688,-259.5625 C 1098.9317,-259.57454 1100.7625,-259.85355 1102.1875,-260.40625 C 1105.1387,-261.55085 1107.0607,-262.27567 1108.875,-263.15625 C 1110.3307,-263.86277 1111.1941,-264.85828 1111.4062,-265.15625 C 1111.6185,-265.4542 1111.5051,-265.8848 1111.5312,-265.90625 C 1111.5742,-265.94148 1111.8716,-266.00028 1112.0312,-266.34375 C 1112.8902,-268.19082 1114.3544,-271.97139 1114.4688,-272.65625 C 1114.5825,-273.33839 1114.6368,-274.00902 1114.6875,-274.40625 C 1114.7169,-274.63575 1114.5404,-275.28515 1114.5625,-275.34375 C 1114.5934,-275.42579 1114.8508,-275.59432 1114.9062,-275.84375 C 1115.1725,-277.04206 1114.9953,-278.05111 1114.7812,-279.46875 C 1114.5673,-280.88638 1113.8096,-284.08338 1113.1562,-284.9375 C 1112.4973,-285.79922 1111.9314,-285.94801 1111.4062,-285.9375 z"
+         transform="translate(8.0045714e-2,-3.125e-2)" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter7578"
+       x="-0.08160872"
+       width="1.1632174"
+       y="-0.22659944"
+       height="1.4531989">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2.437399"
+         id="feGaussianBlur7580" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7594"
+       x="-0.040804356"
+       width="1.0816087"
+       y="-0.11329972"
+       height="1.2265995">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.2186995"
+         id="feGaussianBlur7596" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath7606">
+      <path
+         id="path7608"
+         d="M 1049.205,-282.26672 L 1049.1152,-282.25891 C 1047.7278,-281.37446 1042.5119,-280.65171 1042.4862,-272.73547 C 1042.462,-265.31022 1057.4991,-255.64401 1059.6425,-254.64172 C 1061.3727,-253.83263 1063.2341,-253.23296 1065.0488,-252.92297 L 1066.4862,-252.70422 C 1068.4059,-252.49228 1070.2062,-252.55281 1071.6425,-252.79797 C 1074.7616,-253.33037 1076.7541,-253.72658 1078.7362,-254.11047 C 1080.7183,-254.49434 1081.2105,-255.15012 1082.2988,-255.39172 C 1083.4275,-255.64238 1084.569,-255.27543 1088.5488,-256.26672 C 1092.5283,-257.258 1093.9782,-257.68602 1094.6738,-258.04797 C 1095.396,-258.42398 1096.4355,-258.91855 1097.0488,-259.57922 C 1099.0117,-259.59127 1100.8425,-259.87027 1102.2675,-260.42297 C 1105.2187,-261.56758 1107.1407,-262.29239 1108.955,-263.17297 C 1110.4107,-263.8795 1111.2741,-264.875 1111.4862,-265.17297 C 1111.6985,-265.47093 1111.5852,-265.90152 1111.6112,-265.92297 C 1111.6542,-265.95821 1111.9517,-266.017 1112.1112,-266.36047 C 1112.9702,-268.20755 1114.4344,-271.98811 1114.5488,-272.67297 C 1114.6625,-273.35512 1114.7168,-274.02574 1114.7675,-274.42297 C 1114.7969,-274.65248 1114.6204,-275.30187 1114.6425,-275.36047 C 1114.6734,-275.44252 1114.9308,-275.61104 1114.9862,-275.86047 C 1115.2525,-277.05879 1115.0754,-278.06783 1114.8612,-279.48547 C 1114.6473,-280.90311 1113.8896,-284.1001 1113.2362,-284.95422 C 1112.8168,-285.50279 1112.4369,-285.74672 1112.08,-285.86047 C 1112.0129,-285.87776 1111.9561,-285.90721 1111.8925,-285.92297 C 1111.8715,-285.92695 1111.8508,-285.91983 1111.83,-285.92297 C 1111.5184,-285.99847 1111.2215,-286.08164 1110.6738,-286.14172 C 1109.6883,-286.24984 1108.2491,-286.40112 1106.705,-286.39172 C 1106.1903,-286.38859 1105.6679,-286.34408 1105.1425,-286.29797 C 1101.5836,-285.98569 1096.1327,-285.30689 1094.9238,-284.67297 C 1093.2907,-285.00699 1090.9756,-285.2852 1088.9862,-285.14172 C 1085.9222,-284.92075 1084.0185,-284.79953 1082.08,-284.67297 C 1080.1416,-284.54642 1080.3939,-284.28433 1079.1738,-284.20422 C 1077.8547,-284.11762 1077.3869,-284.42747 1073.6112,-284.11047 C 1070.0655,-283.81275 1064.6306,-283.1173 1063.3925,-282.48547 C 1061.7591,-282.81998 1059.4466,-283.09786 1057.455,-282.95422 C 1054.3908,-282.73324 1052.4872,-282.58078 1050.5488,-282.45422 C 1049.8896,-282.41119 1049.5064,-282.33029 1049.205,-282.26672 z"
+         style="opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter7610"
+       x="-0.021942979"
+       width="1.0438859"
+       y="-0.10017137"
+       height="1.2003427">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.57530213"
+         id="feGaussianBlur7612" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath7616">
+      <path
+         id="path7618"
+         d="M 205.47016,-408.97318 L 205.38003,-408.97164 C 203.9344,-408.18598 198.68082,-407.82829 198.10378,-399.93307 C 197.56244,-392.52754 211.88973,-381.83741 213.95811,-380.68826 C 215.62775,-379.76062 217.44286,-379.03275 219.23156,-378.59711 L 220.65023,-378.27877 C 222.5505,-377.93363 224.35065,-377.86862 225.80054,-378.01314 C 228.94914,-378.32698 230.9644,-378.58345 232.96843,-378.82834 C 234.97245,-379.07322 235.50913,-379.69312 236.61162,-379.85833 C 237.75504,-380.02976 238.86821,-379.58419 242.90739,-380.29586 C 246.94627,-381.00755 248.42246,-381.33354 249.14158,-381.64616 C 249.88822,-381.97095 250.95964,-382.39191 251.61747,-383.00826 C 253.57644,-382.88355 255.42223,-383.03435 256.88227,-383.48645 C 259.90603,-384.42272 261.87384,-385.01189 263.74507,-385.76396 C 265.24645,-386.36738 266.17709,-387.30032 266.40943,-387.58279 C 266.64197,-387.86524 266.55894,-388.30268 266.58637,-388.32227 C 266.63172,-388.35443 266.93259,-388.39235 267.11563,-388.72388 C 268.1012,-390.50664 269.82518,-394.17603 269.987,-394.85126 C 270.14794,-395.52383 270.24882,-396.18904 270.32707,-396.58177 C 270.37238,-396.80868 270.24154,-397.46878 270.26767,-397.5257 C 270.30421,-397.6054 270.57272,-397.75558 270.64536,-398.00055 C 270.99449,-399.17741 270.8881,-400.19633 270.77316,-401.62545 C 270.65853,-403.05454 270.12535,-406.29655 269.53303,-407.1941 C 269.15286,-407.77056 268.79088,-408.04035 268.44277,-408.17869 C 268.37703,-408.20061 268.32242,-408.23394 268.26007,-408.2541 C 268.2394,-408.25953 268.21826,-408.25387 268.19773,-408.25845 C 267.89214,-408.35547 267.60176,-408.45912 267.05957,-408.5572 C 266.084,-408.7337 264.65883,-408.98486 263.11782,-409.08304 C 262.60416,-409.11577 262.07992,-409.10775 261.55259,-409.09835 C 257.98058,-409.03472 252.49564,-408.73725 251.24552,-408.18907 C 249.63965,-408.63604 247.34955,-409.07483 245.35499,-409.07027 C 242.28304,-409.06325 240.37552,-409.07493 238.43292,-409.0837 C 236.49041,-409.09248 236.72384,-408.81345 235.50112,-408.81852 C 234.1792,-408.82401 233.73411,-409.16569 229.9455,-409.11245 C 226.38768,-409.06243 220.91754,-408.74723 219.63844,-408.20318 C 218.0323,-408.65065 215.74477,-409.08893 213.74801,-409.08436 C 210.67586,-409.07735 208.76626,-409.05786 206.82375,-409.06662 C 206.16316,-409.06961 205.77525,-409.0156 205.47016,-408.97318 z"
+         style="opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+    </clipPath>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7622"
+       id="linearGradient7708"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-19.091883,4.2426407)"
+       x1="774.97668"
+       y1="-211.87105"
+       x2="755.11584"
+       y2="-202.67865" />
+    <mask
+       maskUnits="userSpaceOnUse"
+       id="mask7704">
+      <path
+         style="fill:url(#linearGradient7708);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="M 718.40812,-224.31217 L 751.65812,-168.31217 L 1027.6581,-192.31217 L 1187.1581,-240.56217 L 1120.6581,-323.31217 L 718.40812,-224.31217 z"
+         id="path7706" />
+    </mask>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8430"
+       id="radialGradient7904"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.3324832,0.9022288,-0.9582407,-0.3531242,305.29227,19.909497)"
+       cx="142.95833"
+       cy="107.09234"
+       fx="142.95833"
+       fy="107.09234"
+       r="66.981766" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3317"
+       id="radialGradient7906"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.0036478,-1.0345492e-7,1.7124628e-7,1.6613125,-160.53487,-96.205369)"
+       cx="317.78754"
+       cy="129.65378"
+       fx="317.78754"
+       fy="129.65378"
+       r="47.863216" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8398"
+       id="radialGradient7908"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.0747661,-0.1577957,0.2382425,3.1325183,-550.77432,-65.728909)"
+       cx="325.30847"
+       cy="80.909554"
+       fx="325.30847"
+       fy="80.909554"
+       r="26.937988" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8209">
+      <path
+         sodipodi:nodetypes="czcc"
+         id="path8211"
+         d="M 734.03125,519.49186 C 734.03125,519.49186 750.78638,556.50992 762.73266,573.44581 C 774.67895,590.3817 815.45982,629.49186 815.45982,629.49186 L 816.05699,490.90211"
+         style="opacity:1;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8225">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="10.661912"
+         id="feGaussianBlur8227" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8333">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="7.18"
+         id="feGaussianBlur8335" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8338">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8340"
+         d="M 266.27183,924.57185 C 264.86456,943.37307 265.12693,957.32289 268.35357,973.87513 C 271.58023,990.42751 284.75966,1019.7825 288.68798,1037.0589 C 292.61419,1054.326 291.38211,1075.3686 276.22854,1088.2071 C 260.91093,1101.1846 234.17727,1109.8061 208.39624,1103.9409 C 182.61518,1098.0756 138.84716,1054.7175 119.80605,1033.7126 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 C 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 C 24.38107,839.38658 21.33408,813.84026 0.035334479,788.33044 C 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 C 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 C 61.781367,750.82754 82.366432,776.61828 95.766855,817.45839 C 105.32101,813.54047 114.00462,808.08545 125.95427,808.39719 C 114.65677,766.70139 108.0048,738.48134 89.267014,707.32725 C 142.70898,712.99757 172.92404,787.96657 168.23844,795.28805 C 178.21641,793.04406 187.24409,788.75767 198.67497,789.63638 C 187.426,751.28935 177.62715,712.76848 195.01526,670.98819 C 195.01526,670.98819 243.30204,736.42507 249.40491,756.79397 C 255.50779,777.16287 250.92373,795.49448 250.92373,795.49448 C 250.92373,795.49448 267.8833,826.57978 271.21765,846.58862 C 274.59075,866.82996 267.68496,905.69193 266.27183,924.57185 z"
+         style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8354">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="6.82"
+         id="feGaussianBlur8356" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8359">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8361"
+         d="M 266.27183,924.57185 C 264.86456,943.37307 265.12693,957.32289 268.35357,973.87513 C 271.58023,990.42751 284.75966,1019.7825 288.68798,1037.0589 C 292.61419,1054.326 291.38211,1075.3686 276.22854,1088.2071 C 260.91093,1101.1846 234.17727,1109.8061 208.39624,1103.9409 C 182.61518,1098.0756 138.84716,1054.7175 119.80605,1033.7126 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 C 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 C 24.38107,839.38658 21.33408,813.84026 0.035334479,788.33044 C 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 C 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 C 61.781367,750.82754 82.366432,776.61828 95.766855,817.45839 C 105.32101,813.54047 114.00462,808.08545 125.95427,808.39719 C 114.65677,766.70139 108.0048,738.48134 89.267014,707.32725 C 142.70898,712.99757 172.92404,787.96657 168.23844,795.28805 C 178.21641,793.04406 187.24409,788.75767 198.67497,789.63638 C 187.426,751.28935 177.62715,712.76848 195.01526,670.98819 C 195.01526,670.98819 243.30204,736.42507 249.40491,756.79397 C 255.50779,777.16287 250.92373,795.49448 250.92373,795.49448 C 250.92373,795.49448 267.8833,826.57978 271.21765,846.58862 C 274.59075,866.82996 267.68496,905.69193 266.27183,924.57185 z"
+         style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8379"
+       x="-0.14413793"
+       width="1.288276"
+       y="-0.10278689"
+       height="1.2055738">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="7.389266"
+         id="feGaussianBlur8381" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8392">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8394"
+         d="M 760.16396,935.83377 C 766.95806,954.73656 770.65765,969.13346 772.05426,987.04566 C 773.45088,1004.958 768.27158,1038.8465 769.1538,1057.7018 C 770.03555,1076.547 777.28749,1097.8008 796.49843,1106.6707 C 815.9173,1115.6365 845.81767,1116.882 870.61827,1103.5251 C 895.41887,1090.1681 928.01929,1033.1996 941.59253,1006.2164 C 955.21638,979.13246 980.3536,891.71903 986.25333,856.44781 C 992.15306,821.1766 988.80387,815.14704 981.63585,807.39232 C 984.27615,779.55217 980.13613,752.45689 994.74554,720.20614 C 964.49653,732.03184 957.36325,760.36684 946.42665,785.71122 C 938.42574,734.77829 946.63581,714.43803 949.74554,684.49186 C 920.68078,699.26977 906.88403,731.60588 904.74554,777.349 C 893.82159,776.0448 883.3541,772.91477 871.17411,776.63471 C 870.91007,730.61137 869.71055,699.7453 880.08474,662.42822 C 826.82927,683.45508 817.13746,769.02232 824.03125,775.20614 C 813.14843,775.74114 802.66017,773.90884 791.17411,778.06329 C 791.81303,735.49194 790.91365,693.15468 761.17411,655.20614 C 761.17411,655.20614 730.21605,736.12848 729.74554,758.77757 C 729.27503,781.42666 739.19713,798.94345 739.19713,798.94345 C 739.19713,798.94345 730.62906,835.68396 732.89854,857.17568 C 735.19439,878.91714 753.34144,916.85185 760.16396,935.83377 z"
+         style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8404"
+       x="-0.090268657"
+       width="1.1805373"
+       y="-0.10250848"
+       height="1.205017">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="5.3457272"
+         id="feGaussianBlur8406" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8417">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8419"
+         d="M 760.16396,935.83377 C 766.95806,954.73656 770.65765,969.13346 772.05426,987.04566 C 773.45088,1004.958 768.27158,1038.8465 769.1538,1057.7018 C 770.03555,1076.547 777.28749,1097.8008 796.49843,1106.6707 C 815.9173,1115.6365 845.81767,1116.882 870.61827,1103.5251 C 895.41887,1090.1681 928.01929,1033.1996 941.59253,1006.2164 C 955.21638,979.13246 980.3536,891.71903 986.25333,856.44781 C 992.15306,821.1766 988.80387,815.14704 981.63585,807.39232 C 984.27615,779.55217 980.13613,752.45689 994.74554,720.20614 C 964.49653,732.03184 957.36325,760.36684 946.42665,785.71122 C 938.42574,734.77829 946.63581,714.43803 949.74554,684.49186 C 920.68078,699.26977 906.88403,731.60588 904.74554,777.349 C 893.82159,776.0448 883.3541,772.91477 871.17411,776.63471 C 870.91007,730.61137 869.71055,699.7453 880.08474,662.42822 C 826.82927,683.45508 817.13746,769.02232 824.03125,775.20614 C 813.14843,775.74114 802.66017,773.90884 791.17411,778.06329 C 791.81303,735.49194 790.91365,693.15468 761.17411,655.20614 C 761.17411,655.20614 730.21605,736.12848 729.74554,758.77757 C 729.27503,781.42666 739.19713,798.94345 739.19713,798.94345 C 739.19713,798.94345 730.62906,835.68396 732.89854,857.17568 C 735.19439,878.91714 753.34144,916.85185 760.16396,935.83377 z"
+         style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+    </clipPath>
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Shadow">
+    <path
+       style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter11361);enable-background:new"
+       d="M 304.64285,526.6479 C 294.64285,527.00505 286.42857,529.50504 286.42857,529.50504 L 293.92857,535.57647 L 304.28571,539.1479 L 320.35714,539.50504 L 342.85714,534.1479 L 350.71428,535.21933 L 371.07143,533.07647 L 360.71428,539.86219 C 366.17351,538.83858 378.10757,543.4313 370.35714,545.21933 C 368.61714,545.62075 384.28571,540.57648 384.28571,540.57648 L 386.78571,535.93361 L 390.35714,526.6479 L 401.78571,526.6479 L 419.99999,522.00504 L 423.57143,517.00505 L 407.49999,518.07647 L 395.35714,520.21933 L 380.71428,515.21933 L 310.02218,531.92707 L 304.64285,526.6479 z"
+       id="path10326"
+       sodipodi:nodetypes="cccccccccsccccccccccc"
+       transform="matrix(10.726753,0,0,10.726753,-2882.1235,-4565.4583)"
+       inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_new.png"
+       inkscape:export-xdpi="142.10527"
+       inkscape:export-ydpi="142.10527" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer20"
+     inkscape:label="New Ear">
+    <g
+       style="opacity:1;display:inline;enable-background:new"
+       id="g7882"
+       transform="matrix(0.71084,-0.1937433,0.262963,0.9648058,503.68027,136.48399)">
+      <path
+         sodipodi:nodetypes="czzzzcc"
+         id="path7876"
+         d="M 245.12255,100.05344 C 245.12255,100.05344 197.99444,68.406519 177.9079,64.252501 C 157.86998,60.108538 139.435,60.934923 125.97426,77.859824 C 112.51352,94.784725 113.89687,139.12502 112.43872,164.82937 C 110.98057,190.53372 114.98817,235.00638 130.04332,253.49489 C 145.09848,271.98339 175.92966,267.07991 179.97027,274.90859 C 182.1831,279.19595 245.12255,100.05344 245.12255,100.05344 z"
+         style="opacity:1;fill:url(#radialGradient7904);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <path
+         sodipodi:nodetypes="czzzzzc"
+         id="path7878"
+         d="M 135.37935,82.017807 C 135.37935,82.017807 161.7229,83.95659 173.01242,95.920995 C 184.42736,108.01833 186.74699,117.25251 188.30828,133.65558 C 189.87165,150.08057 187.45871,162.0737 180.49446,169.69292 C 173.53021,177.31214 179.49017,189.27624 154.57841,181.76399 C 129.66665,174.25174 127.54617,153.98101 128.06318,135.45924 C 128.58039,116.93026 135.37935,82.017807 135.37935,82.017807 z"
+         style="opacity:1;fill:url(#radialGradient7906);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <path
+         sodipodi:nodetypes="czccssc"
+         id="path7880"
+         d="M 135.648,81.927211 C 135.648,81.927211 131.00335,98.292286 136.23625,110.49031 C 141.72419,123.28285 163.4605,154.75038 163.4605,165.14596 L 186.11675,160.14596 C 188.65893,153.17952 189.32727,144.3939 188.30425,133.64596 C 186.74296,117.24289 184.43795,108.02455 173.023,95.927211 C 163.36812,85.695164 141.42989,82.552354 135.648,81.927211 z"
+         style="opacity:1;fill:url(#radialGradient7908);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer21"
+     inkscape:label="Rendered2"
+     style="display:inline">
+    <path
+       style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 845.03125,1154.7776 C 840.74554,1155.4919 817.4031,1158.3957 787.17411,1164.7776 C 756.94512,1171.1595 729.86016,1169.7437 651.38803,1182.1072 C 571.53625,1194.688 557.32367,1224.6495 543.26578,1229.1715 C 528.56564,1233.9001 397.88839,1163.349 397.88839,1163.349 L 402.17411,1069.0633 C 402.17411,1069.0633 488.05962,1052.8624 514.31696,1035.4919 C 540.57431,1018.1214 559.89934,985.82588 573.60268,964.06329 C 587.30602,942.3007 606.45982,892.63471 606.45982,892.63471 L 845.03125,1154.7776 z"
+       id="path7917"
+       sodipodi:nodetypes="czzzcczzcc" />
+    <path
+       style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8888);enable-background:accumulate"
+       d="M 332.34019,898.38549 L 299.60838,837.08593 L 261.99104,882.19239 C 264.16779,883.5095 267.76529,861.33636 307.59144,817.77531 L 332.34019,898.38549 z"
+       id="path7919"
+       clip-path="url(#clipPath8658)"
+       sodipodi:nodetypes="ccccc"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:1;fill:url(#linearGradient2841);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8892);enable-background:accumulate"
+       d="M 200.81833,863.03015 L 347.18943,811.41136 L 591.14127,1037.6855 L 349.31075,1177.6927 L 168.29141,1090.0114 L 200.81833,863.03015 z"
+       id="path7923"
+       clip-path="url(#clipPath2833)"
+       sodipodi:nodetypes="cccccc"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 642.88839,640.13471 C 642.88839,640.13471 613.33433,680.70776 595.03125,714.42042 C 576.72816,748.13309 536.41016,840.77736 524.67411,885.49185 C 512.91471,930.29529 462.17411,1009.0633 462.17411,1009.0633 L 538.24554,1027.2776 C 538.24554,1027.2776 550.05266,1014.4542 569.31696,981.20614 C 588.58126,947.95806 629.67411,842.63471 629.67411,842.63471 L 642.88839,640.13471 z"
+       id="path7921"
+       sodipodi:nodetypes="czzcczcc" />
+    <path
+       style="opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8856);enable-background:accumulate"
+       d="M 430.28131,381.94122 C 423.21025,384.76965 194.10007,414.09303 194.10007,414.09303 L 154.46046,773.92607 L 244.65895,866.56568 L 296.98485,752.01438 L 397.45289,565.62246 L 430.28131,381.94122 z"
+       id="path7925"
+       sodipodi:nodetypes="ccccccc"
+       clip-path="url(#clipPath3665)"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 969.67051,1164.0346 C 969.67051,1164.0346 992.92679,1175.4283 1005.7383,1184.5107 C 1018.4357,1193.5122 1035.2107,1209.1598 1047.4307,1221.8712 C 1059.7362,1234.6714 1067.5434,1244.4699 1088.9634,1246.032 C 1110.3956,1247.5949 1142.2458,1237.2444 1162.2594,1221.3678 C 1182.2729,1205.4912 1207.9063,1152.135 1207.9063,1152.135 L 1080.7455,1009.0633"
+       id="path7927"
+       sodipodi:nodetypes="czzzzcc" />
+    <path
+       style="opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8860);enable-background:accumulate"
+       d="M 331.34019,641.50471 L 216.17367,835.36467 L 260.2153,925.96265 L 357.79603,732.21539 L 331.34019,641.50471 z"
+       id="path7929"
+       clip-path="url(#clipPath8642)"
+       sodipodi:nodetypes="ccccc"
+       transform="translate(276,136)" />
+    <g
+       style="opacity:1;display:inline;enable-background:new"
+       id="g7931"
+       transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+       inkscape:transform-center-x="-347.89063"
+       inkscape:transform-center-y="-28.255779">
+      <path
+         style="opacity:1;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+         d="M 1049.205,-282.26672 L 1049.1152,-282.25891 C 1047.7278,-281.37446 1042.5119,-280.65171 1042.4862,-272.73547 C 1042.462,-265.31022 1057.4991,-255.64401 1059.6425,-254.64172 C 1061.3727,-253.83263 1063.2341,-253.23296 1065.0488,-252.92297 L 1066.4862,-252.70422 C 1068.4059,-252.49228 1070.2062,-252.55281 1071.6425,-252.79797 C 1074.7616,-253.33037 1076.7541,-253.72658 1078.7362,-254.11047 C 1080.7183,-254.49434 1081.2105,-255.15012 1082.2988,-255.39172 C 1083.4275,-255.64238 1084.569,-255.27543 1088.5488,-256.26672 C 1092.5283,-257.258 1093.9782,-257.68602 1094.6738,-258.04797 C 1095.396,-258.42398 1096.4355,-258.91855 1097.0488,-259.57922 C 1099.0117,-259.59127 1100.8425,-259.87027 1102.2675,-260.42297 C 1105.2187,-261.56758 1107.1407,-262.29239 1108.955,-263.17297 C 1110.4107,-263.8795 1111.2741,-264.875 1111.4862,-265.17297 C 1111.6985,-265.47093 1111.5852,-265.90152 1111.6112,-265.92297 C 1111.6542,-265.95821 1111.9517,-266.017 1112.1112,-266.36047 C 1112.9702,-268.20755 1114.4344,-271.98811 1114.5488,-272.67297 C 1114.6625,-273.35512 1114.7168,-274.02574 1114.7675,-274.42297 C 1114.7969,-274.65248 1114.6204,-275.30187 1114.6425,-275.36047 C 1114.6734,-275.44252 1114.9308,-275.61104 1114.9862,-275.86047 C 1115.2525,-277.05879 1115.0754,-278.06783 1114.8612,-279.48547 C 1114.6473,-280.90311 1113.8896,-284.1001 1113.2362,-284.95422 C 1112.8168,-285.50279 1112.4369,-285.74672 1112.08,-285.86047 C 1112.0129,-285.87776 1111.9561,-285.90721 1111.8925,-285.92297 C 1111.8715,-285.92695 1111.8508,-285.91983 1111.83,-285.92297 C 1111.5184,-285.99847 1111.2215,-286.08164 1110.6738,-286.14172 C 1109.6883,-286.24984 1108.2491,-286.40112 1106.705,-286.39172 C 1106.1903,-286.38859 1105.6679,-286.34408 1105.1425,-286.29797 C 1101.5836,-285.98569 1096.1327,-285.30689 1094.9238,-284.67297 C 1093.2907,-285.00699 1090.9756,-285.2852 1088.9862,-285.14172 C 1085.9222,-284.92075 1084.0185,-284.79953 1082.08,-284.67297 C 1080.1416,-284.54642 1080.3939,-284.28433 1079.1738,-284.20422 C 1077.8547,-284.11762 1077.3869,-284.42747 1073.6112,-284.11047 C 1070.0655,-283.81275 1064.6306,-283.1173 1063.3925,-282.48547 C 1061.7591,-282.81998 1059.4466,-283.09786 1057.455,-282.95422 C 1054.3908,-282.73324 1052.4872,-282.58078 1050.5488,-282.45422 C 1049.8896,-282.41119 1049.5064,-282.33029 1049.205,-282.26672 z"
+         id="path7933" />
+      <g
+         clip-path="url(#clipPath7616)"
+         style="display:inline;filter:url(#filter7610);enable-background:new"
+         id="g7935"
+         transform="matrix(0.9975712,-6.9654277e-2,6.9654277e-2,0.9975712,872.72062,140.02502)">
+        <path
+           sodipodi:nodetypes="ccssscsssscscsscsssccscssccsscssscc"
+           id="path7937"
+           d="M 229.94262,-409.12268 C 226.38481,-409.07267 220.91842,-408.76259 219.63928,-408.21854 C 218.03319,-408.66601 215.73612,-409.09985 213.73933,-409.09528 C 210.66734,-409.08826 208.77464,-409.08651 206.83206,-409.09528 C 206.17159,-409.09827 205.78447,-409.02811 205.47939,-408.98569 C 205.47939,-408.98569 205.47939,-407.88976 205.47939,-407.88976 C 205.59911,-408.06923 205.87191,-408.58022 206.42914,-408.65691 C 207.17672,-408.7598 211.59842,-408.80814 213.73933,-408.76651 C 215.51393,-408.73198 218.19456,-408.49224 220.12854,-407.80756 C 220.44994,-407.69378 220.74779,-407.53378 221.02073,-407.39659 C 222.98415,-406.40966 228.96409,-403.09505 228.96409,-403.09505 C 228.96409,-403.09505 222.33134,-407.04273 221.48122,-407.53358 C 221.27791,-407.65097 220.90658,-407.79127 220.44513,-407.94456 C 221.66576,-408.39235 225.5211,-408.56427 228.27336,-408.65691 C 231.29786,-408.75873 231.62112,-408.7465 233.68405,-408.46512 C 235.81336,-408.17469 237.02256,-407.86236 237.02256,-407.86236 C 237.02255,-407.86236 236.9442,-408.50354 238.05865,-408.65691 C 238.80622,-408.7598 243.22794,-408.80814 245.36884,-408.76651 C 247.43834,-408.72625 250.73489,-408.35935 252.65024,-407.39659 C 253.65356,-406.89226 255.68588,-405.82796 257.44559,-404.86088 L 257.5412,-404.88031 C 257.5412,-404.88031 253.96086,-407.04273 253.11073,-407.53358 C 252.90742,-407.65097 252.5361,-407.79127 252.07464,-407.94456 C 253.29526,-408.39235 257.12183,-408.56427 259.87409,-408.65691 C 262.89859,-408.75873 263.22184,-408.7465 265.28478,-408.46512 C 267.23794,-408.19872 268.2977,-407.93506 268.47939,-407.88976 C 268.47939,-407.88976 268.4523,-408.20122 268.4523,-408.20122 C 268.04327,-408.33767 267.73806,-408.43457 267.05192,-408.5587 C 265.75111,-408.79403 263.6528,-409.16026 261.54335,-409.12268 C 257.9714,-409.05904 252.49007,-408.76672 251.24001,-408.21854 C 249.63418,-408.66549 247.36339,-409.09984 245.36884,-409.09528 C 242.29685,-409.08826 240.37536,-409.08651 238.43279,-409.09528 C 236.49023,-409.10406 236.72011,-408.81621 235.49721,-408.8213 C 234.1753,-408.8268 233.73109,-409.17593 229.94262,-409.12268 C 229.94262,-409.12268 229.94262,-409.12268 229.94262,-409.12268"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+        <path
+           id="path7939"
+           d="M 206.1989,-407.47878 C 208.11911,-406.66172 210.77605,-405.28595 212.35787,-404.08139 C 213.93971,-402.87683 215.26544,-402.30771 217.91246,-400.16344 C 218.79803,-399.44606 219.66111,-398.81359 220.50439,-398.2417 L 221.04496,-398.43181 C 220.33173,-398.9152 219.5772,-399.45212 218.77587,-400.05384 C 215.95364,-402.17305 215.14932,-402.86357 212.7608,-404.32798 C 210.37226,-405.79238 208.66132,-406.69374 206.1989,-407.47878 C 206.1989,-407.47878 206.1989,-407.47878 206.1989,-407.47878"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+           sodipodi:nodetypes="cssccsscc" />
+        <path
+           id="path7941"
+           d="M 237.79963,-407.47878 C 239.71984,-406.66172 242.40557,-405.28595 243.98738,-404.08139 C 244.80045,-403.46223 245.54587,-403.01097 246.43784,-402.42738 L 247.08684,-402.54404 C 246.28853,-403.12041 245.51507,-403.63839 244.39031,-404.32798 C 242.00177,-405.79238 240.26205,-406.69374 237.79963,-407.47878 C 237.79963,-407.47878 237.79963,-407.47878 237.79963,-407.47878"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+           sodipodi:nodetypes="csccscc" />
+      </g>
+      <g
+         clip-path="url(#clipPath7606)"
+         id="g7943">
+        <path
+           style="opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7578);enable-background:new"
+           d="M 1056.25,-278.80481 C 1060.3946,-280.28358 1066.25,-275.67981 1066.25,-275.67981 C 1067.149,-275.39889 1068.9751,-276.57428 1068.8743,-277.36595 C 1068.8743,-277.36595 1067.324,-279.22657 1068.5,-280.30481 C 1069.676,-281.38305 1073.796,-278.79743 1076,-278.67981 C 1078.204,-278.56219 1081.5621,-278.90922 1083,-279.42981 C 1084.4379,-279.9504 1084.1129,-280.8544 1085.625,-281.17981 C 1087.1371,-281.50522 1090.7439,-280.14227 1092.6855,-280.01098 C 1094.6271,-279.87969 1097.3336,-279.67671 1098.5,-280.17981 C 1099.6664,-280.68291 1098.6782,-281.33902 1100.375,-282.05481 C 1102.0718,-282.7706 1108.1352,-283.01143 1110,-282.17981 C 1111.8648,-281.34819 1111.8099,-281.66061 1112.625,-279.17981 C 1113.4401,-276.69901 1120.0648,-274.01696 1111.5,-265.80481 C 1102.9352,-257.59266 1052.1221,-252.01887 1045.875,-263.05481 C 1039.6279,-274.09075 1052.1054,-277.32604 1056.25,-278.80481 z"
+           id="path7945"
+           sodipodi:nodetypes="czzzzzzzzzzzzzz" />
+        <path
+           style="opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7594);enable-background:new"
+           d="M 1058.5,-275.42981 C 1062.6446,-276.90858 1068.5,-272.30481 1068.5,-272.30481 C 1069.399,-272.02389 1071.2251,-273.19928 1071.1243,-273.99095 C 1071.1243,-273.99095 1069.574,-275.85157 1070.75,-276.92981 C 1071.926,-278.00805 1076.046,-275.42243 1078.25,-275.30481 C 1080.454,-275.18719 1083.8121,-275.53422 1085.25,-276.05481 C 1086.6879,-276.5754 1086.3629,-277.4794 1087.875,-277.80481 C 1089.3871,-278.13022 1092.9939,-276.76727 1094.9355,-276.63598 C 1096.8771,-276.50469 1099.5836,-276.30171 1100.75,-276.80481 C 1101.9164,-277.30791 1100.9282,-277.96402 1102.625,-278.67981 C 1104.3218,-279.3956 1110.3852,-279.63643 1112.25,-278.80481 C 1114.1148,-277.97319 1114.0599,-278.28561 1114.875,-275.80481 C 1115.6901,-273.32401 1122.3148,-270.64196 1113.75,-262.42981 C 1105.1852,-254.21766 1054.3721,-248.64387 1048.125,-259.67981 C 1041.8779,-270.71575 1054.3554,-273.95104 1058.5,-275.42981 z"
+           id="path7947"
+           sodipodi:nodetypes="czzzzzzzzzzzzzz" />
+      </g>
+    </g>
+    <path
+       style="opacity:1;fill:#101414;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 628.24553,347.99185 C 624.4411,322.72762 611.43581,297.35383 611.08873,272.46662 C 610.90247,259.1111 614.36158,245.89571 624.84426,232.91257 C 661.19128,167.61674 741.78517,148.21789 810.77892,141.44715 C 897.70131,130.43035 995.69159,159.38722 1044.1503,236.84843 C 1098.2743,312.58173 1100.825,409.38755 1124.7623,496.37638 C 1154.2001,623.50398 1179.5414,752.59052 1185.1545,883.22673 C 1182.0911,961.40858 1176.7282,1048.4109 1124.6513,1111.3609 C 1076.6248,1161.7183 1001.8649,1161.4139 937.58145,1170.3632 C 847.02606,1175.0182 753.22992,1154.2174 675.79755,1106.165 C 611.02191,1068.225 580.06736,992.68633 578.51815,920.14538 C 570.12898,840.27022 604.90967,766.33687 630.13855,692.98577 C 637.60916,610.2247 639.55141,526.73802 639.79189,443.60093 C 638.95507,411.40549 632.70236,379.7836 628.24553,347.99185 z"
+       id="path7949"
+       sodipodi:nodetypes="cscccccccccccc" />
+    <path
+       style="opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8940);enable-background:accumulate"
+       d="M 311.83409,415.43155 L 321.73359,537.05392 L 261.62951,673.52553 L 277.18586,848.1809 C 292.79912,910.0601 309.37131,946.84995 351.56201,965.23473 C 355.88112,928.99475 312.95049,822.27485 312.31937,776.11489 C 311.68792,729.93044 323.14971,667.50703 342.99704,617.81842 C 363.04539,567.62654 379.89378,572.972 385.12193,525.22549 C 390.35008,477.47898 367.69553,375.83357 367.69553,375.83357 L 311.83409,415.43155 z"
+       id="path7951"
+       sodipodi:nodetypes="ccccczzzcc"
+       clip-path="url(#clipPath8616)"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:1;fill:url(#linearGradient8970);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 1010.0312,655.49186 C 1010.0312,655.49186 1026.7864,692.50992 1038.7327,709.44581 C 1050.6789,726.3817 1091.4598,765.49186 1091.4598,765.49186 L 1144.057,637.90211"
+       id="path7953"
+       sodipodi:nodetypes="czcc" />
+    <path
+       style="opacity:0.07999998;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8822);enable-background:accumulate"
+       d="M 730.31998,536.56864 C 730.31998,545.05392 772.86772,595.03667 772.86772,595.03667 L 785.47431,566.26713 L 730.31998,536.56864 z"
+       id="path7955"
+       sodipodi:nodetypes="cccc"
+       clip-path="url(#clipPath8209)"
+       transform="translate(276,136)" />
+    <g
+       transform="translate(450.03125,73.843964)"
+       style="opacity:1;display:inline;enable-background:new"
+       id="g7957"
+       clip-path="url(#clipPath3998)">
+      <g
+         transform="translate(-174.03125,62.156036)"
+         style="filter:url(#filter3677)"
+         id="g7959">
+        <g
+           id="g7961"
+           style="filter:url(#filter3785)">
+          <path
+             sodipodi:nodetypes="czzzzzzzzzz"
+             id="path7963"
+             d="M 425.88244,476.99186 C 436.68787,475.5132 450.62645,480.34637 470.5253,480.20614 C 490.42415,480.06591 527.97852,463.29492 552.66815,463.06328 C 577.35778,462.83164 615.41985,475.34734 631.95387,478.06328 C 648.48789,480.77922 654.80219,477.90476 659.45386,485.92043 C 664.10553,493.9361 661.38057,496.66767 649.09672,506.63472 C 636.81287,516.60177 608.30704,519.27104 583.02529,519.49186 C 557.74295,519.71268 512.644,526.57038 487.66815,523.42042 C 462.6923,520.27046 430.73059,515.59775 418.73958,505.56328 C 406.74857,495.52881 398.88874,488.83146 401.23958,481.63471 C 403.59042,474.43796 415.07701,478.47052 425.88244,476.99186 z"
+             style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <rect
+             y="412.60312"
+             x="343.6539"
+             height="181.01935"
+             width="381.83765"
+             id="rect7965"
+             style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+        </g>
+        <g
+           id="g7967"
+           style="filter:url(#filter3785)">
+          <path
+             sodipodi:nodetypes="czzzcc"
+             id="path7969"
+             d="M 687.14286,452.36218 C 676.68117,462.07661 600.16326,471.36732 586.42857,481.6479 C 572.69388,491.92848 571.67605,494.53616 574.28571,501.6479 C 576.89537,508.75964 580.83098,511.05362 600,510.21932 C 619.16902,509.38502 698.57143,482.5976 698.57143,488.79075 L 687.14286,452.36218 z"
+             style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+             transform="translate(174.03125,-62.156036)" />
+          <rect
+             y="344.82138"
+             x="702.86414"
+             height="162.63455"
+             width="207.8894"
+             id="rect7971"
+             style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+        </g>
+      </g>
+      <g
+         transform="translate(-174.03125,62.156036)"
+         style="opacity:0.18000004;display:inline;enable-background:new"
+         id="g7973">
+        <g
+           id="g7975"
+           style="filter:url(#filter3785)">
+          <path
+             sodipodi:nodetypes="czzzzzzzzzz"
+             id="path7977"
+             d="M 425.88244,476.99186 C 436.68787,475.5132 450.62645,480.34637 470.5253,480.20614 C 490.42415,480.06591 527.97852,463.29492 552.66815,463.06328 C 577.35778,462.83164 615.41985,475.34734 631.95387,478.06328 C 648.48789,480.77922 654.80219,477.90476 659.45386,485.92043 C 664.10553,493.9361 661.38057,496.66767 649.09672,506.63472 C 636.81287,516.60177 608.30704,519.27104 583.02529,519.49186 C 557.74295,519.71268 512.644,526.57038 487.66815,523.42042 C 462.6923,520.27046 430.73059,515.59775 418.73958,505.56328 C 406.74857,495.52881 398.88874,488.83146 401.23958,481.63471 C 403.59042,474.43796 415.07701,478.47052 425.88244,476.99186 z"
+             style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <rect
+             y="412.60312"
+             x="343.6539"
+             height="181.01935"
+             width="381.83765"
+             id="rect7979"
+             style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+        </g>
+        <g
+           id="g7981"
+           style="filter:url(#filter3785)">
+          <path
+             sodipodi:nodetypes="czzzcc"
+             id="path7983"
+             d="M 687.14286,452.36218 C 676.68117,462.07661 600.16326,471.36732 586.42857,481.6479 C 572.69388,491.92848 571.67605,494.53616 574.28571,501.6479 C 576.89537,508.75964 580.83098,511.05362 600,510.21932 C 619.16902,509.38502 698.57143,482.5976 698.57143,488.79075 L 687.14286,452.36218 z"
+             style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+             transform="translate(174.03125,-62.156036)" />
+          <rect
+             y="344.82138"
+             x="702.86414"
+             height="162.63455"
+             width="207.8894"
+             id="rect7985"
+             style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+        </g>
+      </g>
+    </g>
+    <path
+       style="opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8802);enable-background:accumulate"
+       d="M 582.65599,-7.4183011 L 695.79307,78.848726 L 804.68752,337.64981 L 842.87128,545.5392 L 963.07944,637.46308 C 963.07944,637.46308 950.35151,350.37773 943.28044,323.50767 C 936.20938,296.63761 793.37381,-69.643698 793.37381,-69.643698 L 582.65599,-7.4183011 z"
+       id="path7987"
+       clip-path="url(#clipPath8604)"
+       sodipodi:nodetypes="cccccscc"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:1;fill:url(#linearGradient8958);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 964.13839,239.599 C 964.13839,239.599 972.81571,250.49562 988.24554,251.56328 C 1003.6754,252.63094 1037.9672,211.61061 1058.4241,199.42043 C 1078.9034,187.2169 1105.4705,172.81818 1122.3527,179.06329 C 1139.2348,185.30839 1144.5105,205.49938 1150.2098,227.099 C 1155.9092,248.69861 1156.9284,288.91289 1147.5313,319.95615 C 1138.1341,350.9994 1097.028,393.0599 1082.1741,423.349 C 1067.3202,453.6381 1070.567,463.17043 1070.567,463.17043"
+       id="path7989"
+       sodipodi:nodetypes="czzzzzzc" />
+    <path
+       style="opacity:1;fill:url(#radialGradient3315);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+       d="M 1124.4955,207.63471 C 1108.6027,206.74185 1074.7767,219.74054 1058.4241,231.92043 C 1041.9855,244.16433 1029.2032,256.03483 1029.1384,284.06328 C 1029.0732,312.26932 1042.2575,323.13969 1058.2455,331.02757 C 1074.2335,338.91546 1091.9317,338.14685 1110.2098,319.24186 C 1128.488,300.33686 1124.4955,207.63471 1124.4955,207.63471 z"
+       id="path7991"
+       sodipodi:nodetypes="czzzzc" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.75;fill:url(#radialGradient3543);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4120);enable-background:accumulate"
+       id="path7993"
+       sodipodi:cx="385"
+       sodipodi:cy="237.00504"
+       sodipodi:rx="86.428574"
+       sodipodi:ry="73.928574"
+       d="M 471.42857,237.00504 A 86.428574,73.928574 0 1 1 298.57143,237.00504 A 86.428574,73.928574 0 1 1 471.42857,237.00504 z"
+       transform="matrix(0.9434749,-0.1239943,0.1440089,1.0957669,451.94827,134.5988)"
+       clip-path="url(#clipPath4100)" />
+    <path
+       transform="translate(450.03125,73.843964)"
+       style="opacity:1;fill:url(#radialGradient3915);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 527.60588,407.44884 C 527.60588,407.44884 405.56444,445.85232 340.09154,417.08065 C 274.61865,388.30899 265.71429,292.36218 265.71429,292.36218 C 265.71429,292.36218 339.09587,211.85825 395.63507,208.74742 C 451.46212,205.67578 486.20893,228.89074 510.50508,274.59913 C 534.85708,320.41261 527.60588,407.44884 527.60588,407.44884 z"
+       id="path7995"
+       sodipodi:nodetypes="csczzc"
+       mask="url(#mask3684)" />
+    <path
+       style="opacity:1;fill:url(#linearGradient3959);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 772.17411,393.349 C 772.17411,393.349 808.39165,365.96653 823.78125,357.45614 C 838.95859,349.06313 849.49553,345.849 859.6741,345.849 L 844.13839,412.81328"
+       id="path7997"
+       sodipodi:nodetypes="czcc" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:url(#radialGradient3933);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path7999"
+       sodipodi:cx="409.28571"
+       sodipodi:cy="306.64789"
+       sodipodi:rx="36.25"
+       sodipodi:ry="36.25"
+       d="M 445.53571,306.64789 A 36.25,36.25 0 1 1 373.03571,306.64789 A 36.25,36.25 0 1 1 445.53571,306.64789 z"
+       transform="translate(449.49554,74.915393)" />
+    <path
+       style="opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8806);enable-background:accumulate"
+       d="M 311.83409,415.43155 L 321.73359,537.05392 L 261.62951,673.52553 L 277.18586,848.1809 C 292.79912,910.0601 309.37131,946.84995 351.56201,965.23473 C 355.88112,928.99475 360.24362,892.86709 320.31937,742.11489 L 337.99704,672.81842 L 410.12193,534.22549 L 367.69553,375.83357 L 311.83409,415.43155 z"
+       id="path8001"
+       sodipodi:nodetypes="cccccccccc"
+       clip-path="url(#clipPath8616)"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8826);enable-background:accumulate"
+       d="M 635.21025,581.13004 C 621.06811,593.85796 674.44372,615.71019 711.57778,605.17167 C 748.71184,594.63315 816.22265,569.6073 814.81537,525.97571 C 813.40809,482.34413 738.44784,397.28228 738.44784,397.28228 L 635.21025,581.13004 z"
+       id="path8003"
+       sodipodi:nodetypes="czzcc" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:url(#radialGradient3991);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path8005"
+       sodipodi:cx="410"
+       sodipodi:cy="306.64789"
+       sodipodi:rx="23.214285"
+       sodipodi:ry="23.214285"
+       d="M 433.21428,306.64789 A 23.214285,23.214285 0 1 1 386.78572,306.64789 A 23.214285,23.214285 0 1 1 433.21428,306.64789 z"
+       transform="translate(449.67411,74.915393)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3981);enable-background:accumulate"
+       id="path8007"
+       sodipodi:cx="414.28571"
+       sodipodi:cy="303.07648"
+       sodipodi:rx="7.5"
+       sodipodi:ry="7.5"
+       d="M 421.78571,303.07648 A 7.5,7.5 0 1 1 406.78571,303.07648 A 7.5,7.5 0 1 1 421.78571,303.07648 z"
+       transform="translate(451.99554,73.486821)" />
+    <path
+       style="opacity:1;fill:url(#radialGradient4112);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 789.31696,478.349 C 789.31696,478.349 796.33977,497.91759 788.24553,513.349 C 780.15129,528.78041 745.92236,552.33722 720.74554,563.349 C 695.43582,574.41891 635.27254,596.31293 618.95982,605.31328 C 602.49834,614.39571 600.74554,617.99185 600.74554,617.99185 C 600.74554,617.99185 593.59861,598.92744 629.49553,566.20615 C 665.66764,533.23401 771.52265,518.15665 789.31696,478.349 z"
+       id="path8009"
+       sodipodi:nodetypes="czzzczc" />
+    <g
+       style="opacity:1;display:inline;enable-background:new"
+       id="g8011"
+       transform="translate(780.74553,74.55825)">
+      <path
+         transform="translate(-329.81481,0)"
+         clip-path="url(#clipPath3999)"
+         sodipodi:nodetypes="czzczzzszc"
+         id="path8013"
+         d="M 179.64286,267.36218 C 157.23242,307.0651 119.02676,383.14247 110.35715,417.00504 C 101.70994,450.78014 101.58516,483.42158 110,503.43362 C 118.3602,523.31575 136.16398,539.06642 150.71428,544.86218 C 150.1179,530.48631 165.08723,501.57635 223.57143,472.36218 C 282.1977,443.07704 301.95306,445.23132 327.14285,425.21932 C 352.77291,404.85756 335.34872,345.57268 330.35714,331.29075 C 325.36556,317.00882 329.12051,327.91101 328.41112,326.19774 C 317.72184,300.38182 294.1968,271.76744 263.92857,261.6479 C 233.66034,251.52836 198.91081,256.79953 179.64286,267.36218 z"
+         style="opacity:1;fill:url(#radialGradient3585);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
+      <path
+         transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-166.62245,2.387362)"
+         d="M 248.28731,338.07648 A 64.715881,134.00607 0 1 1 118.85555,338.07648 A 64.715881,134.00607 0 1 1 248.28731,338.07648 z"
+         sodipodi:ry="134.00607"
+         sodipodi:rx="64.715881"
+         sodipodi:cy="338.07648"
+         sodipodi:cx="183.57143"
+         id="path8015"
+         style="opacity:1;fill:url(#radialGradient4060);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-162.19388,-18.755495)"
+         d="M 248.28731,338.07648 A 64.715881,134.00607 0 1 1 118.85555,338.07648 A 64.715881,134.00607 0 1 1 248.28731,338.07648 z"
+         sodipodi:ry="134.00607"
+         sodipodi:rx="64.715881"
+         sodipodi:cy="338.07648"
+         sodipodi:cx="183.57143"
+         id="path8017"
+         style="opacity:1;fill:url(#radialGradient4062);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(-329.81481,3e-7)"
+         clip-path="url(#clipPath3999)"
+         sodipodi:nodetypes="czzczzzszc"
+         id="path8019"
+         d="M 179.64286,267.36218 C 157.23242,307.0651 119.02676,383.14247 110.35715,417.00504 C 101.70994,450.78014 101.58516,483.42158 110,503.43362 C 118.3602,523.31575 136.16398,539.06642 150.71428,544.86218 C 150.1179,530.48631 165.08723,501.57635 223.57143,472.36218 C 282.1977,443.07704 301.95306,445.23132 327.14285,425.21932 C 352.77291,404.85756 335.34872,345.57268 330.35714,331.29075 C 325.36556,317.00882 329.12051,327.91101 328.41112,326.19774 C 317.72184,300.38182 294.1968,271.76744 263.92857,261.6479 C 233.66034,251.52836 198.91081,256.79953 179.64286,267.36218 z"
+         style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3587);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter4079);enable-background:new" />
+    </g>
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path8021"
+       sodipodi:cx="310.71429"
+       sodipodi:cy="398.07648"
+       sodipodi:rx="19.704132"
+       sodipodi:ry="19.704132"
+       d="M 330.41843,398.07648 A 19.704132,19.704132 0 1 1 291.01016,398.07648 A 19.704132,19.704132 0 1 1 330.41843,398.07648 z"
+       transform="translate(452.55663,72.581273)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:url(#radialGradient4056);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4082);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4083);enable-background:accumulate"
+       id="path8023"
+       sodipodi:cx="310.71429"
+       sodipodi:cy="398.07648"
+       sodipodi:rx="19.704132"
+       sodipodi:ry="19.704132"
+       d="M 330.41843,398.07648 A 19.704132,19.704132 0 1 1 291.01016,398.07648 A 19.704132,19.704132 0 1 1 330.41843,398.07648 z"
+       transform="translate(450.55663,72.581273)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:url(#radialGradient4119);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path8025"
+       sodipodi:cx="310.71429"
+       sodipodi:cy="398.07648"
+       sodipodi:rx="19.704132"
+       sodipodi:ry="19.704132"
+       d="M 330.41843,398.07648 A 19.704132,19.704132 0 1 1 291.01016,398.07648 A 19.704132,19.704132 0 1 1 330.41843,398.07648 z"
+       transform="translate(450.55663,72.581273)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:url(#radialGradient4868);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4002);enable-background:accumulate"
+       id="path8027"
+       sodipodi:cx="429.56738"
+       sodipodi:cy="377.42877"
+       sodipodi:rx="72.079735"
+       sodipodi:ry="44.547726"
+       d="M 501.64712,377.42877 A 72.079735,44.547726 0 1 1 357.48765,377.42877 A 72.079735,44.547726 0 1 1 501.64712,377.42877 z"
+       transform="matrix(0.9969564,-7.7961675e-2,7.7961675e-2,0.9969564,436.61877,125.29509)"
+       inkscape:transform-center-x="-47.231976"
+       inkscape:transform-center-y="-3.6935079" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:url(#radialGradient4876);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4010);enable-background:accumulate"
+       id="path8029"
+       sodipodi:cx="437.6991"
+       sodipodi:cy="391.21735"
+       sodipodi:rx="36.611931"
+       sodipodi:ry="22.627417"
+       d="M 474.31103,391.21735 A 36.611931,22.627417 0 1 1 401.08717,391.21735 A 36.611931,22.627417 0 1 1 474.31103,391.21735 z"
+       transform="matrix(1.4357951,-6.9991037e-2,6.9991037e-2,1.4357951,235.18065,-63.86546)"
+       inkscape:transform-center-x="-20.955902"
+       inkscape:transform-center-y="-13.056625" />
+    <g
+       transform="translate(450.03125,73.843964)"
+       id="g8031"
+       style="opacity:1;display:inline;filter:url(#filter4053);enable-background:new">
+      <path
+         d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
+         sodipodi:ry="3.2142856"
+         sodipodi:rx="3.2142856"
+         sodipodi:cy="401.82648"
+         sodipodi:cx="413.66071"
+         id="path8033"
+         style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4484);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(13.125009,8.1249913)"
+         d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
+         sodipodi:ry="3.2142856"
+         sodipodi:rx="3.2142856"
+         sodipodi:cy="401.82648"
+         sodipodi:cx="413.66071"
+         id="path8035"
+         style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4486);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(32.946437,7.4999913)"
+         d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
+         sodipodi:ry="3.2142856"
+         sodipodi:rx="3.2142856"
+         sodipodi:cy="401.82648"
+         sodipodi:cx="413.66071"
+         id="path8037"
+         style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4488);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(24.910723,-10.267866)"
+         d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
+         sodipodi:ry="3.2142856"
+         sodipodi:rx="3.2142856"
+         sodipodi:cy="401.82648"
+         sodipodi:cx="413.66071"
+         id="path8039"
+         style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4490);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(47.589294,-0.6250087)"
+         d="M 416.87499,401.82648 A 3.2142856,3.2142856 0 1 1 410.44642,401.82648 A 3.2142856,3.2142856 0 1 1 416.87499,401.82648 z"
+         sodipodi:ry="3.2142856"
+         sodipodi:rx="3.2142856"
+         sodipodi:cy="401.82648"
+         sodipodi:cx="413.66071"
+         id="path8041"
+         style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4492);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+    </g>
+    <path
+       style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+       d="M 896.20301,482.92837 C 897.1881,487.27845 900.74008,489.10785 903.58974,490.82019 C 908.05042,493.33311 910.1099,492.3423 912.74425,490.06258 C 914.3462,488.14141 923.42736,485.36393 928.33848,482.99151 C 932.66809,481.5326 937.24178,477.63278 941.723,474.65775 C 945.11814,473.03051 947.06964,475.01239 949.55168,475.6679 C 952.4958,476.38451 953.96285,477.83965 955.6126,479.20344 C 958.00876,480.37863 954.6847,482.34657 958.8956,483.49658 C 960.08651,483.71452 961.31255,484.07303 962.17859,482.99151"
+       id="path8043"
+       sodipodi:nodetypes="ccccccccc" />
+    <path
+       style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+       d="M 910.85021,475.35223 C 913.16515,475.32025 914.02799,475.99476 916.34292,474.53148 C 919.79856,471.45035 921.74546,471.38671 924.29787,470.11206 C 927.32444,468.79683 930.83357,478.26375 934.3994,479.96105 C 936.79449,479.13963 935.68854,481.75484 935.85149,482.6127 C 935.90862,485.25954 938.65843,486.29076 940.20777,488.04227 C 943.52381,490.29776 947.583,494.33773 951.31945,493.34557 C 957.7647,490.4145 961.59867,492.06411 967.60816,485.95883 C 968.31221,484.77749 967.02391,479.06423 970.70175,478.76149 C 973.22574,479.01487 974.86842,478.81164 976.76267,479.32971 C 982.20367,481.4469 984.50045,485.77971 991.47301,487.28466 C 997.65591,488.25105 999.08565,491.07892 1005.3626,492.33542"
+       id="path8045"
+       sodipodi:nodetypes="cccccccccccc" />
+    <path
+       style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+       d="M 876.98133,483.52197 C 879.37991,482.72817 883.08746,487.71407 885.15446,490.56765 C 885.74727,493.24717 886.30823,496.0541 885.91207,502.68948 C 886.6972,505.10702 888.59256,505.72043 890.7103,505.97248 C 893.82775,505.4357 896.58699,504.64818 898.0339,502.94202 C 899.9055,501.00035 903.34643,505.33596 906.11512,506.98263 C 909.72521,508.89472 913.8889,508.96149 917.98442,509.25547 C 919.688,509.02483 920.35482,513.77062 921.26741,517.3367 C 921.65155,521.71476 920.38197,524.23239 919.49965,527.18568 C 919.20535,529.68223 922.48815,530.71542 925.8131,531.73137 C 928.99554,532.47261 932.35734,533.39321 934.90447,533.49914 C 940.04633,534.37405 942.99321,536.18966 947.0263,537.53975 C 949.26544,538.3563 950.28649,539.78191 951.57199,541.07528"
+       id="path8047"
+       sodipodi:nodetypes="ccccccccccccc" />
+    <path
+       style="opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter8814);enable-background:new"
+       d="M 332,187.69519 C 332,187.69519 389.5,162.19519 389.5,159.69519 C 389.5,157.19519 395,107.69519 395,107.69519 C 395,107.69519 486,59.195189 486.5,57.195189 C 487,55.195189 572.5,-4.8048114 572.5,-4.8048114 L 386.5,17.195189 L 311,123.19519 L 332,187.69519 z"
+       id="path8049"
+       clip-path="url(#clipPath8514)"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 1697.2846,722.5514 C 1697.2846,722.5514 1581.3191,796.0905 1574.2481,800.33314 C 1567.177,804.57578 1343.7312,937.51186 1343.7312,937.51186 L 1347.9739,977.10984 L 1564.3486,876.70067 L 1681.7283,774.8773 L 1697.2846,722.5514 z"
+       id="path8051" />
+    <path
+       style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8810);enable-background:accumulate"
+       d="M 528.91587,556.85291 C 523.25902,555.4387 347.89654,631.80623 347.89654,631.80623 L 313.95541,812.82557 L 365.05087,1006.7738 L 622.25397,1074.4551 C 622.25397,1074.4551 828.72915,1227.1901 834.386,1222.9475 C 840.04286,1218.7049 1002.6774,1029.2002 1002.6774,1029.2002 L 842.87128,845.35248 L 796.20224,667.16157 L 528.91587,556.85291 z"
+       id="path8053"
+       clip-path="url(#clipPath8610)"
+       sodipodi:nodetypes="cccccscccc"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:1;fill:#0c0c0c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+       d="M 1097.6433,613.88997 C 1097.6433,613.88997 1120.2628,607.38316 1133.386,608.01724 C 1146.5093,608.65133 1164.0276,609.95586 1177.0949,620.20343 C 1190.1622,630.45099 1202.1626,647.3435 1211.2073,678.57308 C 1220.2519,709.80266 1212.9056,777.82509 1205.0312,821.92043 C 1197.1569,866.01577 1176.7661,928.03341 1160.0312,961.92043 C 1143.2964,995.80745 1110.2335,1039.4156 1099.4618,1051.7966 C 1088.0976,1064.8586 1043.2559,1088.2228 1020.0312,1094.0633 C 1025.3346,1083.4567 1068.931,1043.4744 1055.0312,1033.349 C 1041.0123,1023.1367 1009.2712,1079.3314 970.7381,1062.3822 C 992.12041,1049.2501 1012.5175,1011.1961 1004.7787,995.78772 C 996.93846,980.17733 974.07378,1044.5453 911.24317,1032.8006 C 941.29521,1005.2739 966.65023,961.89659 952.50587,949.8209 C 938.09071,937.51403 892.04412,1004.1141 892.04412,1004.1141 C 892.04412,1004.1141 889.22222,962.41287 905.81732,935.50673 C 922.45667,908.52886 985.47029,853.89146 1005.3704,823.80331 C 1025.2706,793.71517 1038.983,757.79429 1047.5059,731.28537 C 1056.0287,704.77645 1063.3068,654.18583 1063.3068,654.18583"
+       id="path8055"
+       sodipodi:nodetypes="czzzzzzczczczczzzc" />
+    <path
+       style="opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8818);enable-background:accumulate"
+       d="M 770.74639,609.17881 L 719.8347,706.75955 L 639.93163,817.77531 L 674.57987,889.19309 L 717.00628,968.38906 L 789.13117,923.13422 L 803.27331,730.80117 L 824.48651,592.20825 L 810.34437,502.05213 L 770.74639,609.17881 z"
+       id="path8057"
+       clip-path="url(#clipPath8622)"
+       sodipodi:nodetypes="cccccccccc"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8810);enable-background:accumulate"
+       d="M 295,846.19519 L 301.64488,777.27234 C 301.64488,777.27234 391.96439,866.27691 464,900.19519 C 536.03561,934.11347 772,962.19519 772,962.19519 L 926,936.19519 L 890,1098.1952 L 604,1124.1952 L 306,1035.1952 L 295,846.19519 z"
+       id="path8059"
+       clip-path="url(#clipPath8906)"
+       sodipodi:nodetypes="cczcccccc"
+       transform="translate(276,136)" />
+    <path
+       transform="translate(450.03125,73.843964)"
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter3587);enable-background:new"
+       d="M 405.79629,845.99023 L 480.74961,911.04406 L 483.24924,927.92446 L 502.6526,938.08337 L 509.14464,961.13446 L 540.85369,952.76336 L 555.70293,1000.8466 C 567.95945,1013.5745 645.49637,887.7369 611.56436,1039.0304 L 550.75318,1055.2939 L 461.55026,960.60104 L 398.72523,906.80141 L 405.79629,845.99023 z"
+       id="path8061"
+       sodipodi:nodetypes="cccccccccccc"
+       clip-path="url(#clipPath3602)" />
+    <path
+       style="opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 1159.317,918.349 C 1213.6027,916.92043 1285.352,903.29701 1329.317,891.56328 C 1373.3697,879.80614 1455.2033,855.21604 1504.674,833.70614 C 1554.0133,812.25342 1618.2778,774.42454 1658.9599,741.56329 C 1699.468,708.8426 1711.3498,685.74348 1719.6741,707.99186 C 1728.0432,730.35965 1703.2672,764.31748 1681.817,789.06329 C 1660.2128,813.98669 1629.0856,841.76862 1582.8883,878.349 C 1536.691,914.92938 1426.8058,979.93363 1370.0312,1006.9204 C 1312.9652,1034.0458 1241.8279,1065.1589 1197.8884,1079.4205 C 1153.9489,1093.6821 1066.4598,1110.4919 1066.4598,1110.4919 L 1159.317,918.349 z"
+       id="path8063"
+       sodipodi:nodetypes="czzzzzzzzcc" />
+    <path
+       transform="translate(450.03125,73.843964)"
+       style="opacity:0.5;fill:url(#linearGradient3666);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3779);enable-background:accumulate"
+       d="M 1241.5965,652.95007 C 1241.5965,652.95007 1176.875,707.28713 1095.9326,751.94501 C 1013.9082,797.19985 811.67556,845.28311 811.67556,845.28311 C 811.67556,845.28311 796.57419,866.33507 856.93045,873.56739 C 917.28671,880.79971 1081.0124,820.2667 1135.5306,777.40085 C 1190.0488,734.535 1255.7387,665.67799 1255.7387,665.67799 L 1241.5965,652.95007 z"
+       id="path8065"
+       sodipodi:nodetypes="czczzcc"
+       clip-path="url(#clipPath3992)" />
+    <g
+       transform="translate(450.03125,73.843964)"
+       style="opacity:1;display:inline;enable-background:new"
+       id="g8067"
+       clip-path="url(#clipPath3986)">
+      <g
+         transform="translate(-174.03125,62.156036)"
+         style="filter:url(#filter3677)"
+         id="g8069">
+        <g
+           style="filter:url(#filter3785)"
+           id="g8071">
+          <path
+             sodipodi:nodetypes="czzccccc"
+             id="path8073"
+             d="M 1094.2857,725.93361 C 1094.2857,725.93361 1093.9896,752.09452 1098.9285,763.79076 C 1103.8674,775.487 1118.9666,790.27741 1127.5,795.21933 C 1136.0334,800.16125 1146.4286,803.79075 1146.4286,803.79075 L 1264.2857,688.79075 L 1282.1429,613.07647 L 1185.7143,651.6479 L 1094.2857,725.93361 z"
+             style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+             transform="translate(174.03125,-62.156036)" />
+          <rect
+             y="486.14224"
+             x="1197.8389"
+             height="309.71277"
+             width="333.75412"
+             id="rect8075"
+             style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+        </g>
+      </g>
+      <g
+         transform="translate(-174.03125,62.156036)"
+         style="opacity:0.18000004;display:inline;enable-background:new"
+         id="g8077">
+        <g
+           style="filter:url(#filter3785)"
+           id="g8079">
+          <path
+             sodipodi:nodetypes="czzccccc"
+             id="path8081"
+             d="M 1094.2857,725.93361 C 1094.2857,725.93361 1093.9896,752.09452 1098.9285,763.79076 C 1103.8674,775.487 1118.9666,790.27741 1127.5,795.21933 C 1136.0334,800.16125 1146.4286,803.79075 1146.4286,803.79075 L 1264.2857,688.79075 L 1282.1429,613.07647 L 1185.7143,651.6479 L 1094.2857,725.93361 z"
+             style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+             transform="translate(174.03125,-62.156036)" />
+          <rect
+             y="486.14224"
+             x="1197.8389"
+             height="309.71277"
+             width="333.75412"
+             id="rect8083"
+             style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+        </g>
+      </g>
+    </g>
+    <path
+       transform="translate(450.03125,73.843964)"
+       style="opacity:0.83300003;fill:#050505;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;marker:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter8225);enable-background:accumulate"
+       d="M 1264.1875,605 C 1259.6964,605.73268 1256.0305,608.45509 1252.25,611.40625 C 1242.1687,619.27601 1224.0805,645.83149 1204.2188,661.875 C 1164.3514,694.07816 1100.2228,731.85201 1051.6562,752.96875 C 1003.0422,774.10613 921.11498,798.78676 877.34375,810.46875 C 833.94554,822.05121 762.29972,835.59982 709.09375,837 L 704.53125,837.125 L 702.53125,841.25 L 609.6875,1033.375 L 603.1875,1046.8438 L 617.84375,1044 C 617.84375,1044 705.11343,1027.3486 750.1875,1012.7188 C 794.9127,998.20213 865.97836,967.05197 923.21875,939.84375 C 980.82199,912.46306 1090.1551,847.86412 1137.5,810.375 C 1183.8608,773.66518 1215.3049,745.65818 1237.4375,720.125 C 1248.3386,707.549 1260.1823,692.59356 1268.4688,677.375 C 1276.7552,662.15644 1287.6285,633.15692 1282.1562,618.53125 C 1280.9385,615.27651 1279.6048,612.46995 1277.5625,610.03125 C 1275.5202,607.59255 1269.0878,608.45926 1269,605 C 1268.7902,596.73518 1265.6845,604.75577 1264.1875,605 z M 1266.3438,620.21875 C 1266.7586,620.80449 1267.3749,621.77641 1268.125,623.78125 C 1271.0218,631.52338 1266.6843,655.68 1259.3125,669.21875 C 1251.9407,682.7575 1236.6741,698.14269 1226.125,710.3125 C 1205.0496,734.62606 1174.2213,762.17406 1128.1875,798.625 C 1083.1379,834.29659 972.72717,899.71959 916.78125,926.3125 C 859.88952,953.35499 788.68509,984.4309 745.53125,998.4375 C 709.16634,1010.2406 649.68654,1022.2713 629.8125,1026.2188 L 714.09375,851.75 C 768.80066,849.7007 837.88634,836.53365 881.21875,824.96875 C 925.55297,813.1365 1007.2974,788.63242 1057.625,766.75 C 1107.737,744.96129 1170.1594,705.58184 1211.6562,672.0625 C 1232.3026,655.38529 1253.4011,629.51662 1261.4688,623.21875 C 1263.9058,621.31633 1265.5494,620.58295 1266.3438,620.21875 z"
+       id="path8085"
+       clip-path="url(#clipPath3722)"
+       sodipodi:nodetypes="cssssccccccssssssssccssssssccssssc" />
+    <g
+       style="opacity:1;display:inline;enable-background:new"
+       id="g8087"
+       mask="url(#mask7704)"
+       transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+       inkscape:transform-center-x="-185.09603"
+       inkscape:transform-center-y="-12.859654">
+      <path
+         transform="translate(8.0045714e-2,-3.125e-2)"
+         style="fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+         d="M 1111.4062,-285.9375 L 1107.4688,-284.0625 C 1107.4283,-284.05228 1107.3692,-284.04201 1107.3438,-284.03125 C 1106.925,-283.8184 1107.1791,-283.93067 1106.6875,-283.71875 C 1106.2014,-283.50919 1104.9499,-283.13456 1102.5938,-282.25 C 1099.2626,-280.99942 1096.7895,-280.10016 1095.5938,-279.1875 C 1094.0576,-279.16623 1091.8733,-278.95419 1089.9375,-278.46875 C 1086.956,-277.72108 1085.0823,-277.29474 1083.1875,-276.875 C 1081.2927,-276.45527 1081.512,-276.23281 1080.3125,-276 C 1079.0159,-275.74833 1078.5911,-276.00899 1074.875,-275.21875 C 1071.3851,-274.4766 1065.9802,-273.28768 1064.7188,-272.53125 C 1063.1348,-272.71203 1060.8513,-272.85303 1058.875,-272.5625 C 1055.8346,-272.11554 1053.9588,-271.88974 1052.0312,-271.65625 C 1051.3758,-271.57687 1050.9902,-271.45547 1050.6875,-271.375 C 1050.2613,-271.24334 1050.0017,-271.11498 1049.3125,-271.03125 C 1048.0009,-270.87188 1047.5503,-271.18808 1043.7812,-270.75 C 1040.2273,-270.33691 1034.7758,-269.47718 1033.5312,-268.8125 C 1031.9322,-269.10979 1029.6735,-269.34669 1027.6875,-269.15625 C 1024.6287,-268.86293 1022.7155,-268.67226 1020.7812,-268.5 C 1018.847,-268.32773 1019.0926,-268.07763 1017.875,-267.96875 C 1016.5588,-267.85105 1016.1152,-268.13238 1012.3438,-267.71875 C 1008.8017,-267.3303 1003.3359,-266.50948 1002.0625,-265.84375 C 1000.4636,-266.13844 998.1753,-266.35076 996.1875,-266.15625 C 993.12921,-265.857 991.2463,-265.67601 989.3125,-265.5 C 988.65501,-265.44015 988.27245,-265.32144 987.96875,-265.25 C 987.54105,-265.13104 987.28525,-265.03193 986.59375,-264.96875 C 985.27775,-264.84849 984.834,-265.16363 981.0625,-264.75 C 977.50631,-264.35998 972.0569,-263.51084 970.8125,-262.84375 C 969.21381,-263.13793 966.95265,-263.36747 964.96875,-263.15625 C 961.91305,-262.83092 959.9947,-262.63001 958.0625,-262.4375 C 956.13031,-262.24499 956.37275,-261.99662 955.15625,-261.875 C 953.84137,-261.74353 953.3932,-262.03954 949.625,-261.59375 C 946.08611,-261.17509 940.6473,-260.30158 939.375,-259.625 C 937.77741,-259.90604 935.51505,-260.04543 933.53125,-259.8125 C 930.47927,-259.45413 928.58625,-259.24464 926.65625,-259.03125 C 926.00007,-258.95869 925.6156,-258.85856 925.3125,-258.78125 C 924.88571,-258.65402 924.6276,-258.51405 923.9375,-258.4375 C 922.62411,-258.29181 922.17015,-258.61152 918.40625,-258.125 C 914.85737,-257.66624 909.4276,-256.70598 908.1875,-256 C 906.59441,-256.24424 904.3537,-256.38135 902.375,-256.125 C 899.32741,-255.73018 897.4243,-255.47655 895.5,-255.21875 C 893.57571,-254.96096 893.7739,-254.72522 892.5625,-254.5625 C 891.25301,-254.3866 890.8153,-254.66688 887.0625,-254.09375 C 883.53821,-253.55551 878.1393,-252.39458 876.875,-251.65625 C 875.28751,-251.85979 873.0295,-251.91098 871.0625,-251.5625 C 868.03631,-251.02638 866.1636,-250.70081 864.25,-250.375 C 863.59941,-250.26423 863.2363,-250.10406 862.9375,-250 C 862.51681,-249.83512 862.27405,-249.6687 861.59375,-249.53125 C 860.29905,-249.26966 859.86665,-249.53745 856.15625,-248.71875 C 852.65777,-247.9468 847.31035,-246.33582 846.09375,-245.5 C 844.53085,-245.57745 842.33625,-245.41472 840.40625,-244.90625 C 837.43387,-244.12312 835.58855,-243.67416 833.71875,-243.15625 C 831.84875,-242.63835 832.0521,-242.38897 830.875,-242.0625 C 829.60251,-241.7096 829.17795,-241.95541 825.53125,-240.875 C 822.10657,-239.86037 816.88185,-237.94183 815.65625,-237.03125 C 814.11747,-237.01851 811.93645,-236.75903 810.03125,-236.15625 C 807.10027,-235.22891 805.2809,-234.69783 803.4375,-234.09375 C 802.81071,-233.88837 802.44585,-233.70117 802.15625,-233.5625 C 801.74867,-233.34889 801.50295,-233.15375 800.84375,-232.9375 C 799.58925,-232.52596 799.1576,-232.74846 795.5625,-231.5 C 792.17261,-230.32283 786.96755,-228.2863 785.78125,-227.34375 C 784.25737,-227.28408 782.1312,-226.94888 780.25,-226.28125 C 777.35261,-225.25296 775.55095,-224.60577 773.71875,-223.96875 C 771.88655,-223.33174 772.0909,-223.12021 770.9375,-222.71875 C 769.69071,-222.28479 769.27395,-222.51903 765.71875,-221.15625 C 762.38005,-219.87645 757.23165,-217.6737 756.03125,-216.6875 C 754.52407,-216.57981 752.39555,-216.1887 750.53125,-215.46875 C 747.66307,-214.36115 745.90735,-213.68719 744.09375,-213 C 743.47705,-212.76637 743.0973,-212.55797 742.8125,-212.40625 C 742.81251,-212.40625 742.8125,-212.37673 742.8125,-212.375 L 734.8125,-209.1875 L 722.3366,-205.69561 L 730.26626,-186.41789 C 729.67463,-184.44432 742.8125,-191.15625 742.8125,-191.15625 C 743.03891,-191.30093 743.26145,-191.42886 743.53125,-191.53125 C 744.61177,-191.94123 745.70285,-191.74702 749.53125,-193.21875 C 753.35977,-194.69049 754.7553,-195.22373 755.4375,-195.625 C 756.11711,-196.02478 757.04925,-196.50437 757.65625,-197.15625 C 759.48317,-197.294 761.22705,-197.64948 762.59375,-198.15625 C 765.56175,-199.25677 767.4691,-199.96244 769.375,-200.625 C 771.28081,-201.28754 771.72915,-202.03987 772.78125,-202.40625 C 773.87287,-202.78636 774.97635,-202.57163 778.84375,-203.9375 C 782.71115,-205.30336 784.1269,-205.76458 784.8125,-206.15625 C 785.51361,-206.55677 786.5133,-207.08923 787.125,-207.75 C 789.09581,-207.80466 790.94195,-208.13463 792.40625,-208.625 C 795.40777,-209.63008 797.3324,-210.24671 799.25,-210.875 C 800.78861,-211.3791 801.42415,-211.92177 802.15625,-212.3125 C 802.38647,-212.44681 802.63215,-212.56623 802.90625,-212.65625 C 804.00457,-213.01673 805.0877,-212.73762 809,-213.96875 C 812.91231,-215.19988 814.366,-215.6417 815.0625,-216 C 815.75641,-216.35697 816.6926,-216.79261 817.3125,-217.40625 C 819.17771,-217.42891 820.94835,-217.67308 822.34375,-218.09375 C 825.37415,-219.00729 827.33615,-219.52385 829.28125,-220.0625 C 831.22637,-220.60114 831.70745,-221.32702 832.78125,-221.625 C 833.89527,-221.93415 835.00125,-221.61761 838.96875,-222.65625 C 842.93625,-223.69488 844.38625,-224.08898 845.09375,-224.40625 C 845.82855,-224.73584 846.90765,-225.15997 847.53125,-225.78125 C 849.52907,-225.66525 851.3887,-225.80134 852.875,-226.15625 C 855.95311,-226.89125 857.9584,-227.25719 859.9375,-227.65625 C 861.52541,-227.97643 862.1818,-228.4468 862.9375,-228.75 C 863.17501,-228.8568 863.4044,-228.94276 863.6875,-229 C 864.82091,-229.22919 865.99215,-228.79107 870.03125,-229.5 C 874.07067,-230.20893 875.5315,-230.42709 876.25,-230.6875 C 876.96581,-230.94694 877.95435,-231.25474 878.59375,-231.78125 C 880.51795,-231.54176 882.34165,-231.55672 883.78125,-231.78125 C 886.90767,-232.26887 888.9358,-232.48192 890.9375,-232.75 C 892.93921,-233.01807 893.42625,-233.69514 894.53125,-233.84375 C 895.67767,-233.99793 896.8071,-233.54218 900.875,-234.0625 C 904.94281,-234.58282 906.43525,-234.75823 907.15625,-235 C 907.89337,-235.24714 908.95435,-235.58623 909.59375,-236.125 C 911.64375,-235.78947 913.56745,-235.72704 915.09375,-235.90625 C 918.23595,-236.27521 920.27375,-236.46561 922.28125,-236.6875 C 923.89207,-236.86552 924.5459,-237.2957 925.3125,-237.53125 C 925.55341,-237.61677 925.80655,-237.68685 926.09375,-237.71875 C 927.24345,-237.84647 928.39505,-237.3721 932.46875,-237.84375 C 936.54245,-238.3154 938.0278,-238.45435 938.75,-238.6875 C 939.46941,-238.91977 940.45025,-239.16096 941.09375,-239.65625 C 943.03005,-239.32279 944.8638,-239.25201 946.3125,-239.40625 C 949.45851,-239.7412 951.49,-239.92484 953.5,-240.125 C 955.50991,-240.32514 955.98415,-240.95139 957.09375,-241.0625 C 958.24485,-241.17778 959.39025,-240.69744 963.46875,-241.125 C 967.54725,-241.55256 969.05765,-241.68709 969.78125,-241.90625 C 970.52047,-242.13011 971.57685,-242.4195 972.21875,-242.9375 C 974.27575,-242.53883 976.2206,-242.4441 977.75,-242.59375 C 980.89871,-242.90185 982.9258,-243.067 984.9375,-243.25 C 986.55151,-243.39682 987.20055,-243.81055 987.96875,-244.03125 C 988.21005,-244.11211 988.4623,-244.16116 988.75,-244.1875 C 989.90211,-244.29295 991.0429,-243.79475 995.125,-244.1875 C 999.20711,-244.58025 1000.7139,-244.71834 1001.4375,-244.9375 C 1002.1584,-245.15583 1003.1371,-245.3852 1003.7812,-245.875 C 1005.7193,-245.52501 1007.5501,-245.42062 1009,-245.5625 C 1012.1487,-245.8706 1014.1758,-246.03575 1016.1875,-246.21875 C 1018.1991,-246.40174 1018.7017,-247.05677 1019.8125,-247.15625 C 1020.9648,-247.25948 1022.1047,-246.77142 1026.1875,-247.15625 C 1030.2704,-247.54107 1031.7762,-247.65725 1032.5,-247.875 C 1033.2393,-248.09743 1034.2956,-248.38949 1034.9375,-248.90625 C 1036.9949,-248.50448 1038.9404,-248.40292 1040.4688,-248.5625 C 1043.6153,-248.89102 1045.6458,-249.0852 1047.6562,-249.28125 C 1049.2692,-249.43854 1049.9219,-249.91273 1050.6875,-250.15625 C 1050.9282,-250.24429 1051.1507,-250.27762 1051.4375,-250.3125 C 1052.5858,-250.4522 1053.7542,-249.97259 1057.8125,-250.5625 C 1061.8708,-251.15242 1063.3743,-251.33964 1064.0938,-251.59375 C 1064.8104,-251.84691 1065.7684,-252.15182 1066.4062,-252.6875 C 1068.3259,-252.47556 1070.1262,-252.53609 1071.5625,-252.78125 C 1074.6816,-253.31365 1076.6741,-253.70986 1078.6562,-254.09375 C 1080.6383,-254.47762 1081.1305,-255.1334 1082.2188,-255.375 C 1083.3475,-255.62566 1084.489,-255.25871 1088.4688,-256.25 C 1092.4483,-257.24127 1093.8983,-257.6693 1094.5938,-258.03125 C 1095.316,-258.40725 1096.3555,-258.90183 1096.9688,-259.5625 C 1098.9317,-259.57454 1100.7625,-259.85355 1102.1875,-260.40625 C 1105.1387,-261.55085 1107.0607,-262.27567 1108.875,-263.15625 C 1110.3307,-263.86277 1111.1941,-264.85828 1111.4062,-265.15625 C 1111.6185,-265.4542 1111.5051,-265.8848 1111.5312,-265.90625 C 1111.5742,-265.94148 1111.8716,-266.00028 1112.0312,-266.34375 C 1112.8902,-268.19082 1114.3544,-271.97139 1114.4688,-272.65625 C 1114.5825,-273.33839 1114.6368,-274.00902 1114.6875,-274.40625 C 1114.7169,-274.63575 1114.5404,-275.28515 1114.5625,-275.34375 C 1114.5934,-275.42579 1114.8508,-275.59432 1114.9062,-275.84375 C 1115.1725,-277.04206 1114.9953,-278.05111 1114.7812,-279.46875 C 1114.5673,-280.88638 1113.8096,-284.08338 1113.1562,-284.9375 C 1112.4973,-285.79922 1111.9314,-285.94801 1111.4062,-285.9375 z"
+         id="path8089"
+         sodipodi:nodetypes="ccssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssscccccssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssssssssc" />
+      <g
+         clip-path="url(#clipPath7421)"
+         id="g8091">
+        <path
+           id="path8093"
+           d="M 1107.409,-284.04961 C 1106.9903,-283.83678 1107.2534,-283.95572 1106.7618,-283.7438 C 1106.2757,-283.53426 1105.0384,-283.16941 1102.6822,-282.28485 C 1099.3511,-281.03428 1096.852,-280.13141 1095.6563,-279.21875 C 1094.1202,-279.19749 1091.9358,-278.98544 1090,-278.5 C 1087.0185,-277.75234 1085.1448,-277.32599 1083.25,-276.90625 C 1081.3552,-276.48653 1081.5745,-276.26406 1080.375,-276.03125 C 1079.0784,-275.77959 1078.6536,-276.04024 1074.9375,-275.25 C 1071.4476,-274.50786 1066.0427,-273.31893 1064.7813,-272.5625 C 1063.1974,-272.74329 1060.9138,-272.88428 1058.9375,-272.59375 C 1055.8971,-272.1468 1054.0213,-271.92099 1052.0938,-271.6875 C 1051.4384,-271.60813 1051.0527,-271.48672 1050.75,-271.40625 C 1050.3238,-271.2746 1050.0642,-271.14623 1049.375,-271.0625 C 1048.0634,-270.90314 1047.6128,-271.21933 1043.8438,-270.78125 C 1040.2899,-270.36817 1034.8384,-269.50843 1033.5938,-268.84375 C 1031.9948,-269.14105 1029.736,-269.37794 1027.75,-269.1875 C 1024.6912,-268.89419 1022.778,-268.70351 1020.8438,-268.53125 C 1018.9095,-268.35899 1019.1551,-268.10888 1017.9375,-268 C 1016.6213,-267.88231 1016.1777,-268.16363 1012.4063,-267.75 C 1008.8644,-267.36156 1003.3984,-266.54073 1002.125,-265.875 C 1000.5261,-266.1697 998.23783,-266.38201 996.25,-266.1875 C 993.19176,-265.88826 991.30887,-265.70726 989.375,-265.53125 C 988.71751,-265.47141 988.33496,-265.35269 988.03125,-265.28125 C 987.6036,-265.1623 987.34774,-265.06318 986.65625,-265 C 985.34029,-264.87975 984.89649,-265.19488 981.125,-264.78125 C 977.56886,-264.39124 972.11946,-263.54209 970.875,-262.875 C 969.27637,-263.16919 967.01516,-263.39872 965.03125,-263.1875 C 961.97565,-262.86218 960.05721,-262.66126 958.125,-262.46875 C 956.19279,-262.27625 956.43513,-262.02787 955.21875,-261.90625 C 953.90387,-261.77479 953.45577,-262.07079 949.6875,-261.625 C 946.14863,-261.20635 940.70982,-260.33283 939.4375,-259.65625 C 937.83995,-259.9373 935.57754,-260.07668 933.59375,-259.84375 C 930.54177,-259.48539 928.64867,-259.27589 926.71875,-259.0625 C 926.06255,-258.98995 925.67809,-258.88981 925.375,-258.8125 C 924.94823,-258.68528 924.69009,-258.5453 924,-258.46875 C 922.68667,-258.32307 922.23254,-258.64277 918.46875,-258.15625 C 914.91986,-257.6975 909.49012,-256.73723 908.25,-256.03125 C 906.65695,-256.27549 904.41619,-256.4126 902.4375,-256.15625 C 899.38991,-255.76144 897.48679,-255.5078 895.5625,-255.25 C 893.63822,-254.99221 893.83639,-254.75647 892.625,-254.59375 C 891.31554,-254.41785 890.87781,-254.69813 887.125,-254.125 C 883.60071,-253.58676 878.20185,-252.42583 876.9375,-251.6875 C 875.35,-251.89104 873.092,-251.94223 871.125,-251.59375 C 868.09883,-251.05763 866.22611,-250.73206 864.3125,-250.40625 C 863.66189,-250.29548 863.29879,-250.13531 863,-250.03125 C 862.57933,-249.86637 862.33655,-249.69995 861.65625,-249.5625 C 860.3616,-249.30091 859.92913,-249.5687 856.21875,-248.75 C 852.72022,-247.97805 847.3728,-246.36707 846.15625,-245.53125 C 844.59347,-245.6087 842.39867,-245.44597 840.46875,-244.9375 C 837.49631,-244.15437 835.65114,-243.70541 833.78125,-243.1875 C 831.91137,-242.6696 832.11465,-242.42022 830.9375,-242.09375 C 829.66504,-241.74085 829.24047,-241.98666 825.59375,-240.90625 C 822.16905,-239.89162 816.94431,-237.97308 815.71875,-237.0625 C 814.17992,-237.04976 811.99892,-236.79028 810.09375,-236.1875 C 807.16269,-235.26016 805.34344,-234.72908 803.5,-234.125 C 802.87324,-233.91962 802.50827,-233.73242 802.21875,-233.59375 C 801.81112,-233.38014 801.56541,-233.185 800.90625,-232.96875 C 799.65179,-232.55721 799.22014,-232.77971 795.625,-231.53125 C 792.23515,-230.35408 787.03002,-228.31755 785.84375,-227.375 C 784.31986,-227.31533 782.1937,-226.98013 780.3125,-226.3125 C 777.41511,-225.28421 775.61342,-224.63702 773.78125,-224 C 771.94908,-223.36299 772.1534,-223.15146 771,-222.75 C 769.75322,-222.31604 769.33639,-222.55028 765.78125,-221.1875 C 762.44258,-219.9077 757.2941,-217.70495 756.09375,-216.71875 C 754.58657,-216.61106 752.45806,-216.21995 750.59375,-215.5 C 747.72557,-214.3924 745.96995,-213.71844 744.15625,-213.03125 C 743.53959,-212.79762 743.15984,-212.58922 742.875,-212.4375 C 742.875,-212.4375 742.875,-211.34375 742.875,-211.34375 C 742.98678,-211.56611 743.26099,-212.16118 743.78125,-212.4375 C 744.47922,-212.80822 748.59488,-214.43087 750.59375,-215.15625 C 752.25061,-215.7575 754.74764,-216.48493 756.5625,-216.46875 C 756.86412,-216.46606 757.15012,-216.41785 757.40625,-216.375 C 759.24874,-216.06675 764.875,-214.8125 764.875,-214.8125 C 764.87499,-214.8125 758.64151,-216.45925 757.84375,-216.65625 C 757.65296,-216.70336 757.30803,-216.72497 756.875,-216.71875 C 758.02046,-217.58846 761.636,-219.11226 764.21875,-220.15625 C 767.05697,-221.30352 767.33556,-221.40807 769.28125,-221.8125 C 771.28955,-222.22994 772.4375,-222.3125 772.4375,-222.3125 C 772.4375,-222.31249 772.35514,-222.91364 773.40625,-223.4375 C 774.11135,-223.78891 778.29327,-225.3299 780.3125,-226 C 782.2644,-226.64773 785.3699,-227.3585 787.1875,-227 C 789.05073,-226.6325 794.71875,-225.1875 794.71875,-225.1875 C 794.71876,-225.1875 788.43175,-227.05861 787.625,-227.28125 C 787.43208,-227.3345 787.09416,-227.36729 786.65625,-227.375 C 787.81459,-228.20788 791.45069,-229.57032 794.0625,-230.53125 C 796.93266,-231.58726 797.22984,-231.69305 799.1875,-232.0625 C 801.04099,-232.41229 802.04634,-232.48798 802.21875,-232.5 C 802.33235,-232.71724 802.5962,-233.31002 803.125,-233.5625 C 803.83444,-233.90124 808.05107,-235.27525 810.09375,-235.875 C 811.78692,-236.37211 814.33452,-236.91177 816.1875,-236.78125 C 816.49545,-236.75957 816.80099,-236.68399 817.0625,-236.625 C 818.94368,-236.20068 824.65625,-234.59375 824.65625,-234.59375 C 824.65626,-234.59375 818.31451,-236.659 817.5,-236.90625 C 817.30521,-236.96539 816.94212,-237.01019 816.5,-237.03125 C 817.66949,-237.8288 821.36302,-239.08747 824,-239.96875 C 826.89781,-240.93722 827.23301,-240.97207 829.21875,-241.25 C 831.2684,-241.53689 832.40625,-241.5625 832.40625,-241.5625 C 832.40623,-241.5625 832.3335,-242.16947 833.40625,-242.625 C 834.12585,-242.93057 838.39723,-244.12575 840.46875,-244.625 C 842.47119,-245.10758 845.66724,-245.55329 847.53125,-245.03125 C 849.44203,-244.4961 855.25,-242.53125 855.25,-242.53125 C 855.25,-242.53125 848.82734,-244.95476 848,-245.25 C 847.80216,-245.32061 847.41784,-245.39039 846.96875,-245.4375 C 848.15665,-246.16615 851.88402,-247.21158 854.5625,-247.9375 C 857.50592,-248.73525 857.85458,-248.70833 859.875,-248.84375 C 861.78789,-248.97198 862.82205,-248.91484 863,-248.90625 C 863.11728,-249.10991 863.39176,-249.68573 863.9375,-249.875 C 864.66969,-250.12894 869.01602,-250.92289 871.125,-251.25 C 872.87313,-251.52111 875.52588,-251.7347 877.4375,-251.34375 C 877.75516,-251.27879 878.04272,-251.15824 878.3125,-251.0625 C 880.25324,-250.37377 886.15625,-247.96875 886.15625,-247.96875 C 886.15626,-247.96875 879.62154,-250.91952 878.78125,-251.28125 C 878.58028,-251.36776 878.20612,-251.44804 877.75,-251.53125 C 878.9565,-252.16443 882.77956,-252.92685 885.5,-253.4375 C 888.48953,-253.99869 888.80023,-253.96704 890.84375,-253.96875 C 892.95301,-253.97052 894.15625,-253.84375 894.15625,-253.84375 C 894.15625,-253.84374 894.08354,-254.47494 895.1875,-254.78125 C 895.92802,-254.98672 900.31362,-255.61512 902.4375,-255.84375 C 904.49052,-256.06474 907.75613,-256.09597 909.65625,-255.375 C 911.60404,-254.63593 917.5,-252 917.5,-252 C 917.50002,-252 910.93712,-255.17897 910.09375,-255.5625 C 909.89207,-255.65423 909.55154,-255.74871 909.09375,-255.84375 C 910.30467,-256.44563 914.07817,-257.09259 916.8125,-257.5 C 919.8173,-257.94772 920.13801,-257.9517 922.1875,-257.90625 C 924.12795,-257.86323 925.19449,-257.71202 925.375,-257.6875 C 925.49392,-257.88066 925.7589,-258.45333 926.3125,-258.59375 C 927.05521,-258.78213 931.46679,-259.32803 933.59375,-259.53125 C 935.35678,-259.69967 938.01384,-259.76554 939.9375,-259.28125 C 940.25718,-259.20077 940.54101,-259.07766 940.8125,-258.96875 C 942.76543,-258.18526 948.71875,-255.5 948.71875,-255.5 C 948.71873,-255.5 942.12684,-258.75348 941.28125,-259.15625 C 941.07903,-259.25257 940.70899,-259.36328 940.25,-259.46875 C 941.46414,-260.04302 945.29366,-260.59094 948.03125,-260.96875 C 951.03963,-261.38395 951.35432,-261.41138 953.40625,-261.34375 C 955.52423,-261.27394 956.71875,-261.09375 956.71875,-261.09375 C 956.71873,-261.09375 956.6415,-261.73116 957.75,-262 C 958.49362,-262.18035 962.90176,-262.66355 965.03125,-262.84375 C 967.08972,-263.01792 970.37449,-262.96807 972.28125,-262.1875 C 974.23584,-261.38734 980.15625,-258.65625 980.15625,-258.65625 C 980.15623,-258.65625 973.59632,-261.96501 972.75,-262.375 C 972.54763,-262.47305 972.17814,-262.5781 971.71875,-262.6875 C 972.93392,-263.2514 976.72883,-263.8018 979.46875,-264.15625 C 982.47966,-264.54577 982.79006,-264.5539 984.84375,-264.46875 C 986.78814,-264.38815 987.85038,-264.21551 988.03125,-264.1875 C 988.15041,-264.37836 988.41402,-264.93281 988.96875,-265.0625 C 989.71301,-265.2365 994.11868,-265.71297 996.25,-265.875 C 998.01662,-266.00927 1000.6997,-266.00071 1002.625,-265.5 C 1002.945,-265.41679 1003.2283,-265.29873 1003.5,-265.1875 C 1005.4546,-264.38734 1011.4063,-261.625 1011.4063,-261.625 C 1011.4062,-261.625 1004.8151,-264.96501 1003.9688,-265.375 C 1003.7664,-265.47305 1003.3969,-265.57811 1002.9375,-265.6875 C 1004.1526,-266.2514 1007.9788,-266.77056 1010.7188,-267.125 C 1013.7297,-267.51453 1014.0713,-267.5539 1016.125,-267.46875 C 1018.2447,-267.38087 1019.4375,-267.15625 1019.4375,-267.15625 C 1019.4375,-267.15625 1019.3591,-267.80527 1020.4688,-268.0625 C 1021.2131,-268.23506 1025.6183,-268.68586 1027.75,-268.84375 C 1029.8106,-268.99635 1033.0929,-268.94052 1035,-268.15625 C 1036.955,-267.3523 1042.875,-264.65625 1042.875,-264.65625 C 1042.875,-264.65625 1036.3152,-267.93212 1035.4688,-268.34375 C 1035.2663,-268.44219 1034.897,-268.54597 1034.4375,-268.65625 C 1035.6529,-269.21779 1039.4494,-269.78403 1042.1875,-270.15625 C 1045.1965,-270.5653 1045.5102,-270.57183 1047.5625,-270.5 C 1049.5056,-270.43201 1050.5697,-270.33515 1050.75,-270.3125 C 1050.8688,-270.5069 1051.1346,-271.04131 1051.6875,-271.1875 C 1052.4293,-271.38362 1056.8186,-272.01628 1058.9375,-272.28125 C 1060.6939,-272.50086 1063.3428,-272.61356 1065.25,-272.25 C 1065.5669,-272.18959 1065.8558,-272.06062 1066.125,-271.96875 C 1068.0612,-271.30783 1073.9688,-269.03125 1073.9688,-269.03125 C 1073.9687,-269.03125 1067.4321,-271.8378 1066.5938,-272.1875 C 1066.3933,-272.27113 1066.0176,-272.36083 1065.5625,-272.4375 C 1066.7662,-273.08796 1070.5816,-273.80945 1073.2813,-274.4375 C 1076.248,-275.1277 1076.5702,-275.19257 1078.5938,-275.3125 C 1080.6824,-275.4363 1081.875,-275.34375 1081.875,-275.34375 C 1081.875,-275.34374 1081.788,-275.9758 1082.875,-276.375 C 1083.6042,-276.6428 1087.9222,-277.71297 1090,-278.1875 C 1092.0085,-278.64619 1095.1679,-279.2168 1097,-278.8125 C 1098.8781,-278.39804 1110.5782,-275.79687 1110.5782,-275.79687 C 1110.5782,-275.79687 1098.2507,-278.81953 1097.4375,-279.0625 C 1097.243,-279.12062 1096.8789,-279.16876 1096.4375,-279.1875 C 1097.6051,-279.99119 1099.9517,-280.8748 1102.5469,-281.89062 C 1104.2283,-282.5488 1103.4706,-282.26721 1105.3228,-282.89422 C 1107.0764,-283.48788 1107.8082,-283.90493 1107.9532,-284.00721 C 1108.2993,-284.21372 1107.5972,-284.12909 1107.409,-284.04961 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7001);enable-background:new"
+           sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc" />
+        <path
+           id="path8095"
+           d="M 1082.625,-275.125 C 1084.498,-274.73152 1087.1211,-273.97945 1088.6563,-273.15625 C 1090.1915,-272.33306 1091.4785,-272.10025 1094.0313,-270.65625 C 1096.5579,-269.22699 1098.8271,-268.64929 1101,-268.125 C 1103.3476,-267.55858 1106.4354,-267.40977 1109.8438,-266.9375 C 1108.7549,-267.77725 1103.2364,-268.10995 1101.4375,-268.5 C 1099.6386,-268.89006 1097.5434,-269.51616 1094.8438,-270.8125 C 1092.1441,-272.10884 1091.3494,-272.61146 1089.0313,-273.5 C 1086.7131,-274.38854 1085.0269,-274.88314 1082.625,-275.125 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6949);enable-background:new" />
+        <path
+           id="path8097"
+           d="M 1051.4688,-270 C 1053.3741,-269.42241 1055.9969,-268.38428 1057.5625,-267.40625 C 1059.1281,-266.42823 1060.4427,-266.04644 1063.0625,-264.28125 C 1065.6555,-262.53409 1068.0484,-261.57198 1070.3125,-260.6875 C 1072.7586,-259.73193 1075.9951,-259.03037 1079.7188,-257.625 C 1078.5292,-258.76284 1072.6557,-260.31175 1070.7813,-261 C 1068.9068,-261.68825 1066.6995,-262.5662 1063.9063,-264.28125 C 1061.113,-265.99629 1060.3327,-266.56515 1057.9688,-267.6875 C 1055.6047,-268.80984 1053.9121,-269.52205 1051.4688,-270 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6961);enable-background:new" />
+        <path
+           id="path8099"
+           d="M 1020.2188,-266.84375 C 1022.1307,-266.20564 1024.8,-265.08839 1026.375,-264.03125 C 1027.9501,-262.9741 1029.2706,-262.52258 1031.9063,-260.625 C 1034.5149,-258.74679 1036.9347,-257.59497 1039.2188,-256.5625 C 1041.6865,-255.44705 1044.9833,-254.3892 1048.75,-252.71875 C 1047.5467,-253.94128 1041.5472,-256.03298 1039.6563,-256.84375 C 1037.7653,-257.65452 1035.5914,-258.73754 1032.7813,-260.59375 C 1029.9711,-262.44995 1029.1595,-263.07068 1026.7813,-264.3125 C 1024.403,-265.5543 1022.6706,-266.28819 1020.2188,-266.84375 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6957);enable-background:new" />
+        <path
+           id="path8101"
+           d="M 1110.1719,-266.89063 C 1110.3227,-266.84207 1110.8599,-266.25963 1110.2813,-265.40625 C 1109.4712,-264.21166 1104.5764,-262.08196 1101.7188,-261.28125 C 1098.8739,-260.48413 1095.4287,-260.30351 1091.1563,-261.65625 C 1086.8547,-263.0182 1085.6866,-264.12497 1080.5,-265.96875 C 1085.164,-263.85358 1086.6953,-262.01642 1090.625,-260.625 C 1092.2457,-260.05113 1093.9921,-259.6854 1095.6875,-259.59375 C 1095.2424,-259.26812 1094.1572,-258.61045 1092.125,-258 C 1089.3295,-257.16031 1085.4759,-256.46622 1083.875,-256.375 C 1082.3604,-256.28868 1080.733,-256.88749 1080.4375,-257 C 1080.6042,-256.89692 1080.8107,-256.62266 1080.1875,-255.96875 C 1079.2882,-255.02512 1074.0401,-254.04575 1071.0625,-253.71875 C 1068.0982,-253.3932 1064.5409,-253.73471 1060.1563,-255.625 C 1056.1783,-257.33997 1054.8173,-258.54036 1050.75,-260.375 C 1050.75,-260.375 1050.75,-260.21875 1050.75,-260.21875 C 1054.3931,-258.12346 1056.034,-256.33548 1059.625,-254.65625 C 1061.3552,-253.84716 1063.2167,-253.24749 1065.0313,-252.9375 C 1064.4964,-252.65074 1063.4735,-252.22599 1061.5938,-251.90625 C 1058.7248,-251.41829 1054.7848,-251.09011 1053.1563,-251.15625 C 1052.3056,-251.19079 1051.4277,-251.34062 1050.75,-251.5625 C 1050.0652,-251.77738 1049.5603,-252.00717 1049.4375,-252.0625 C 1049.6069,-251.95529 1049.8686,-251.65962 1049.2188,-251.03125 C 1048.3091,-250.15163 1042.9727,-249.69487 1039.9688,-249.5625 C 1036.9783,-249.43071 1033.3799,-250.01313 1028.9688,-252.125 C 1024.5276,-254.25126 1023.3273,-255.5266 1018.0625,-257.90625 C 1022.7968,-255.30921 1024.349,-253.27715 1028.4063,-251.1875 C 1030.0796,-250.32565 1031.8915,-249.69325 1033.6563,-249.25 C 1033.193,-249.01668 1032.0669,-248.56186 1029.9688,-248.3125 C 1027.0825,-247.96952 1023.1342,-247.81962 1021.5,-247.9375 C 1019.9538,-248.049 1018.2688,-248.79446 1017.9688,-248.9375 C 1018.1379,-248.81721 1018.3826,-248.52702 1017.75,-247.9375 C 1016.8372,-247.08677 1011.5059,-246.67538 1008.5,-246.5625 C 1005.5075,-246.45013 1001.9103,-247.05293 997.5,-249.15625 C 993.49875,-251.06448 992.11197,-252.29408 988.03125,-254.25 C 988.03122,-254.25 988.03125,-254.09375 988.03125,-254.09375 C 991.68631,-251.88983 993.32546,-250.0412 996.9375,-248.1875 C 998.67779,-247.29435 1000.5745,-246.65923 1002.4063,-246.21875 C 1001.8663,-245.97045 1000.8282,-245.60342 998.9375,-245.375 C 996.05182,-245.02642 992.07145,-244.85405 990.4375,-244.96875 C 989.58405,-245.02865 988.71119,-245.22666 988.03125,-245.46875 C 987.34415,-245.70405 986.8419,-245.94101 986.71875,-246 C 986.88873,-245.88773 987.18323,-245.57775 986.53125,-244.96875 C 985.6186,-244.11625 980.25592,-243.67538 977.25,-243.5625 C 974.25754,-243.45013 970.65654,-244.09055 966.25,-246.15625 C 961.81347,-248.23603 960.60312,-249.48796 955.34375,-251.8125 C 960.07313,-249.26501 961.63449,-247.2347 965.6875,-245.1875 C 967.35905,-244.34317 969.17304,-243.72107 970.9375,-243.28125 C 970.47427,-243.04703 969.3478,-242.59718 967.25,-242.34375 C 964.36431,-241.99517 960.4138,-241.77423 958.78125,-241.875 C 957.23669,-241.97032 955.58094,-242.70385 955.28125,-242.84375 C 955.45024,-242.72522 955.66317,-242.4399 955.03125,-241.84375 C 954.11939,-240.98347 948.7846,-240.5135 945.78125,-240.375 C 942.7913,-240.2371 939.2138,-240.82568 934.8125,-242.84375 C 930.81942,-244.67464 929.44739,-245.87295 925.375,-247.75 C 925.37498,-247.75 925.375,-247.59375 925.375,-247.59375 C 929.02261,-245.46048 930.64533,-243.65888 934.25,-241.875 C 935.98675,-241.01549 937.85727,-240.42486 939.6875,-240 C 939.14803,-239.7471 938.13687,-239.35871 936.25,-239.09375 C 933.37022,-238.68939 929.41187,-238.44813 927.78125,-238.53125 C 926.92953,-238.57466 926.05355,-238.7398 925.375,-238.96875 C 924.68931,-239.19076 924.1854,-239.41214 924.0625,-239.46875 C 924.23209,-239.35976 924.4944,-239.0591 923.84375,-238.4375 C 922.93296,-237.56736 917.59354,-237.04598 914.59375,-236.875 C 911.60742,-236.70479 908.01994,-237.19077 903.625,-239.15625 C 899.20011,-241.13513 898.01904,-242.38444 892.78125,-244.53125 C 897.49122,-242.14358 899.05142,-240.14252 903.09375,-238.1875 C 904.7609,-237.38119 906.55418,-236.79092 908.3125,-236.40625 C 907.85087,-236.15755 906.7155,-235.694 904.625,-235.375 C 901.7494,-234.93624 897.8446,-234.6419 896.21875,-234.6875 C 894.68052,-234.73062 892.98595,-235.43272 892.6875,-235.5625 C 892.85583,-235.44968 893.09807,-235.14875 892.46875,-234.53125 C 891.56063,-233.64015 886.2658,-233.003 883.28125,-232.71875 C 880.31007,-232.43577 876.70783,-232.89455 872.34375,-234.65625 C 868.38441,-236.25456 867.0146,-237.45112 863,-238.96875 C 863.00003,-238.96875 863,-238.8125 863,-238.8125 C 866.5959,-237.00115 868.23831,-235.23017 871.8125,-233.65625 C 873.53457,-232.8979 875.39998,-232.3673 877.21875,-232.03125 C 876.68266,-231.75217 875.65217,-231.34362 873.78125,-230.96875 C 870.92586,-230.39665 866.99183,-229.94936 865.375,-229.9375 C 864.53049,-229.93129 863.66892,-230.01844 863,-230.1875 C 862.32409,-230.34901 861.83991,-230.51673 861.71875,-230.5625 C 861.88597,-230.46848 862.14142,-230.17902 861.5,-229.5 C 860.60213,-228.54948 855.31352,-227.58292 852.375,-227.0625 C 849.44966,-226.54441 845.94285,-226.68826 841.65625,-228.09375 C 837.34045,-229.50882 836.18348,-230.62369 831.09375,-232.0625 C 835.6706,-230.31149 837.1823,-228.50244 841.125,-227.0625 C 842.75108,-226.46861 844.49385,-226.10685 846.21875,-225.90625 C 845.7659,-225.60923 844.66397,-225.02286 842.625,-224.4375 C 839.82028,-223.63233 835.98614,-222.86167 834.40625,-222.6875 C 832.9115,-222.5227 831.29002,-223.00431 831,-223.09375 C 831.16356,-223.00368 831.39278,-222.73382 830.78125,-222.03125 C 829.89878,-221.0174 824.73673,-219.6596 821.84375,-218.96875 C 818.96373,-218.28097 815.50815,-218.20873 811.28125,-219.40625 C 807.4464,-220.4927 806.10867,-221.47862 802.21875,-222.53125 C 802.21874,-222.53125 802.21875,-222.375 802.21875,-222.375 C 805.70293,-220.98015 807.28816,-219.4556 810.75,-218.34375 C 812.41793,-217.80803 814.20578,-217.55701 815.96875,-217.46875 C 815.44911,-217.11663 814.46836,-216.55423 812.65625,-215.9375 C 809.89059,-214.99625 806.06601,-214.00213 804.5,-213.78125 C 803.68206,-213.66586 802.8669,-213.65842 802.21875,-213.75 C 801.56379,-213.83321 801.08615,-213.96827 800.96875,-214 C 801.13079,-213.92536 801.40274,-213.65956 800.78125,-212.90625 C 799.91125,-211.85172 794.77162,-210.247 791.90625,-209.46875 C 789.05372,-208.69399 785.64713,-208.51055 781.46875,-209.5625 C 777.26192,-210.62163 776.11206,-211.60416 771.125,-212.71875 C 775.60954,-211.25929 777.09435,-209.58352 780.9375,-208.46875 C 782.52254,-208.00898 784.22429,-207.8305 785.90625,-207.78125 C 785.46468,-207.44449 784.39374,-206.75352 782.40625,-206 C 779.67232,-204.96351 775.95427,-203.83731 774.40625,-203.5625 C 772.94163,-203.30248 771.34667,-203.67904 771.0625,-203.75 C 771.22275,-203.67035 771.44294,-203.42902 770.84375,-202.6875 C 769.97909,-201.61744 764.92723,-199.86935 762.09375,-199 C 759.27295,-198.13453 755.88625,-197.84369 751.75,-198.78125 C 747.99741,-199.63186 746.70215,-200.49772 742.875,-201.375 C 742.875,-201.375 742.875,-201.21875 742.875,-201.21875 C 746.30296,-199.98096 747.86241,-198.58645 751.25,-197.6875 C 752.88216,-197.25436 754.61704,-197.10449 756.34375,-197.125 C 755.83482,-196.74083 754.867,-196.10318 753.09375,-195.375 C 750.38741,-194.26366 746.65742,-193.06719 745.125,-192.75 C 744.3246,-192.58431 743.51269,-192.53138 742.875,-192.59375 C 742.875,-192.59375 742.875,-192.07823 742.875,-191.67146 C 742.875,-191.40639 742.875,-191.1875 742.875,-191.1875 C 743.10145,-191.33218 743.32391,-191.46011 743.59375,-191.5625 C 744.67427,-191.97248 745.76536,-191.77827 749.59375,-193.25 C 753.42218,-194.72174 754.81787,-195.25498 755.5,-195.65625 C 756.1796,-196.05603 757.11165,-196.53562 757.71875,-197.1875 C 759.5456,-197.32525 761.2895,-197.68073 762.65625,-198.1875 C 765.62437,-199.28802 767.53162,-199.99369 769.4375,-200.65625 C 771.34336,-201.31879 771.79159,-202.07112 772.84375,-202.4375 C 773.9353,-202.81761 775.03886,-202.60288 778.90625,-203.96875 C 782.7737,-205.33461 784.18941,-205.79583 784.875,-206.1875 C 785.57609,-206.58802 786.57581,-207.12048 787.1875,-207.78125 C 789.1583,-207.83591 791.00435,-208.16588 792.46875,-208.65625 C 795.47023,-209.66133 797.3949,-210.27796 799.3125,-210.90625 C 800.8511,-211.41035 801.48652,-211.95302 802.21875,-212.34375 C 802.44891,-212.47806 802.69449,-212.59748 802.96875,-212.6875 C 804.06698,-213.04798 805.1502,-212.76887 809.0625,-214 C 812.97483,-215.23113 814.42855,-215.67295 815.125,-216.03125 C 815.81888,-216.38822 816.75515,-216.82386 817.375,-217.4375 C 819.24021,-217.46016 821.01081,-217.70433 822.40625,-218.125 C 825.43668,-219.03854 827.39863,-219.5551 829.34375,-220.09375 C 831.28886,-220.63239 831.76993,-221.35827 832.84375,-221.65625 C 833.95776,-221.9654 835.06369,-221.64886 839.03125,-222.6875 C 842.99886,-223.72613 844.44883,-224.12023 845.15625,-224.4375 C 845.89112,-224.76709 846.97008,-225.19122 847.59375,-225.8125 C 849.59149,-225.6965 851.45118,-225.83259 852.9375,-226.1875 C 856.01561,-226.9225 858.02094,-227.28844 860,-227.6875 C 861.58792,-228.00768 862.24429,-228.47805 863,-228.78125 C 863.23757,-228.88805 863.46695,-228.97401 863.75,-229.03125 C 864.88347,-229.26044 866.05448,-228.82232 870.09375,-229.53125 C 874.13308,-230.24018 875.594,-230.45834 876.3125,-230.71875 C 877.02836,-230.97819 878.01678,-231.28599 878.65625,-231.8125 C 880.58052,-231.57301 882.40413,-231.58797 883.84375,-231.8125 C 886.97008,-232.30012 888.9983,-232.51317 891,-232.78125 C 893.00171,-233.04932 893.48869,-233.72639 894.59375,-233.875 C 895.74014,-234.02918 896.86967,-233.57343 900.9375,-234.09375 C 905.00534,-234.61407 906.49763,-234.78948 907.21875,-235.03125 C 907.95585,-235.27839 909.01684,-235.61748 909.65625,-236.15625 C 911.70632,-235.82072 913.63003,-235.75829 915.15625,-235.9375 C 918.29856,-236.30646 920.33619,-236.49686 922.34375,-236.71875 C 923.95451,-236.89677 924.60842,-237.32695 925.375,-237.5625 C 925.61594,-237.64802 925.86912,-237.7181 926.15625,-237.75 C 927.30603,-237.87772 928.45754,-237.40335 932.53125,-237.875 C 936.60499,-238.34665 938.09034,-238.4856 938.8125,-238.71875 C 939.53196,-238.95102 940.51274,-239.19221 941.15625,-239.6875 C 943.09262,-239.35404 944.92631,-239.28326 946.375,-239.4375 C 949.52102,-239.77245 951.55256,-239.95609 953.5625,-240.15625 C 955.57246,-240.35639 956.04664,-240.98264 957.15625,-241.09375 C 958.30739,-241.20903 959.45268,-240.72869 963.53125,-241.15625 C 967.60986,-241.58381 969.12011,-241.71834 969.84375,-241.9375 C 970.5829,-242.16136 971.63947,-242.45075 972.28125,-242.96875 C 974.33835,-242.57008 976.28312,-242.47535 977.8125,-242.625 C 980.96123,-242.9331 982.98834,-243.09825 985,-243.28125 C 986.61407,-243.42807 987.2631,-243.8418 988.03125,-244.0625 C 988.27267,-244.14336 988.52478,-244.19241 988.8125,-244.21875 C 989.96461,-244.3242 991.10546,-243.826 995.1875,-244.21875 C 999.26958,-244.6115 1000.7764,-244.74959 1001.5,-244.96875 C 1002.2209,-245.18708 1003.1997,-245.41645 1003.8438,-245.90625 C 1005.7818,-245.55626 1007.6126,-245.45187 1009.0625,-245.59375 C 1012.2112,-245.90185 1014.2383,-246.067 1016.25,-246.25 C 1018.2616,-246.43299 1018.7642,-247.08802 1019.875,-247.1875 C 1021.0273,-247.29073 1022.1672,-246.80267 1026.25,-247.1875 C 1030.3329,-247.57232 1031.8387,-247.6885 1032.5625,-247.90625 C 1033.3018,-248.12868 1034.3581,-248.42074 1035,-248.9375 C 1037.0574,-248.53573 1039.0029,-248.43417 1040.5313,-248.59375 C 1043.6779,-248.92227 1045.7084,-249.11645 1047.7188,-249.3125 C 1049.3318,-249.46979 1049.9844,-249.94398 1050.75,-250.1875 C 1050.9907,-250.27554 1051.2132,-250.30887 1051.5,-250.34375 C 1052.6483,-250.48345 1053.8167,-250.00384 1057.875,-250.59375 C 1061.9333,-251.18367 1063.4368,-251.37089 1064.1563,-251.625 C 1064.873,-251.87816 1065.8308,-252.18307 1066.4688,-252.71875 C 1068.3885,-252.50681 1070.1887,-252.56734 1071.625,-252.8125 C 1074.7441,-253.3449 1076.7366,-253.74111 1078.7188,-254.125 C 1080.7009,-254.50887 1081.1931,-255.16465 1082.2813,-255.40625 C 1083.4101,-255.65691 1084.5516,-255.28996 1088.5313,-256.28125 C 1092.5109,-257.27253 1093.9609,-257.70055 1094.6563,-258.0625 C 1095.3786,-258.43851 1096.4182,-258.93308 1097.0313,-259.59375 C 1098.9943,-259.6058 1100.825,-259.8848 1102.25,-260.4375 C 1105.2012,-261.58211 1107.1232,-262.30692 1108.9375,-263.1875 C 1110.3932,-263.89403 1111.2723,-264.87391 1111.4844,-265.17188 C 1111.6966,-265.46984 1111.5962,-265.91718 1111.6223,-265.93863 C 1111.6652,-265.97387 1111.9416,-266.0236 1112.1013,-266.36707 C 1112.9602,-268.21415 1114.4223,-272.01166 1114.5365,-272.69652 C 1114.6502,-273.37868 1114.7003,-274.04426 1114.751,-274.44149 C 1114.7804,-274.67101 1114.6043,-275.30693 1114.6264,-275.36553 C 1114.6573,-275.44759 1114.9309,-275.63081 1114.9863,-275.88024 C 1115.2526,-277.07857 1115.0752,-278.07153 1114.8612,-279.48917 C 1114.6472,-280.90681 1113.8775,-284.11131 1113.2243,-284.96543 C 1112.5654,-285.82715 1112.0014,-285.9766 1111.4764,-285.96609 C 1111.2678,-285.69633 1111.6132,-285.703 1111.639,-285.65348 C 1112.3196,-285.60269 1112.573,-285.28484 1113.0582,-284.75686 C 1113.5434,-284.22888 1114.501,-280.8173 1114.6376,-279.36691 C 1114.7742,-277.91652 1114.8276,-276.50671 1114.5496,-275.89827 C 1114.2715,-275.28982 1113.6054,-275.46963 1113.313,-275.40375 C 1113.844,-275.21786 1114.2038,-275.19053 1114.2654,-274.34607 C 1114.3247,-273.53269 1114.1322,-272.70638 1113.7456,-271.54045 C 1113.3544,-270.36044 1111.9004,-267.19047 1111.4599,-266.94168 C 1111.0076,-266.68617 1110.5075,-266.75969 1110.1719,-266.89063 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6997);enable-background:new"
+           sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc" />
+        <path
+           id="path8103"
+           d="M 988.75,-263.84375 C 990.66161,-263.20935 993.30027,-262.08534 994.875,-261.03125 C 996.44977,-259.97716 997.7711,-259.54873 1000.4063,-257.65625 C 1003.0145,-255.78311 1005.4332,-254.64103 1007.7188,-253.59375 C 1010.1881,-252.46228 1013.4709,-251.43901 1017.25,-249.65625 C 1016.0428,-250.91465 1010.111,-253.0207 1008.2188,-253.84375 C 1006.3266,-254.66679 1004.0908,-255.77424 1001.2813,-257.625 C 998.47169,-259.47575 997.65906,-260.10654 995.28125,-261.34375 C 992.90343,-262.58094 991.20137,-263.29295 988.75,-263.84375 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6953);enable-background:new" />
+        <path
+           id="path8105"
+           d="M 957.5,-260.78125 C 959.41,-260.16315 962.08288,-259.07191 963.65625,-258.03125 C 965.22964,-256.99059 966.55233,-256.54873 969.1875,-254.65625 C 971.79573,-252.7831 974.21442,-251.64104 976.5,-250.59375 C 978.96931,-249.46228 982.25213,-248.439 986.03125,-246.65625 C 984.82397,-247.91465 978.82971,-250.05195 976.9375,-250.875 C 975.04533,-251.69804 972.84084,-252.8055 970.03125,-254.65625 C 967.22167,-256.507 966.4383,-257.09557 964.0625,-258.3125 C 961.68672,-259.52941 959.94929,-260.25135 957.5,-260.78125 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6993);enable-background:new" />
+        <path
+           id="path8107"
+           d="M 926.09375,-257.375 C 928.00147,-256.77755 930.64723,-255.71116 932.21875,-254.6875 C 933.79025,-253.66385 935.08897,-253.24779 937.71875,-251.40625 C 940.32166,-249.58352 942.74762,-248.43405 945.03125,-247.40625 C 947.49845,-246.29584 950.7866,-245.31302 954.5625,-243.5625 C 953.35627,-244.8106 947.3906,-246.88059 945.5,-247.6875 C 943.60942,-248.4944 941.39758,-249.57854 938.59375,-251.375 C 935.7899,-253.17144 934.96671,-253.77751 932.59375,-254.96875 C 930.22078,-256.15999 928.54013,-256.87158 926.09375,-257.375 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6989);enable-background:new" />
+        <path
+           id="path8109"
+           d="M 894.90625,-253.5625 C 896.80838,-253.00895 899.49326,-251.97363 901.0625,-250.96875 C 902.63173,-249.96388 903.93651,-249.56011 906.5625,-247.75 C 909.16162,-245.95836 911.56284,-244.87811 913.84375,-243.875 C 916.30803,-242.79126 919.60359,-241.83471 923.375,-240.125 C 922.1702,-241.36007 916.20084,-243.36978 914.3125,-244.15625 C 912.42418,-244.94272 910.2373,-245.98705 907.4375,-247.75 C 904.63773,-249.51294 903.83831,-250.11836 901.46875,-251.28125 C 899.09918,-252.44413 897.3455,-253.11537 894.90625,-253.5625 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6985);enable-background:new" />
+        <path
+           id="path8111"
+           d="M 863.71875,-248.65625 C 865.59937,-248.22716 868.22302,-247.27587 869.78125,-246.34375 C 871.33948,-245.41164 872.63358,-245.08599 875.25,-243.34375 C 877.83971,-241.61931 880.23067,-240.63573 882.5,-239.71875 C 884.95176,-238.72806 888.23959,-237.84168 892,-236.21875 C 890.79869,-237.42609 884.84751,-239.28484 882.96875,-240 C 881.09,-240.71517 878.88335,-241.68442 876.09375,-243.375 C 873.30412,-245.06557 872.50914,-245.60322 870.15625,-246.65625 C 867.80333,-247.70926 866.13041,-248.36873 863.71875,-248.65625 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6965);enable-background:new" />
+        <path
+           id="path8113"
+           d="M 833.15625,-241.375 C 835.00461,-241.07856 837.6257,-240.39868 839.15625,-239.59375 C 840.68683,-238.78882 841.96999,-238.53802 844.53125,-237.0625 C 847.06629,-235.60204 849.42193,-234.73741 851.65625,-234 C 854.07024,-233.20332 857.31336,-232.53311 861.03125,-231.15625 C 859.84354,-232.28498 853.94353,-233.746 852.09375,-234.3125 C 850.24398,-234.879 848.09033,-235.68642 845.34375,-237.15625 C 842.59718,-238.62608 841.84239,-239.07653 839.53125,-239.9375 C 837.2201,-240.79845 835.52654,-241.25759 833.15625,-241.375 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6981);enable-background:new" />
+        <path
+           id="path8115"
+           d="M 802.90625,-232.3125 C 804.72845,-232.10123 807.27201,-231.51193 808.78125,-230.78125 C 810.2905,-230.05059 811.53693,-229.85127 814.0625,-228.5 C 816.56226,-227.16254 818.89404,-226.45157 821.09375,-225.84375 C 823.47028,-225.18708 826.65839,-224.77087 830.3125,-223.65625 C 829.14515,-224.70121 823.38362,-225.75954 821.5625,-226.21875 C 819.74139,-226.67796 817.61025,-227.34571 814.90625,-228.65625 C 812.20222,-229.96677 811.43519,-230.37615 809.15625,-231.125 C 806.8773,-231.87383 805.243,-232.30431 802.90625,-232.3125 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6977);enable-background:new" />
+        <path
+           id="path8117"
+           d="M 773.1875,-222.1875 C 774.99859,-222.0088 777.50809,-221.52244 779,-220.84375 C 780.49194,-220.16506 781.7534,-220.04553 784.25,-218.78125 C 786.72107,-217.52987 789.04005,-216.88511 791.21875,-216.34375 C 793.57262,-215.75887 796.71009,-215.44623 800.3125,-214.5 C 799.16166,-215.49116 793.45999,-216.2833 791.65625,-216.6875 C 789.85253,-217.0917 787.74072,-217.70866 785.0625,-218.9375 C 782.38432,-220.16634 781.65905,-220.54839 779.40625,-221.21875 C 777.15346,-221.88909 775.50998,-222.22107 773.1875,-222.1875 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6973);enable-background:new" />
+        <path
+           id="path8119"
+           d="M 743.5625,-211.1875 C 745.35531,-211.05839 747.83563,-210.63785 749.3125,-210 C 750.7894,-209.36215 752.0286,-209.25844 754.5,-208.0625 C 756.94618,-206.87878 759.22054,-206.31584 761.375,-205.84375 C 763.70267,-205.33372 766.7946,-205.16311 770.375,-204.28125 C 769.23121,-205.25185 763.62741,-205.8719 761.84375,-206.21875 C 760.06008,-206.56559 757.9609,-207.10631 755.3125,-208.25 C 752.66409,-209.39368 751.91755,-209.76631 749.6875,-210.375 C 747.45742,-210.98368 745.86156,-211.28466 743.5625,-211.1875 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6969);enable-background:new" />
+        <g
+           id="g8121"
+           style="fill:#ffffff;fill-opacity:1;filter:url(#filter7345)">
+          <path
+             sodipodi:nodetypes="czzzczzc"
+             id="path8123"
+             d="M 744.9375,-212.11731 C 744.9375,-212.11731 752.15979,-215.34049 754,-215.61731 C 755.84021,-215.89413 757.35225,-215.62054 760,-215.05481 C 762.64775,-214.48908 768.7357,-212.83963 771.1875,-211.67981 C 773.6393,-210.51999 776.5,-208.11731 776.5,-208.11731 C 776.5,-208.11731 769.35356,-210.8975 766.3125,-211.67981 C 763.27144,-212.46212 758.66789,-213.76355 755.9375,-213.99231 C 753.20711,-214.22107 744.9375,-212.11731 744.9375,-212.11731 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+          <path
+             sodipodi:nodetypes="czzzczzc"
+             id="path8125"
+             d="M 735.46875,-206.95416 C 735.46875,-206.95416 739.12854,-209.17734 740.96875,-209.45416 C 742.80896,-209.73098 744.6335,-209.20739 747.28125,-208.64166 C 749.929,-208.07593 756.01695,-206.42648 758.46875,-205.26666 C 760.92055,-204.10684 765.03125,-203.14166 765.03125,-203.14166 C 765.03125,-203.14166 756.63481,-204.48435 753.59375,-205.26666 C 750.55269,-206.04897 745.63664,-207.6004 742.90625,-207.82916 C 740.17586,-208.05792 735.46875,-206.95416 735.46875,-206.95416 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             sodipodi:nodetypes="czzzczzc"
+             id="path8127"
+             d="M 759.85042,-217.61116 C 759.85042,-217.61116 768.39412,-220.90973 770.2482,-221.06902 C 772.10229,-221.22832 773.88986,-220.58982 776.4963,-219.85694 C 779.10274,-219.12406 785.07354,-217.091 787.44666,-215.77769 C 789.81978,-214.46438 793.86083,-213.23987 793.86083,-213.23987 C 793.86083,-213.23987 785.5667,-215.11352 782.58152,-216.08754 C 779.59633,-217.06156 774.78883,-218.92232 772.0785,-219.32416 C 769.36817,-219.726 759.85042,-217.61116 759.85042,-217.61116 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             sodipodi:nodetypes="czzzczzc"
+             id="path8129"
+             d="M 775.19813,-223.2266 C 775.19813,-223.2266 782.96946,-226.00904 784.82644,-226.13009 C 786.68341,-226.25113 788.45744,-225.57592 791.04822,-224.78947 C 793.63899,-224.00302 799.56662,-221.8473 801.91216,-220.48535 C 804.25771,-219.1234 808.27265,-217.81585 808.27265,-217.81585 C 808.27265,-217.81585 800.01892,-219.86008 797.05444,-220.89543 C 794.08997,-221.93078 789.32185,-223.89024 786.62038,-224.34786 C 783.91891,-224.80549 775.19813,-223.2266 775.19813,-223.2266 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-4.3190906"
+             inkscape:transform-center-x="13.852145"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8131"
+             d="M 789.64298,-227.95417 C 789.64298,-227.95417 798.32554,-231.47448 800.18452,-231.55952 C 802.04349,-231.64455 803.8041,-230.9351 806.37915,-230.09859 C 808.9542,-229.2621 814.83894,-226.99193 817.15766,-225.58479 C 819.47638,-224.17764 823.46523,-222.79255 823.46523,-222.79255 C 823.46523,-222.79255 815.25266,-224.99632 812.3088,-226.08891 C 809.36494,-227.1815 804.63568,-229.23299 801.94358,-229.74288 C 799.25149,-230.25276 789.64298,-227.95417 789.64298,-227.95417 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-4.3190906"
+             inkscape:transform-center-x="13.852145"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8133"
+             d="M 804.49513,-233.32948 C 804.49513,-233.32948 812.30269,-235.91229 814.16167,-235.99733 C 816.02064,-236.08236 817.78125,-235.37291 820.3563,-234.5364 C 822.93135,-233.69991 828.81609,-231.42974 831.13481,-230.0226 C 833.45353,-228.61545 837.44238,-227.23036 837.44238,-227.23036 C 837.44238,-227.23036 829.22981,-229.43413 826.28595,-230.52672 C 823.34209,-231.61931 818.61283,-233.6708 815.92073,-234.18069 C 813.22864,-234.69057 804.49513,-233.32948 804.49513,-233.32948 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-4.3190906"
+             inkscape:transform-center-x="13.852145"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8135"
+             d="M 819.55763,-237.57948 C 819.55763,-237.57948 828.11519,-240.16229 829.97417,-240.24733 C 831.83314,-240.33236 833.59375,-239.62291 836.1688,-238.7864 C 838.74385,-237.94991 844.62859,-235.67974 846.94731,-234.2726 C 849.26603,-232.86545 853.25488,-231.48036 853.25488,-231.48036 C 853.25488,-231.48036 845.04231,-233.68413 842.09845,-234.77672 C 839.15459,-235.86931 834.42533,-237.9208 831.73323,-238.43069 C 829.04114,-238.94057 819.55763,-237.57948 819.55763,-237.57948 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-4.9269042"
+             inkscape:transform-center-x="13.64141"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8137"
+             d="M 836.23395,-242.60125 C 836.23395,-242.60125 843.20097,-244.58848 845.06179,-244.56882 C 846.9226,-244.54915 848.64052,-243.7418 851.16444,-242.76177 C 853.68837,-241.78177 859.4361,-239.18419 861.672,-237.64886 C 863.9079,-236.11351 867.81253,-234.50625 867.81253,-234.50625 C 867.81253,-234.50625 859.73692,-237.16847 856.85917,-238.42491 C 853.98143,-239.68136 849.37505,-241.99561 846.71589,-242.65612 C 844.05674,-243.31661 836.23395,-242.60125 836.23395,-242.60125 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.1542119"
+             inkscape:transform-center-x="13.55068"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8139"
+             d="M 850.73028,-246.00461 C 850.73028,-246.00461 858.41812,-248.03229 860.2781,-247.97315 C 862.13807,-247.914 863.83848,-247.07036 866.34103,-246.03699 C 868.84358,-245.00365 874.5349,-242.28467 876.73771,-240.70224 C 878.94053,-239.11979 882.81016,-237.43004 882.81016,-237.43004 C 882.81016,-237.43004 874.79287,-240.26302 871.94244,-241.58026 C 869.09201,-242.89749 864.53578,-245.30898 861.89124,-246.02576 C 859.2467,-246.74254 850.73028,-246.00461 850.73028,-246.00461 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.4740887"
+             inkscape:transform-center-x="13.41151"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8141"
+             d="M 864.82496,-249.21081 C 864.82496,-249.21081 872.99448,-251.17987 874.85184,-251.06477 C 876.70919,-250.94965 878.38342,-250.05521 880.85374,-248.94698 C 883.32405,-247.83877 888.93094,-244.94971 891.08512,-243.30167 C 893.2393,-241.65363 897.05632,-239.84815 897.05632,-239.84815 C 897.05632,-239.84815 889.12793,-242.92121 886.31845,-244.32365 C 883.50896,-245.72609 879.02739,-248.27364 876.40562,-249.06971 C 873.78386,-249.86577 864.82496,-249.21081 864.82496,-249.21081 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.79376"
+             inkscape:transform-center-x="13.258805"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8143"
+             d="M 881.38485,-251.60282 C 881.38485,-251.60282 889.47021,-253.51091 891.32322,-253.33946 C 893.17622,-253.16799 894.82252,-252.22313 897.25804,-251.04038 C 899.69357,-249.85767 905.21013,-246.79968 907.31327,-245.08699 C 909.41641,-243.37429 913.17684,-241.45373 913.17684,-241.45373 C 913.17684,-241.45373 905.34544,-244.76613 902.57984,-246.25323 C 899.81423,-247.74035 895.41209,-250.42282 892.8157,-251.29814 C 890.21933,-252.17345 881.38485,-251.60282 881.38485,-251.60282 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8145"
+             d="M 896.58415,-254.34724 C 896.58415,-254.34724 904.22581,-255.77494 906.07962,-255.61239 C 907.93342,-255.44983 909.58424,-254.51289 912.02541,-253.34186 C 914.46659,-252.17086 919.99779,-249.1394 922.10913,-247.43684 C 924.22047,-245.73426 927.99009,-243.83179 927.99009,-243.83179 C 927.99009,-243.83179 920.14286,-247.10653 917.37014,-248.58034 C 914.59743,-250.05414 910.18245,-252.71543 907.58189,-253.57827 C 904.98134,-254.44109 896.58415,-254.34724 896.58415,-254.34724 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8147"
+             d="M 911.45328,-255.98544 C 911.45328,-255.98544 920.09494,-257.53814 921.94875,-257.37559 C 923.80255,-257.21303 925.45337,-256.27609 927.89454,-255.10506 C 930.33572,-253.93406 935.86692,-250.9026 937.97826,-249.20004 C 940.0896,-247.49746 943.85922,-245.59499 943.85922,-245.59499 C 943.85922,-245.59499 936.01199,-248.86973 933.23927,-250.34354 C 930.46656,-251.81734 926.05158,-254.47863 923.45102,-255.34147 C 920.85047,-256.20429 911.45328,-255.98544 911.45328,-255.98544 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8149"
+             d="M 927.70328,-258.29794 C 927.70328,-258.29794 935.34494,-259.16314 937.19875,-259.00059 C 939.05255,-258.83803 940.70337,-257.90109 943.14454,-256.73006 C 945.58572,-255.55906 951.11692,-252.5276 953.22826,-250.82504 C 955.3396,-249.12246 959.10922,-247.21999 959.10922,-247.21999 C 959.10922,-247.21999 951.26199,-250.49473 948.48927,-251.96854 C 945.71656,-253.44234 941.30158,-256.10363 938.70102,-256.96647 C 936.10047,-257.82929 927.70328,-258.29794 927.70328,-258.29794 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8151"
+             d="M 942.82828,-259.48544 C 942.82828,-259.48544 951.40744,-260.97564 953.26125,-260.81309 C 955.11505,-260.65053 956.76587,-259.71359 959.20704,-258.54256 C 961.64822,-257.37156 967.17942,-254.3401 969.29076,-252.63754 C 971.4021,-250.93496 975.17172,-249.03249 975.17172,-249.03249 C 975.17172,-249.03249 967.32449,-252.30723 964.55177,-253.78104 C 961.77906,-255.25484 957.36408,-257.91613 954.76352,-258.77897 C 952.16297,-259.64179 942.82828,-259.48544 942.82828,-259.48544 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8153"
+             d="M 959.07828,-261.54794 C 959.07828,-261.54794 966.90744,-262.35064 968.76125,-262.18809 C 970.61505,-262.02553 972.26587,-261.08859 974.70704,-259.91756 C 977.14822,-258.74656 982.67942,-255.7151 984.79076,-254.01254 C 986.9021,-252.30996 990.67172,-250.40749 990.67172,-250.40749 C 990.67172,-250.40749 982.82449,-253.68223 980.05177,-255.15604 C 977.27906,-256.62984 972.86408,-259.29113 970.26352,-260.15397 C 967.66297,-261.01679 959.07828,-261.54794 959.07828,-261.54794 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8155"
+             d="M 974.45328,-262.79794 C 974.45328,-262.79794 982.84494,-263.97564 984.69875,-263.81309 C 986.55255,-263.65053 988.20337,-262.71359 990.64454,-261.54256 C 993.08572,-260.37156 998.61692,-257.3401 1000.7283,-255.63754 C 1002.8396,-253.93496 1006.6092,-252.03249 1006.6092,-252.03249 C 1006.6092,-252.03249 998.76199,-255.30723 995.98927,-256.78104 C 993.21656,-258.25484 988.80158,-260.91613 986.20102,-261.77897 C 983.60047,-262.64179 974.45328,-262.79794 974.45328,-262.79794 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8157"
+             d="M 990.64078,-264.86044 C 990.64078,-264.86044 997.53244,-265.85064 999.38625,-265.68809 C 1001.2401,-265.52553 1002.8909,-264.58859 1005.332,-263.41756 C 1007.7732,-262.24656 1013.3044,-259.2151 1015.4158,-257.51254 C 1017.5271,-255.80996 1021.2967,-253.90749 1021.2967,-253.90749 C 1021.2967,-253.90749 1013.4495,-257.18223 1010.6768,-258.65604 C 1007.9041,-260.12984 1003.4891,-262.79113 1000.8885,-263.65397 C 998.28797,-264.51679 990.64078,-264.86044 990.64078,-264.86044 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8159"
+             d="M 1007.7658,-265.79794 C 1007.7658,-265.79794 1014.5949,-266.97564 1016.4488,-266.81309 C 1018.3026,-266.65053 1019.9534,-265.71359 1022.3945,-264.54256 C 1024.8357,-263.37156 1030.3669,-260.3401 1032.4783,-258.63754 C 1034.5896,-256.93496 1038.3592,-255.03249 1038.3592,-255.03249 C 1038.3592,-255.03249 1030.512,-258.30723 1027.7393,-259.78104 C 1024.9666,-261.25484 1020.5516,-263.91613 1017.951,-264.77897 C 1015.3505,-265.64179 1007.7658,-265.79794 1007.7658,-265.79794 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8161"
+             d="M 1023.8908,-267.79794 C 1023.8908,-267.79794 1029.9699,-268.22564 1031.8238,-268.06309 C 1033.6776,-267.90053 1035.3284,-266.96359 1037.7695,-265.79256 C 1040.2107,-264.62156 1045.7419,-261.5901 1047.8533,-259.88754 C 1049.9646,-258.18496 1053.7342,-256.28249 1053.7342,-256.28249 C 1053.7342,-256.28249 1045.887,-259.55723 1043.1143,-261.03104 C 1040.3416,-262.50484 1035.9266,-265.16613 1033.326,-266.02897 C 1030.7255,-266.89179 1023.8908,-267.79794 1023.8908,-267.79794 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.7433893"
+             inkscape:transform-center-x="13.28378"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8163"
+             d="M 1039.7033,-269.17294 C 1039.7033,-269.17294 1046.1574,-269.85064 1048.0113,-269.68809 C 1049.8651,-269.52553 1051.5159,-268.58859 1053.957,-267.41756 C 1056.3982,-266.24656 1061.9294,-263.2151 1064.0408,-261.51254 C 1066.1521,-259.80996 1069.9217,-257.90749 1069.9217,-257.90749 C 1069.9217,-257.90749 1062.0745,-261.18223 1059.3018,-262.65604 C 1056.5291,-264.12984 1052.1141,-266.79113 1049.5135,-267.65397 C 1046.913,-268.51679 1039.7033,-269.17294 1039.7033,-269.17294 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-5.1360724"
+             inkscape:transform-center-x="13.55813"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8165"
+             d="M 1055.2718,-271.03319 C 1055.2718,-271.03319 1060.7694,-271.94264 1062.6296,-271.88667 C 1064.4897,-271.83067 1066.1915,-270.98993 1068.6957,-269.96081 C 1071.2001,-268.93171 1076.896,-266.22241 1079.1015,-264.64372 C 1081.307,-263.06501 1085.1795,-261.38182 1085.1795,-261.38182 C 1085.1795,-261.38182 1077.1575,-264.20121 1074.3047,-265.5136 C 1071.4521,-266.82598 1066.8918,-269.22973 1064.246,-269.94203 C 1061.6003,-270.65431 1055.2718,-271.03319 1055.2718,-271.03319 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-4.6370147"
+             inkscape:transform-center-x="13.74758"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8167"
+             d="M 1072.7007,-273.48537 C 1072.7007,-273.48537 1077.2479,-274.64118 1079.1087,-274.67158 C 1080.9694,-274.70196 1082.7083,-273.94109 1085.2576,-273.02927 C 1087.807,-272.1175 1093.6225,-269.67541 1095.899,-268.20077 C 1098.1753,-266.72609 1102.1217,-265.22441 1102.1217,-265.22441 C 1102.1217,-265.22441 1093.9775,-267.66852 1091.067,-268.84713 C 1088.1565,-270.02573 1083.4896,-272.21528 1080.8136,-272.80404 C 1078.1377,-273.39279 1072.7007,-273.48537 1072.7007,-273.48537 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             inkscape:transform-center-y="-4.4842392"
+             inkscape:transform-center-x="13.79933"
+             sodipodi:nodetypes="czzzczzc"
+             id="path8169"
+             d="M 1087.1585,-276.5244 C 1087.1585,-276.5244 1093.1185,-278.29795 1094.9787,-278.35464 C 1096.8387,-278.41131 1098.5883,-277.67509 1101.1502,-276.79939 C 1103.7122,-275.92373 1103.6728,-275.94226 1106.4837,-275.30924 C 1109.2806,-274.67938 1113.5604,-273.79611 1113.5604,-273.79611 C 1113.5604,-273.79611 1109.9449,-273.81239 1106.7681,-274.26225 C 1103.6526,-274.70344 1099.3938,-275.9605 1096.7097,-276.51138 C 1094.0258,-277.06226 1087.1585,-276.5244 1087.1585,-276.5244 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+          <path
+             sodipodi:nodetypes="czczc"
+             id="path8171"
+             d="M 1099.25,-279.92981 C 1099.4112,-279.66119 1110.4581,-284.53027 1111.4375,-284.61731 C 1112.4169,-284.70435 1113.4375,-281.49231 1113.4375,-281.49231 C 1113.4375,-281.49231 1112.6624,-282.99665 1110.5625,-282.55481 C 1108.4626,-282.11297 1099.2616,-279.8834 1099.25,-279.92981 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+        </g>
+        <path
+           id="path8173"
+           d="M 1107.4532,-284.0938 C 1107.0345,-283.88097 1107.2976,-283.99991 1106.806,-283.78799 C 1106.3199,-283.57845 1105.0826,-283.2136 1102.7264,-282.32904 C 1099.3953,-281.07847 1096.8962,-280.1756 1095.7005,-279.26294 C 1094.1644,-279.24168 1091.98,-279.02963 1090.0442,-278.54419 C 1087.0627,-277.79653 1085.189,-277.37018 1083.2942,-276.95044 C 1081.3994,-276.53072 1081.6187,-276.30825 1080.4192,-276.07544 C 1079.1226,-275.82378 1078.6978,-276.08443 1074.9817,-275.29419 C 1071.4918,-274.55205 1066.0869,-273.36312 1064.8255,-272.60669 C 1063.2416,-272.78748 1060.958,-272.92847 1058.9817,-272.63794 C 1055.9413,-272.19099 1054.0655,-271.96518 1052.138,-271.73169 C 1051.4826,-271.65232 1051.0969,-271.53091 1050.7942,-271.45044 C 1050.368,-271.31879 1050.1084,-271.19042 1049.4192,-271.10669 C 1048.1076,-270.94733 1047.657,-271.26352 1043.888,-270.82544 C 1040.3341,-270.41236 1034.8826,-269.55262 1033.638,-268.88794 C 1032.039,-269.18524 1029.7802,-269.42213 1027.7942,-269.23169 C 1024.7354,-268.93838 1022.8222,-268.7477 1020.888,-268.57544 C 1018.9537,-268.40318 1019.1993,-268.15307 1017.9817,-268.04419 C 1016.6655,-267.9265 1016.2219,-268.20782 1012.4505,-267.79419 C 1008.9086,-267.40575 1003.4426,-266.58492 1002.1692,-265.91919 C 1000.5703,-266.21389 998.28202,-266.4262 996.29419,-266.23169 C 993.23595,-265.93245 991.35306,-265.75145 989.41919,-265.57544 C 988.7617,-265.5156 988.37915,-265.39688 988.07544,-265.32544 C 987.64779,-265.20649 987.39193,-265.10737 986.70044,-265.04419 C 985.38448,-264.92394 984.94068,-265.23907 981.16919,-264.82544 C 977.61305,-264.43543 972.16365,-263.58628 970.91919,-262.91919 C 969.32056,-263.21338 967.05935,-263.44291 965.07544,-263.23169 C 962.01984,-262.90637 960.1014,-262.70545 958.16919,-262.51294 C 956.23698,-262.32044 956.47932,-262.07206 955.26294,-261.95044 C 953.94806,-261.81898 953.49996,-262.11498 949.73169,-261.66919 C 946.19282,-261.25054 940.75401,-260.37702 939.48169,-259.70044 C 937.88414,-259.98149 935.62173,-260.12087 933.63794,-259.88794 C 930.58596,-259.52958 928.69286,-259.32008 926.76294,-259.10669 C 926.10674,-259.03414 925.72228,-258.934 925.41919,-258.85669 C 924.99242,-258.72947 924.73428,-258.58949 924.04419,-258.51294 C 922.73086,-258.36726 922.27673,-258.68696 918.51294,-258.20044 C 914.96405,-257.74169 909.53431,-256.78142 908.29419,-256.07544 C 906.70114,-256.31968 904.46038,-256.45679 902.48169,-256.20044 C 899.4341,-255.80563 897.53098,-255.55199 895.60669,-255.29419 C 893.68241,-255.0364 893.88058,-254.80066 892.66919,-254.63794 C 891.35973,-254.46204 890.922,-254.74232 887.16919,-254.16919 C 883.6449,-253.63095 878.24604,-252.47002 876.98169,-251.73169 C 875.39419,-251.93523 873.13619,-251.98642 871.16919,-251.63794 C 868.14302,-251.10182 866.2703,-250.77625 864.35669,-250.45044 C 863.70608,-250.33967 863.34298,-250.1795 863.04419,-250.07544 C 862.62352,-249.91056 862.38074,-249.74414 861.70044,-249.60669 C 860.40579,-249.3451 859.97332,-249.61289 856.26294,-248.79419 C 852.76441,-248.02224 847.41699,-246.41126 846.20044,-245.57544 C 844.63766,-245.65289 842.44286,-245.49016 840.51294,-244.98169 C 837.5405,-244.19856 835.69533,-243.7496 833.82544,-243.23169 C 831.95556,-242.71379 832.15884,-242.46441 830.98169,-242.13794 C 829.70923,-241.78504 829.28466,-242.03085 825.63794,-240.95044 C 822.21324,-239.93581 816.9885,-238.01727 815.76294,-237.10669 C 814.22411,-237.09395 812.04311,-236.83447 810.13794,-236.23169 C 807.20688,-235.30435 805.38763,-234.77327 803.54419,-234.16919 C 802.91743,-233.96381 802.55246,-233.77661 802.26294,-233.63794 C 801.85531,-233.42433 801.6096,-233.22919 800.95044,-233.01294 C 799.69598,-232.6014 799.26433,-232.8239 795.66919,-231.57544 C 792.27934,-230.39827 787.07421,-228.36174 785.88794,-227.41919 C 784.36405,-227.35952 782.23789,-227.02432 780.35669,-226.35669 C 777.4593,-225.3284 775.65761,-224.68121 773.82544,-224.04419 C 771.99327,-223.40718 772.19759,-223.19565 771.04419,-222.79419 C 769.79741,-222.36023 769.38058,-222.59447 765.82544,-221.23169 C 762.48677,-219.95189 757.33829,-217.74914 756.13794,-216.76294 C 754.63076,-216.65525 752.50225,-216.26414 750.63794,-215.54419 C 747.76976,-214.43659 746.01414,-213.76263 744.20044,-213.07544 C 743.58378,-212.84181 743.20403,-212.63341 742.91919,-212.48169 C 742.91919,-212.48169 742.91919,-211.38794 742.91919,-211.38794 C 743.03097,-211.6103 743.30518,-212.20537 743.82544,-212.48169 C 744.52341,-212.85241 748.63907,-214.47506 750.63794,-215.20044 C 752.2948,-215.80169 754.79183,-216.52912 756.60669,-216.51294 C 756.90831,-216.51025 757.19431,-216.46204 757.45044,-216.41919 C 759.29293,-216.11094 764.91919,-214.85669 764.91919,-214.85669 C 764.91918,-214.85669 758.6857,-216.50344 757.88794,-216.70044 C 757.69715,-216.74755 757.35222,-216.76916 756.91919,-216.76294 C 758.06465,-217.63265 761.68019,-219.15645 764.26294,-220.20044 C 767.10116,-221.34771 767.37975,-221.45226 769.32544,-221.85669 C 771.33374,-222.27413 772.48169,-222.35669 772.48169,-222.35669 C 772.48169,-222.35668 772.39933,-222.95783 773.45044,-223.48169 C 774.15554,-223.8331 778.33746,-225.37409 780.35669,-226.04419 C 782.30859,-226.69192 785.41409,-227.40269 787.23169,-227.04419 C 789.09492,-226.67669 794.76294,-225.23169 794.76294,-225.23169 C 794.76295,-225.23169 788.47594,-227.1028 787.66919,-227.32544 C 787.47627,-227.37869 787.13835,-227.41148 786.70044,-227.41919 C 787.85878,-228.25207 791.49488,-229.61451 794.10669,-230.57544 C 796.97685,-231.63145 797.27403,-231.73724 799.23169,-232.10669 C 801.08518,-232.45648 802.09053,-232.53217 802.26294,-232.54419 C 802.37654,-232.76143 802.64039,-233.35421 803.16919,-233.60669 C 803.87863,-233.94543 808.09526,-235.31944 810.13794,-235.91919 C 811.83111,-236.4163 814.37871,-236.95596 816.23169,-236.82544 C 816.53964,-236.80376 816.84518,-236.72818 817.10669,-236.66919 C 818.98787,-236.24487 824.70044,-234.63794 824.70044,-234.63794 C 824.70045,-234.63794 818.3587,-236.70319 817.54419,-236.95044 C 817.3494,-237.00958 816.98631,-237.05438 816.54419,-237.07544 C 817.71368,-237.87299 821.40721,-239.13166 824.04419,-240.01294 C 826.942,-240.98141 827.2772,-241.01626 829.26294,-241.29419 C 831.31259,-241.58108 832.45044,-241.60669 832.45044,-241.60669 C 832.45042,-241.60669 832.37769,-242.21366 833.45044,-242.66919 C 834.17004,-242.97476 838.44142,-244.16994 840.51294,-244.66919 C 842.51538,-245.15177 845.71143,-245.59748 847.57544,-245.07544 C 849.48622,-244.54029 855.29419,-242.57544 855.29419,-242.57544 C 855.29419,-242.57544 848.87153,-244.99895 848.04419,-245.29419 C 847.84635,-245.3648 847.46203,-245.43458 847.01294,-245.48169 C 848.20084,-246.21034 851.92821,-247.25577 854.60669,-247.98169 C 857.55011,-248.77944 857.89877,-248.75252 859.91919,-248.88794 C 861.83208,-249.01617 862.86624,-248.95903 863.04419,-248.95044 C 863.16147,-249.1541 863.43595,-249.72992 863.98169,-249.91919 C 864.71388,-250.17313 869.06021,-250.96708 871.16919,-251.29419 C 872.91732,-251.5653 875.57007,-251.77889 877.48169,-251.38794 C 877.79935,-251.32298 878.08691,-251.20243 878.35669,-251.10669 C 880.29743,-250.41796 886.20044,-248.01294 886.20044,-248.01294 C 886.20045,-248.01294 879.66573,-250.96371 878.82544,-251.32544 C 878.62447,-251.41195 878.25031,-251.49223 877.79419,-251.57544 C 879.00069,-252.20862 882.82375,-252.97104 885.54419,-253.48169 C 888.53372,-254.04288 888.84442,-254.01123 890.88794,-254.01294 C 892.9972,-254.01471 894.20044,-253.88794 894.20044,-253.88794 C 894.20044,-253.88793 894.12773,-254.51913 895.23169,-254.82544 C 895.97221,-255.03091 900.35781,-255.65931 902.48169,-255.88794 C 904.53471,-256.10893 907.80032,-256.14016 909.70044,-255.41919 C 911.64823,-254.68012 917.54419,-252.04419 917.54419,-252.04419 C 917.54421,-252.04419 910.98131,-255.22316 910.13794,-255.60669 C 909.93626,-255.69842 909.59573,-255.7929 909.13794,-255.88794 C 910.34886,-256.48982 914.12236,-257.13678 916.85669,-257.54419 C 919.86149,-257.99191 920.1822,-257.99589 922.23169,-257.95044 C 924.17214,-257.90742 925.23868,-257.75621 925.41919,-257.73169 C 925.53811,-257.92485 925.80309,-258.49752 926.35669,-258.63794 C 927.0994,-258.82632 931.51098,-259.37222 933.63794,-259.57544 C 935.40097,-259.74386 938.05803,-259.80973 939.98169,-259.32544 C 940.30137,-259.24496 940.5852,-259.12185 940.85669,-259.01294 C 942.80962,-258.22945 948.76294,-255.54419 948.76294,-255.54419 C 948.76292,-255.54419 942.17103,-258.79767 941.32544,-259.20044 C 941.12322,-259.29676 940.75318,-259.40747 940.29419,-259.51294 C 941.50833,-260.08721 945.33785,-260.63513 948.07544,-261.01294 C 951.08382,-261.42814 951.39851,-261.45557 953.45044,-261.38794 C 955.56842,-261.31813 956.76294,-261.13794 956.76294,-261.13794 C 956.76292,-261.13794 956.68569,-261.77535 957.79419,-262.04419 C 958.53781,-262.22454 962.94595,-262.70774 965.07544,-262.88794 C 967.13391,-263.06211 970.41868,-263.01226 972.32544,-262.23169 C 974.28003,-261.43153 980.20044,-258.70044 980.20044,-258.70044 C 980.20042,-258.70044 973.64051,-262.0092 972.79419,-262.41919 C 972.59182,-262.51724 972.22233,-262.62229 971.76294,-262.73169 C 972.97811,-263.29559 976.77302,-263.84599 979.51294,-264.20044 C 982.52385,-264.58996 982.83425,-264.59809 984.88794,-264.51294 C 986.83233,-264.43234 987.89457,-264.2597 988.07544,-264.23169 C 988.1946,-264.42255 988.45821,-264.977 989.01294,-265.10669 C 989.7572,-265.28069 994.16287,-265.75716 996.29419,-265.91919 C 998.06081,-266.05346 1000.7439,-266.0449 1002.6692,-265.54419 C 1002.9892,-265.46098 1003.2725,-265.34292 1003.5442,-265.23169 C 1005.4988,-264.43153 1011.4505,-261.66919 1011.4505,-261.66919 C 1011.4504,-261.66919 1004.8593,-265.0092 1004.013,-265.41919 C 1003.8106,-265.51724 1003.4411,-265.6223 1002.9817,-265.73169 C 1004.1968,-266.29559 1008.023,-266.81475 1010.763,-267.16919 C 1013.7739,-267.55872 1014.1155,-267.59809 1016.1692,-267.51294 C 1018.2889,-267.42506 1019.4817,-267.20044 1019.4817,-267.20044 C 1019.4817,-267.20044 1019.4033,-267.84946 1020.513,-268.10669 C 1021.2573,-268.27925 1025.6625,-268.73005 1027.7942,-268.88794 C 1029.8548,-269.04054 1033.1371,-268.98471 1035.0442,-268.20044 C 1036.9992,-267.39649 1042.9192,-264.70044 1042.9192,-264.70044 C 1042.9192,-264.70044 1036.3594,-267.97631 1035.513,-268.38794 C 1035.3105,-268.48638 1034.9412,-268.59016 1034.4817,-268.70044 C 1035.6971,-269.26198 1039.4936,-269.82822 1042.2317,-270.20044 C 1045.2407,-270.60949 1045.5544,-270.61602 1047.6067,-270.54419 C 1049.5498,-270.4762 1050.6139,-270.37934 1050.7942,-270.35669 C 1050.913,-270.55109 1051.1788,-271.0855 1051.7317,-271.23169 C 1052.4735,-271.42781 1056.8628,-272.06047 1058.9817,-272.32544 C 1060.7381,-272.54505 1063.387,-272.65775 1065.2942,-272.29419 C 1065.6111,-272.23378 1065.9,-272.10481 1066.1692,-272.01294 C 1068.1054,-271.35202 1074.013,-269.07544 1074.013,-269.07544 C 1074.0129,-269.07544 1067.4763,-271.88199 1066.638,-272.23169 C 1066.4375,-272.31532 1066.0618,-272.40502 1065.6067,-272.48169 C 1066.8104,-273.13215 1070.6258,-273.85364 1073.3255,-274.48169 C 1076.2922,-275.17189 1076.6144,-275.23676 1078.638,-275.35669 C 1080.7266,-275.48049 1081.9192,-275.38794 1081.9192,-275.38794 C 1081.9192,-275.38793 1081.8322,-276.01999 1082.9192,-276.41919 C 1083.6484,-276.68699 1087.9664,-277.75716 1090.0442,-278.23169 C 1092.0527,-278.69038 1095.2121,-279.26099 1097.0442,-278.85669 C 1098.9223,-278.44223 1110.6224,-275.84106 1110.6224,-275.84106 C 1110.6224,-275.84106 1098.2949,-278.86372 1097.4817,-279.10669 C 1097.2872,-279.16481 1096.9231,-279.21295 1096.4817,-279.23169 C 1097.6493,-280.03538 1099.9959,-280.91899 1102.5911,-281.93481 C 1104.2725,-282.59299 1103.5148,-282.3114 1105.367,-282.93841 C 1107.1206,-283.53207 1107.8524,-283.94912 1107.9974,-284.0514 C 1108.3435,-284.25791 1107.6414,-284.17328 1107.4532,-284.0938 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7333);enable-background:new"
+           sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc" />
+        <path
+           id="path8175"
+           d="M 1082.625,-275.125 C 1084.498,-274.73152 1087.1211,-273.97945 1088.6563,-273.15625 C 1090.1915,-272.33306 1091.4785,-272.10025 1094.0313,-270.65625 C 1096.5579,-269.22699 1098.8271,-268.64929 1101,-268.125 C 1103.3476,-267.55858 1106.4354,-267.40977 1109.8438,-266.9375 C 1108.7549,-267.77725 1103.2364,-268.10995 1101.4375,-268.5 C 1099.6386,-268.89006 1097.5434,-269.51616 1094.8438,-270.8125 C 1092.1441,-272.10884 1091.3494,-272.61146 1089.0313,-273.5 C 1086.7131,-274.38854 1085.0269,-274.88314 1082.625,-275.125 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7285);enable-background:new" />
+        <path
+           id="path8177"
+           d="M 1051.4688,-270 C 1053.3741,-269.42241 1055.9969,-268.38428 1057.5625,-267.40625 C 1059.1281,-266.42823 1060.4427,-266.04644 1063.0625,-264.28125 C 1065.6555,-262.53409 1068.0484,-261.57198 1070.3125,-260.6875 C 1072.7586,-259.73193 1075.9951,-259.03037 1079.7188,-257.625 C 1078.5292,-258.76284 1072.6557,-260.31175 1070.7813,-261 C 1068.9068,-261.68825 1066.6995,-262.5662 1063.9063,-264.28125 C 1061.113,-265.99629 1060.3327,-266.56515 1057.9688,-267.6875 C 1055.6047,-268.80984 1053.9121,-269.52205 1051.4688,-270 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7289);enable-background:new" />
+        <path
+           id="path8179"
+           d="M 1020.2188,-266.84375 C 1022.1307,-266.20564 1024.8,-265.08839 1026.375,-264.03125 C 1027.9501,-262.9741 1029.2706,-262.52258 1031.9063,-260.625 C 1034.5149,-258.74679 1036.9347,-257.59497 1039.2188,-256.5625 C 1041.6865,-255.44705 1044.9833,-254.3892 1048.75,-252.71875 C 1047.5467,-253.94128 1041.5472,-256.03298 1039.6563,-256.84375 C 1037.7653,-257.65452 1035.5914,-258.73754 1032.7813,-260.59375 C 1029.9711,-262.44995 1029.1595,-263.07068 1026.7813,-264.3125 C 1024.403,-265.5543 1022.6706,-266.28819 1020.2188,-266.84375 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7293);enable-background:new" />
+        <path
+           id="path8181"
+           d="M 1110.1719,-266.89063 C 1110.3227,-266.84207 1110.8599,-266.25963 1110.2813,-265.40625 C 1109.4712,-264.21166 1104.5764,-262.08196 1101.7188,-261.28125 C 1098.8739,-260.48413 1095.4287,-260.30351 1091.1563,-261.65625 C 1086.8547,-263.0182 1085.6866,-264.12497 1080.5,-265.96875 C 1085.164,-263.85358 1086.6953,-262.01642 1090.625,-260.625 C 1092.2457,-260.05113 1093.9921,-259.6854 1095.6875,-259.59375 C 1095.2424,-259.26812 1094.1572,-258.61045 1092.125,-258 C 1089.3295,-257.16031 1085.4759,-256.46622 1083.875,-256.375 C 1082.3604,-256.28868 1080.733,-256.88749 1080.4375,-257 C 1080.6042,-256.89692 1080.8107,-256.62266 1080.1875,-255.96875 C 1079.2882,-255.02512 1074.0401,-254.04575 1071.0625,-253.71875 C 1068.0982,-253.3932 1064.5409,-253.73471 1060.1563,-255.625 C 1056.1783,-257.33997 1054.8173,-258.54036 1050.75,-260.375 C 1050.75,-260.375 1050.75,-260.21875 1050.75,-260.21875 C 1054.3931,-258.12346 1056.034,-256.33548 1059.625,-254.65625 C 1061.3552,-253.84716 1063.2167,-253.24749 1065.0313,-252.9375 C 1064.4964,-252.65074 1063.4735,-252.22599 1061.5938,-251.90625 C 1058.7248,-251.41829 1054.7848,-251.09011 1053.1563,-251.15625 C 1052.3056,-251.19079 1051.4277,-251.34062 1050.75,-251.5625 C 1050.0652,-251.77738 1049.5603,-252.00717 1049.4375,-252.0625 C 1049.6069,-251.95529 1049.8686,-251.65962 1049.2188,-251.03125 C 1048.3091,-250.15163 1042.9727,-249.69487 1039.9688,-249.5625 C 1036.9783,-249.43071 1033.3799,-250.01313 1028.9688,-252.125 C 1024.5276,-254.25126 1023.3273,-255.5266 1018.0625,-257.90625 C 1022.7968,-255.30921 1024.349,-253.27715 1028.4063,-251.1875 C 1030.0796,-250.32565 1031.8915,-249.69325 1033.6563,-249.25 C 1033.193,-249.01668 1032.0669,-248.56186 1029.9688,-248.3125 C 1027.0825,-247.96952 1023.1342,-247.81962 1021.5,-247.9375 C 1019.9538,-248.049 1018.2688,-248.79446 1017.9688,-248.9375 C 1018.1379,-248.81721 1018.3826,-248.52702 1017.75,-247.9375 C 1016.8372,-247.08677 1011.5059,-246.67538 1008.5,-246.5625 C 1005.5075,-246.45013 1001.9103,-247.05293 997.5,-249.15625 C 993.49875,-251.06448 992.11197,-252.29408 988.03125,-254.25 C 988.03122,-254.25 988.03125,-254.09375 988.03125,-254.09375 C 991.68631,-251.88983 993.32546,-250.0412 996.9375,-248.1875 C 998.67779,-247.29435 1000.5745,-246.65923 1002.4063,-246.21875 C 1001.8663,-245.97045 1000.8282,-245.60342 998.9375,-245.375 C 996.05182,-245.02642 992.07145,-244.85405 990.4375,-244.96875 C 989.58405,-245.02865 988.71119,-245.22666 988.03125,-245.46875 C 987.34415,-245.70405 986.8419,-245.94101 986.71875,-246 C 986.88873,-245.88773 987.18323,-245.57775 986.53125,-244.96875 C 985.6186,-244.11625 980.25592,-243.67538 977.25,-243.5625 C 974.25754,-243.45013 970.65654,-244.09055 966.25,-246.15625 C 961.81347,-248.23603 960.60312,-249.48796 955.34375,-251.8125 C 960.07313,-249.26501 961.63449,-247.2347 965.6875,-245.1875 C 967.35905,-244.34317 969.17304,-243.72107 970.9375,-243.28125 C 970.47427,-243.04703 969.3478,-242.59718 967.25,-242.34375 C 964.36431,-241.99517 960.4138,-241.77423 958.78125,-241.875 C 957.23669,-241.97032 955.58094,-242.70385 955.28125,-242.84375 C 955.45024,-242.72522 955.66317,-242.4399 955.03125,-241.84375 C 954.11939,-240.98347 948.7846,-240.5135 945.78125,-240.375 C 942.7913,-240.2371 939.2138,-240.82568 934.8125,-242.84375 C 930.81942,-244.67464 929.44739,-245.87295 925.375,-247.75 C 925.37498,-247.75 925.375,-247.59375 925.375,-247.59375 C 929.02261,-245.46048 930.64533,-243.65888 934.25,-241.875 C 935.98675,-241.01549 937.85727,-240.42486 939.6875,-240 C 939.14803,-239.7471 938.13687,-239.35871 936.25,-239.09375 C 933.37022,-238.68939 929.41187,-238.44813 927.78125,-238.53125 C 926.92953,-238.57466 926.05355,-238.7398 925.375,-238.96875 C 924.68931,-239.19076 924.1854,-239.41214 924.0625,-239.46875 C 924.23209,-239.35976 924.4944,-239.0591 923.84375,-238.4375 C 922.93296,-237.56736 917.59354,-237.04598 914.59375,-236.875 C 911.60742,-236.70479 908.01994,-237.19077 903.625,-239.15625 C 899.20011,-241.13513 898.01904,-242.38444 892.78125,-244.53125 C 897.49122,-242.14358 899.05142,-240.14252 903.09375,-238.1875 C 904.7609,-237.38119 906.55418,-236.79092 908.3125,-236.40625 C 907.85087,-236.15755 906.7155,-235.694 904.625,-235.375 C 901.7494,-234.93624 897.8446,-234.6419 896.21875,-234.6875 C 894.68052,-234.73062 892.98595,-235.43272 892.6875,-235.5625 C 892.85583,-235.44968 893.09807,-235.14875 892.46875,-234.53125 C 891.56063,-233.64015 886.2658,-233.003 883.28125,-232.71875 C 880.31007,-232.43577 876.70783,-232.89455 872.34375,-234.65625 C 868.38441,-236.25456 867.0146,-237.45112 863,-238.96875 C 863.00003,-238.96875 863,-238.8125 863,-238.8125 C 866.5959,-237.00115 868.23831,-235.23017 871.8125,-233.65625 C 873.53457,-232.8979 875.39998,-232.3673 877.21875,-232.03125 C 876.68266,-231.75217 875.65217,-231.34362 873.78125,-230.96875 C 870.92586,-230.39665 866.99183,-229.94936 865.375,-229.9375 C 864.53049,-229.93129 863.66892,-230.01844 863,-230.1875 C 862.32409,-230.34901 861.83991,-230.51673 861.71875,-230.5625 C 861.88597,-230.46848 862.14142,-230.17902 861.5,-229.5 C 860.60213,-228.54948 855.31352,-227.58292 852.375,-227.0625 C 849.44966,-226.54441 845.94285,-226.68826 841.65625,-228.09375 C 837.34045,-229.50882 836.18348,-230.62369 831.09375,-232.0625 C 835.6706,-230.31149 837.1823,-228.50244 841.125,-227.0625 C 842.75108,-226.46861 844.49385,-226.10685 846.21875,-225.90625 C 845.7659,-225.60923 844.66397,-225.02286 842.625,-224.4375 C 839.82028,-223.63233 835.98614,-222.86167 834.40625,-222.6875 C 832.9115,-222.5227 831.29002,-223.00431 831,-223.09375 C 831.16356,-223.00368 831.39278,-222.73382 830.78125,-222.03125 C 829.89878,-221.0174 824.73673,-219.6596 821.84375,-218.96875 C 818.96373,-218.28097 815.50815,-218.20873 811.28125,-219.40625 C 807.4464,-220.4927 806.10867,-221.47862 802.21875,-222.53125 C 802.21874,-222.53125 802.21875,-222.375 802.21875,-222.375 C 805.70293,-220.98015 807.28816,-219.4556 810.75,-218.34375 C 812.41793,-217.80803 814.20578,-217.55701 815.96875,-217.46875 C 815.44911,-217.11663 814.46836,-216.55423 812.65625,-215.9375 C 809.89059,-214.99625 806.06601,-214.00213 804.5,-213.78125 C 803.68206,-213.66586 802.8669,-213.65842 802.21875,-213.75 C 801.56379,-213.83321 801.08615,-213.96827 800.96875,-214 C 801.13079,-213.92536 801.40274,-213.65956 800.78125,-212.90625 C 799.91125,-211.85172 794.77162,-210.247 791.90625,-209.46875 C 789.05372,-208.69399 785.64713,-208.51055 781.46875,-209.5625 C 777.26192,-210.62163 776.11206,-211.60416 771.125,-212.71875 C 775.60954,-211.25929 777.09435,-209.58352 780.9375,-208.46875 C 782.52254,-208.00898 784.22429,-207.8305 785.90625,-207.78125 C 785.46468,-207.44449 784.39374,-206.75352 782.40625,-206 C 779.67232,-204.96351 775.95427,-203.83731 774.40625,-203.5625 C 772.94163,-203.30248 771.34667,-203.67904 771.0625,-203.75 C 771.22275,-203.67035 771.44294,-203.42902 770.84375,-202.6875 C 769.97909,-201.61744 764.92723,-199.86935 762.09375,-199 C 759.27295,-198.13453 755.88625,-197.84369 751.75,-198.78125 C 747.99741,-199.63186 746.70215,-200.49772 742.875,-201.375 C 742.875,-201.375 742.875,-201.21875 742.875,-201.21875 C 746.30296,-199.98096 747.86241,-198.58645 751.25,-197.6875 C 752.88216,-197.25436 754.61704,-197.10449 756.34375,-197.125 C 755.83482,-196.74083 754.867,-196.10318 753.09375,-195.375 C 750.38741,-194.26366 746.65742,-193.06719 745.125,-192.75 C 744.3246,-192.58431 743.51269,-192.53138 742.875,-192.59375 C 742.875,-192.59375 742.875,-192.07823 742.875,-191.67146 C 742.875,-191.40639 742.875,-191.1875 742.875,-191.1875 C 743.10145,-191.33218 743.32391,-191.46011 743.59375,-191.5625 C 744.67427,-191.97248 745.76536,-191.77827 749.59375,-193.25 C 753.42218,-194.72174 754.81787,-195.25498 755.5,-195.65625 C 756.1796,-196.05603 757.11165,-196.53562 757.71875,-197.1875 C 759.5456,-197.32525 761.2895,-197.68073 762.65625,-198.1875 C 765.62437,-199.28802 767.53162,-199.99369 769.4375,-200.65625 C 771.34336,-201.31879 771.79159,-202.07112 772.84375,-202.4375 C 773.9353,-202.81761 775.03886,-202.60288 778.90625,-203.96875 C 782.7737,-205.33461 784.18941,-205.79583 784.875,-206.1875 C 785.57609,-206.58802 786.57581,-207.12048 787.1875,-207.78125 C 789.1583,-207.83591 791.00435,-208.16588 792.46875,-208.65625 C 795.47023,-209.66133 797.3949,-210.27796 799.3125,-210.90625 C 800.8511,-211.41035 801.48652,-211.95302 802.21875,-212.34375 C 802.44891,-212.47806 802.69449,-212.59748 802.96875,-212.6875 C 804.06698,-213.04798 805.1502,-212.76887 809.0625,-214 C 812.97483,-215.23113 814.42855,-215.67295 815.125,-216.03125 C 815.81888,-216.38822 816.75515,-216.82386 817.375,-217.4375 C 819.24021,-217.46016 821.01081,-217.70433 822.40625,-218.125 C 825.43668,-219.03854 827.39863,-219.5551 829.34375,-220.09375 C 831.28886,-220.63239 831.76993,-221.35827 832.84375,-221.65625 C 833.95776,-221.9654 835.06369,-221.64886 839.03125,-222.6875 C 842.99886,-223.72613 844.44883,-224.12023 845.15625,-224.4375 C 845.89112,-224.76709 846.97008,-225.19122 847.59375,-225.8125 C 849.59149,-225.6965 851.45118,-225.83259 852.9375,-226.1875 C 856.01561,-226.9225 858.02094,-227.28844 860,-227.6875 C 861.58792,-228.00768 862.24429,-228.47805 863,-228.78125 C 863.23757,-228.88805 863.46695,-228.97401 863.75,-229.03125 C 864.88347,-229.26044 866.05448,-228.82232 870.09375,-229.53125 C 874.13308,-230.24018 875.594,-230.45834 876.3125,-230.71875 C 877.02836,-230.97819 878.01678,-231.28599 878.65625,-231.8125 C 880.58052,-231.57301 882.40413,-231.58797 883.84375,-231.8125 C 886.97008,-232.30012 888.9983,-232.51317 891,-232.78125 C 893.00171,-233.04932 893.48869,-233.72639 894.59375,-233.875 C 895.74014,-234.02918 896.86967,-233.57343 900.9375,-234.09375 C 905.00534,-234.61407 906.49763,-234.78948 907.21875,-235.03125 C 907.95585,-235.27839 909.01684,-235.61748 909.65625,-236.15625 C 911.70632,-235.82072 913.63003,-235.75829 915.15625,-235.9375 C 918.29856,-236.30646 920.33619,-236.49686 922.34375,-236.71875 C 923.95451,-236.89677 924.60842,-237.32695 925.375,-237.5625 C 925.61594,-237.64802 925.86912,-237.7181 926.15625,-237.75 C 927.30603,-237.87772 928.45754,-237.40335 932.53125,-237.875 C 936.60499,-238.34665 938.09034,-238.4856 938.8125,-238.71875 C 939.53196,-238.95102 940.51274,-239.19221 941.15625,-239.6875 C 943.09262,-239.35404 944.92631,-239.28326 946.375,-239.4375 C 949.52102,-239.77245 951.55256,-239.95609 953.5625,-240.15625 C 955.57246,-240.35639 956.04664,-240.98264 957.15625,-241.09375 C 958.30739,-241.20903 959.45268,-240.72869 963.53125,-241.15625 C 967.60986,-241.58381 969.12011,-241.71834 969.84375,-241.9375 C 970.5829,-242.16136 971.63947,-242.45075 972.28125,-242.96875 C 974.33835,-242.57008 976.28312,-242.47535 977.8125,-242.625 C 980.96123,-242.9331 982.98834,-243.09825 985,-243.28125 C 986.61407,-243.42807 987.2631,-243.8418 988.03125,-244.0625 C 988.27267,-244.14336 988.52478,-244.19241 988.8125,-244.21875 C 989.96461,-244.3242 991.10546,-243.826 995.1875,-244.21875 C 999.26958,-244.6115 1000.7764,-244.74959 1001.5,-244.96875 C 1002.2209,-245.18708 1003.1997,-245.41645 1003.8438,-245.90625 C 1005.7818,-245.55626 1007.6126,-245.45187 1009.0625,-245.59375 C 1012.2112,-245.90185 1014.2383,-246.067 1016.25,-246.25 C 1018.2616,-246.43299 1018.7642,-247.08802 1019.875,-247.1875 C 1021.0273,-247.29073 1022.1672,-246.80267 1026.25,-247.1875 C 1030.3329,-247.57232 1031.8387,-247.6885 1032.5625,-247.90625 C 1033.3018,-248.12868 1034.3581,-248.42074 1035,-248.9375 C 1037.0574,-248.53573 1039.0029,-248.43417 1040.5313,-248.59375 C 1043.6779,-248.92227 1045.7084,-249.11645 1047.7188,-249.3125 C 1049.3318,-249.46979 1049.9844,-249.94398 1050.75,-250.1875 C 1050.9907,-250.27554 1051.2132,-250.30887 1051.5,-250.34375 C 1052.6483,-250.48345 1053.8167,-250.00384 1057.875,-250.59375 C 1061.9333,-251.18367 1063.4368,-251.37089 1064.1563,-251.625 C 1064.873,-251.87816 1065.8308,-252.18307 1066.4688,-252.71875 C 1068.3885,-252.50681 1070.1887,-252.56734 1071.625,-252.8125 C 1074.7441,-253.3449 1076.7366,-253.74111 1078.7188,-254.125 C 1080.7009,-254.50887 1081.1931,-255.16465 1082.2813,-255.40625 C 1083.4101,-255.65691 1084.5516,-255.28996 1088.5313,-256.28125 C 1092.5109,-257.27253 1093.9609,-257.70055 1094.6563,-258.0625 C 1095.3786,-258.43851 1096.4182,-258.93308 1097.0313,-259.59375 C 1098.9943,-259.6058 1100.825,-259.8848 1102.25,-260.4375 C 1105.2012,-261.58211 1107.1232,-262.30692 1108.9375,-263.1875 C 1110.3932,-263.89403 1111.2723,-264.87391 1111.4844,-265.17188 C 1111.6966,-265.46984 1111.5962,-265.91718 1111.6223,-265.93863 C 1111.6652,-265.97387 1111.9416,-266.0236 1112.1013,-266.36707 C 1112.9602,-268.21415 1114.4223,-272.01166 1114.5365,-272.69652 C 1114.6502,-273.37868 1114.7003,-274.04426 1114.751,-274.44149 C 1114.7804,-274.67101 1114.6043,-275.30693 1114.6264,-275.36553 C 1114.6573,-275.44759 1114.9309,-275.63081 1114.9863,-275.88024 C 1115.2526,-277.07857 1115.0752,-278.07153 1114.8612,-279.48917 C 1114.6472,-280.90681 1113.8775,-284.11131 1113.2243,-284.96543 C 1112.5654,-285.82715 1112.0014,-285.9766 1111.4764,-285.96609 C 1111.2678,-285.69633 1111.6132,-285.703 1111.639,-285.65348 C 1112.3196,-285.60269 1112.573,-285.28484 1113.0582,-284.75686 C 1113.5434,-284.22888 1114.28,-280.90569 1114.4166,-279.4553 C 1114.5532,-278.00491 1114.6066,-276.5951 1114.3286,-275.98666 C 1114.0505,-275.37821 1113.6054,-275.46963 1113.313,-275.40375 C 1113.844,-275.21786 1113.9828,-275.27892 1114.0444,-274.43446 C 1114.1037,-273.62108 1113.9112,-272.79477 1113.5246,-271.62884 C 1113.1334,-270.44883 1111.6794,-267.27886 1111.2389,-267.03007 C 1110.7866,-266.77456 1110.5075,-266.75969 1110.1719,-266.89063 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7337);enable-background:new"
+           sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc" />
+        <path
+           id="path8183"
+           d="M 988.75,-263.84375 C 990.66161,-263.20935 993.30027,-262.08534 994.875,-261.03125 C 996.44977,-259.97716 997.7711,-259.54873 1000.4063,-257.65625 C 1003.0145,-255.78311 1005.4332,-254.64103 1007.7188,-253.59375 C 1010.1881,-252.46228 1013.4709,-251.43901 1017.25,-249.65625 C 1016.0428,-250.91465 1010.111,-253.0207 1008.2188,-253.84375 C 1006.3266,-254.66679 1004.0908,-255.77424 1001.2813,-257.625 C 998.47169,-259.47575 997.65906,-260.10654 995.28125,-261.34375 C 992.90343,-262.58094 991.20137,-263.29295 988.75,-263.84375 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7297);enable-background:new" />
+        <path
+           id="path8185"
+           d="M 957.5,-260.78125 C 959.41,-260.16315 962.08288,-259.07191 963.65625,-258.03125 C 965.22964,-256.99059 966.55233,-256.54873 969.1875,-254.65625 C 971.79573,-252.7831 974.21442,-251.64104 976.5,-250.59375 C 978.96931,-249.46228 982.25213,-248.439 986.03125,-246.65625 C 984.82397,-247.91465 978.82971,-250.05195 976.9375,-250.875 C 975.04533,-251.69804 972.84084,-252.8055 970.03125,-254.65625 C 967.22167,-256.507 966.4383,-257.09557 964.0625,-258.3125 C 961.68672,-259.52941 959.94929,-260.25135 957.5,-260.78125 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7301);enable-background:new" />
+        <path
+           id="path8187"
+           d="M 926.09375,-257.375 C 928.00147,-256.77755 930.64723,-255.71116 932.21875,-254.6875 C 933.79025,-253.66385 935.08897,-253.24779 937.71875,-251.40625 C 940.32166,-249.58352 942.74762,-248.43405 945.03125,-247.40625 C 947.49845,-246.29584 950.7866,-245.31302 954.5625,-243.5625 C 953.35627,-244.8106 947.3906,-246.88059 945.5,-247.6875 C 943.60942,-248.4944 941.39758,-249.57854 938.59375,-251.375 C 935.7899,-253.17144 934.96671,-253.77751 932.59375,-254.96875 C 930.22078,-256.15999 928.54013,-256.87158 926.09375,-257.375 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7305);enable-background:new" />
+        <path
+           id="path8189"
+           d="M 894.90625,-253.5625 C 896.80838,-253.00895 899.49326,-251.97363 901.0625,-250.96875 C 902.63173,-249.96388 903.93651,-249.56011 906.5625,-247.75 C 909.16162,-245.95836 911.56284,-244.87811 913.84375,-243.875 C 916.30803,-242.79126 919.60359,-241.83471 923.375,-240.125 C 922.1702,-241.36007 916.20084,-243.36978 914.3125,-244.15625 C 912.42418,-244.94272 910.2373,-245.98705 907.4375,-247.75 C 904.63773,-249.51294 903.83831,-250.11836 901.46875,-251.28125 C 899.09918,-252.44413 897.3455,-253.11537 894.90625,-253.5625 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7309);enable-background:new" />
+        <path
+           id="path8191"
+           d="M 863.71875,-248.65625 C 865.59937,-248.22716 868.22302,-247.27587 869.78125,-246.34375 C 871.33948,-245.41164 872.63358,-245.08599 875.25,-243.34375 C 877.83971,-241.61931 880.23067,-240.63573 882.5,-239.71875 C 884.95176,-238.72806 888.23959,-237.84168 892,-236.21875 C 890.79869,-237.42609 884.84751,-239.28484 882.96875,-240 C 881.09,-240.71517 878.88335,-241.68442 876.09375,-243.375 C 873.30412,-245.06557 872.50914,-245.60322 870.15625,-246.65625 C 867.80333,-247.70926 866.13041,-248.36873 863.71875,-248.65625 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7313);enable-background:new" />
+        <path
+           id="path8193"
+           d="M 833.15625,-241.375 C 835.00461,-241.07856 837.6257,-240.39868 839.15625,-239.59375 C 840.68683,-238.78882 841.96999,-238.53802 844.53125,-237.0625 C 847.06629,-235.60204 849.42193,-234.73741 851.65625,-234 C 854.07024,-233.20332 857.31336,-232.53311 861.03125,-231.15625 C 859.84354,-232.28498 853.94353,-233.746 852.09375,-234.3125 C 850.24398,-234.879 848.09033,-235.68642 845.34375,-237.15625 C 842.59718,-238.62608 841.84239,-239.07653 839.53125,-239.9375 C 837.2201,-240.79845 835.52654,-241.25759 833.15625,-241.375 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7317);enable-background:new" />
+        <path
+           id="path8195"
+           d="M 802.90625,-232.3125 C 804.72845,-232.10123 807.27201,-231.51193 808.78125,-230.78125 C 810.2905,-230.05059 811.53693,-229.85127 814.0625,-228.5 C 816.56226,-227.16254 818.89404,-226.45157 821.09375,-225.84375 C 823.47028,-225.18708 826.65839,-224.77087 830.3125,-223.65625 C 829.14515,-224.70121 823.38362,-225.75954 821.5625,-226.21875 C 819.74139,-226.67796 817.61025,-227.34571 814.90625,-228.65625 C 812.20222,-229.96677 811.43519,-230.37615 809.15625,-231.125 C 806.8773,-231.87383 805.243,-232.30431 802.90625,-232.3125 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7321);enable-background:new" />
+        <path
+           id="path8197"
+           d="M 773.1875,-222.1875 C 774.99859,-222.0088 777.50809,-221.52244 779,-220.84375 C 780.49194,-220.16506 781.7534,-220.04553 784.25,-218.78125 C 786.72107,-217.52987 789.04005,-216.88511 791.21875,-216.34375 C 793.57262,-215.75887 796.71009,-215.44623 800.3125,-214.5 C 799.16166,-215.49116 793.45999,-216.2833 791.65625,-216.6875 C 789.85253,-217.0917 787.74072,-217.70866 785.0625,-218.9375 C 782.38432,-220.16634 781.65905,-220.54839 779.40625,-221.21875 C 777.15346,-221.88909 775.50998,-222.22107 773.1875,-222.1875 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7329);enable-background:new" />
+        <path
+           id="path8199"
+           d="M 743.5625,-211.1875 C 745.35531,-211.05839 747.83563,-210.63785 749.3125,-210 C 750.7894,-209.36215 752.0286,-209.25844 754.5,-208.0625 C 756.94618,-206.87878 759.22054,-206.31584 761.375,-205.84375 C 763.70267,-205.33372 766.7946,-205.16311 770.375,-204.28125 C 769.23121,-205.25185 763.62741,-205.8719 761.84375,-206.21875 C 760.06008,-206.56559 757.9609,-207.10631 755.3125,-208.25 C 752.66409,-209.39368 751.91755,-209.76631 749.6875,-210.375 C 747.45742,-210.98368 745.86156,-211.28466 743.5625,-211.1875 z"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter7325);enable-background:new" />
+      </g>
+    </g>
+    <path
+       style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+       d="M 863.87812,475.6679 C 865.52024,472.4499 867.39593,469.93261 868.73948,465.81892 C 869.5382,462.16103 872.05152,463.78819 875.99995,457.42202 C 877.40188,455.18252 881.47648,457.81338 884.96505,455.02291 C 886.23577,454.21972 887.84993,454.6186 889.44761,454.95978 C 893.213,456.27874 895.27337,458.66333 897.78137,460.76815 C 903.92043,466.73838 918.31551,468.71142 921.26741,467.08161 C 922.70146,464.17687 929.14869,461.67273 933.64178,455.96993 C 934.38989,454.84726 945.37114,447.22547 948.28899,449.40394"
+       id="path8201"
+       sodipodi:nodetypes="ccccccccc" />
+    <path
+       style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+       d="M 888.50059,465.25071 C 895.864,462.01774 902.31149,456.34231 909.20872,451.86619 C 912.51929,449.89665 916.07855,455.0822 920.00472,455.46485 C 922.30245,455.24672 923.71762,456.66744 925.68683,457.10635 C 930.84319,458.42414 928.08476,460.97123 935.66209,463.54607 C 941.8177,465.26647 944.56949,456.7476 950.56184,456.22247 C 955.43923,455.71948 958.66076,455.90644 962.17859,455.96993 C 966.10555,456.10882 966.25714,452.47233 968.23951,450.66663 C 971.22007,447.86141 975.39512,448.81691 978.38436,445.92573 C 979.4019,444.54105 980.33894,442.91488 981.11895,440.81764 C 982.00096,438.8173 984.15901,441.12362 985.91718,442.08033"
+       id="path8203"
+       sodipodi:nodetypes="ccccccccccc" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer15"
+     inkscape:label="Feet"
+     style="display:inline">
+    <path
+       style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9048);enable-background:accumulate"
+       d="M 403.27922,1056.3058 L 459.84776,1013.8794 L 531.97265,1028.0215 L 485.30361,1080.3474 L 431.56349,1087.4185 L 403.27922,1056.3058 z"
+       id="path8994" />
+    <path
+       style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+       d="M 542.27183,1060.5719 C 540.86456,1079.3731 541.12693,1093.3229 544.35357,1109.8752 C 547.58023,1126.4275 560.75966,1155.7825 564.68798,1173.0589 C 568.61419,1190.326 567.38211,1211.3686 552.22854,1224.2072 C 536.91093,1237.1846 510.17726,1245.8061 484.39623,1239.9409 C 458.61518,1234.0757 414.84716,1190.7175 395.80604,1169.7126 C 376.6939,1148.6293 332.04518,1075.862 317.86751,1045.4368 C 303.68984,1015.0117 305.2079,1008.7182 309.74779,999.90708 C 300.38107,975.38658 297.33408,949.84027 276.03534,924.33044 C 306.36081,927.44488 319.91562,951.28677 336.16102,971.47019 C 330.63113,923.39416 318.10631,907.05369 307.78707,880.74589 C 337.78137,886.82754 358.36643,912.61828 371.76686,953.45839 C 381.32101,949.54048 390.00462,944.08545 401.95427,944.39719 C 390.65677,902.70139 384.00481,874.48135 365.26702,843.32725 C 418.70898,848.99758 448.92404,923.96657 444.23844,931.28805 C 454.21641,929.04406 463.24409,924.75767 474.67497,925.63638 C 463.426,887.28936 453.62716,848.76848 471.01526,806.98819 C 471.01526,806.98819 519.30204,872.42507 525.40492,892.79397 C 531.50779,913.16287 526.92373,931.49448 526.92373,931.49448 C 526.92373,931.49448 543.8833,962.57978 547.21765,982.58862 C 550.59075,1002.83 543.68496,1041.6919 542.27183,1060.5719 z"
+       id="path4189"
+       sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+    <path
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3587);enable-background:accumulate"
+       d="M 719.5,738.69519 L 737.81177,754.12715 L 782.2228,738.73894 L 805.5,713.19519 L 816.96397,732.41584 L 847.63558,745.19938 L 872.73295,750.92775 L 892,723.19519 L 908.02309,747.02126 L 947,752.19519 L 957.24541,745.99667 L 964.00012,754.69487 L 989.5,765.69519 L 991.5,725.19519 L 955.94866,710.6576 L 923.45591,689.1305 L 883.0038,677.66492 L 861.69668,662.13148 L 840,685.19519 L 755.02878,638.61208 L 722,676.69519 L 719.5,738.69519 z"
+       id="path4191"
+       sodipodi:nodetypes="cccccccccccccccccccccc"
+       clip-path="url(#clipPath3631)"
+       transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
+    <path
+       style="opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter3898);enable-background:new"
+       d="M 584,696.5 L 577.4375,713.65625 C 577.4375,713.65625 569.62598,734.02113 561.75,757.3125 C 557.81201,768.95818 553.86698,781.35395 550.8125,792.4375 C 547.75802,803.52105 545.47664,812.81736 545.3125,820.71875 C 544.91443,839.88071 551.05903,855.60705 554.25,862.46875 C 553.47847,866.02398 552.25863,871.92307 550.90625,880.5625 C 548.98583,892.83071 547.18798,907.71691 548.53125,920.4375 C 549.91334,933.52585 555.34347,948.62515 561.125,963.46875 C 566.90653,978.31235 573.17935,992.69586 576.34375,1001.5 C 582.97581,1019.9519 586.33671,1033.0763 587.65625,1050 C 588.2376,1057.4561 587.41398,1070.336 586.40625,1083.375 C 585.39852,1096.414 584.21964,1109.6764 584.71875,1120.3438 C 585.70786,1141.4836 594.04673,1167.1785 618.09375,1178.2812 C 640.86858,1188.7966 673.42057,1189.9834 701.53125,1174.8438 C 717.69117,1166.1404 731.60759,1147.7462 744.90625,1127.9375 C 758.20491,1108.1288 769.87542,1086.8841 776.84375,1073.0312 C 792.19667,1042.51 816.23728,957.56702 822.46875,920.3125 C 825.48734,902.26597 826.39041,891.24695 825.09375,882.28125 C 824.11522,875.51521 821.26556,870.13385 818.21875,866.0625 C 820.26149,838.55459 817.48668,814.69372 830.1875,786.65625 L 840.75,763.375 L 816.9375,772.6875 C 799.44775,779.52503 788.03586,791.73286 780.34375,804.75 C 780.02124,805.29577 779.78061,805.85776 779.46875,806.40625 C 779.69078,783.89104 783.87659,768.76866 786.0625,747.71875 L 788.03125,728.71875 L 771,737.375 C 740.40551,752.93071 725.30511,785.56821 721.28125,827.59375 C 717.03593,826.96828 712.44985,826.5741 707.46875,826.75 C 707.17726,787.56964 707.07246,759.71315 716.0625,727.375 L 721.65625,707.25 L 702.21875,714.90625 C 671.30938,727.11019 654.35921,756.83698 645.59375,783.28125 C 641.21102,796.50339 638.84793,809.08246 638,819.21875 C 637.76797,821.99248 637.68894,824.53007 637.6875,826.9375 C 634.44563,826.90109 631.26698,827.07339 627.625,827.4375 C 627.66662,788.43277 624.14076,747.68335 595.34375,710.9375 L 584,696.5 z M 589.8125,740.3125 C 606.61941,770.95633 607.28701,804.27978 606.75,840.0625 L 606.53125,855.125 L 618.56618,848.58579 C 627.22823,845.45277 638.12676,848.35827 650.5,847.75 L 665.17465,857.1066 L 658.84375,831.3125 C 658.7541,831.08253 658.62329,830.89581 658.59375,830.59375 C 658.39424,828.55389 658.37143,825.12068 658.71875,820.96875 C 659.41339,812.66489 661.50832,801.38351 665.34375,789.8125 C 670.49907,774.25956 678.83176,758.62002 690.46875,747.28125 C 685.78494,775.91923 687.25316,807.54059 687.45711,843.08639 L 684.69118,856.34803 L 700.1875,848.75 C 709.2169,845.99229 717.37647,848.40004 729.46875,849.84375 L 742.71507,859.28798 L 741.09375,840 C 742.54168,809.02823 749.31524,786.32192 761.8125,771.125 C 758.82562,790.90384 756.38207,812.9098 762.125,849.46875 L 763.19052,855.84193 L 760.25237,867.35878 L 770.86948,859.1906 L 780.05921,869.41258 L 778.51093,858.94898 L 781.9375,852 C 787.63852,838.78851 792.11032,825.78663 798.28125,815.34375 C 799.24111,813.71941 800.31278,812.27939 801.34375,810.78125 C 797.66309,831.9366 798.91659,850.9894 797.25,868.5625 L 792.56986,876.36948 L 799.96875,876.59375 C 803.1888,880.07736 803.83625,880.44443 804.53125,885.25 C 805.22625,890.05557 804.84987,899.65035 801.96875,916.875 C 796.40076,950.16292 770.12313,994.71481 758.22835,1018.3614 C 751.62344,1031.4918 739.70002,1075.8473 727.105,1094.6079 C 714.50998,1113.3684 698.57363,1134.3752 689.93296,1139.0288 C 668.44244,1150.603 645.37702,1164.5347 629.31407,1157.1183 C 614.93921,1150.4813 606.27438,1135.9256 605.5,1119.375 C 605.11689,1111.187 606.11279,1098.0658 607.125,1084.9688 C 608.13721,1071.8717 618.41391,1062.398 622.54839,1048.4062 C 627.92068,1030.2254 621.10152,1011.8118 610.04839,994.46875 C 603.56184,984.29097 586.07159,970.21085 580.5,955.90625 C 574.92841,941.60165 570.13249,926.9031 569.21875,918.25 C 568.29254,909.47887 569.64125,895.22498 571.4375,883.75 C 573.23375,872.27503 575.28125,863.46875 575.28125,863.46875 L 584.70403,859.85355 L 574.21875,855.96875 C 574.21875,855.96875 565.71986,840.65865 566.125,821.15625 C 566.19611,817.73309 567.96126,808.4282 570.84375,797.96875 C 573.72624,787.5093 577.60841,775.41604 581.46875,764 C 584.51314,754.99692 587.24938,747.39655 589.8125,740.3125 z"
+       id="path4193"
+       clip-path="url(#clipPath3677)"
+       sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc"
+       transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)" />
+    <g
+       id="g3617"
+       clip-path="url(#clipPath3622)"
+       transform="translate(276,136)">
+      <path
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-52.200498,74.09707)"
+         id="path4195"
+         d="M -15.66751,843.48852 L -65.16499,827.93217 L -92.03504,880.25807 L -51.02285,925.51291 L -1.52538,887.32914 L -15.66751,843.48852 z"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9024);enable-background:accumulate" />
+      <path
+         sodipodi:nodetypes="ccccccccccccc"
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-46.92842,75.511284)"
+         id="path4197"
+         d="M 118.70648,859.93048 L 63.552152,813.26144 L 19.711532,850.03099 L 53.652662,903.7711 L 40.055848,989.23313 L 0.61048221,1017.5253 L -40.401718,1028.839 L -43.230138,1075.508 L 13.338402,1100.9639 L 32.282389,1031.3139 L 55.738939,972.45727 L 102.08648,899.84236 L 118.70648,859.93048 z"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9020);enable-background:accumulate" />
+    </g>
+    <path
+       style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9044);enable-background:accumulate"
+       d="M -70.82184,932.58397 L -10.01066,905.71392 L 90.3985,936.82662 L 26.75889,967.93931 L -55.26549,950.96875 L -70.82184,932.58397 z"
+       id="path4199"
+       transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,229.07158,211.51128)" />
+    <path
+       style="opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter4105);enable-background:new"
+       d="M 583.0625,715.75 C 570.95641,750.19974 556.348,784.28333 551.3125,820.59375 C 550.48042,835.52242 555.90165,849.75318 560.15625,863.65625 C 554.24001,890.85751 550.01944,920.5562 561.3125,946.78125 C 574.82967,984.9421 596.31397,1022.4634 593.73529,1064.2495 C 592.78699,1093.5437 584.72085,1125.2436 599.125,1152.5312 C 609.32364,1171.866 632.26456,1179.8429 653.09285,1180.1988 C 680.95504,1181.3729 709.55546,1168.5772 725.09375,1144.9375 C 747.68924,1115.5658 766.89426,1083.4402 780.3324,1048.8777 C 797.22293,1003.3717 810.0042,956.31698 818.26642,908.4788 C 820.09082,895.53774 821.3675,881.00895 813.6875,869.65625 C 810.25635,862.31993 813.72957,854.09611 813.00293,846.34648 C 813.67693,821.35182 817.01525,795.68272 829.65625,773.75 C 811.92312,780.1946 794.58357,790.30971 785.65318,807.61425 C 781.7181,814.3238 778.04836,821.18838 774.28125,828 C 770.73126,797.98592 778.00088,768.35172 781.0625,738.71875 C 760.89646,747.77338 744.18578,764.37397 736.88755,785.40075 C 730.58292,800.98078 728.08533,817.71793 726.625,834.4375 C 718.37166,832.91825 709.94053,832.33595 701.5625,832.9375 C 700.59942,794.23963 701.09554,753.53035 712.53125,717.03125 C 693.85012,723.24901 677.36504,735.76676 666.90322,752.41848 C 653.05068,773.29827 645.64182,798.17243 643.84375,823.03125 C 644.42909,827.35579 643.78249,834.87134 637.5,832.90625 C 632.16882,832.9238 626.87092,833.58508 621.5625,834 C 622.71034,794.61852 618.22106,752.3718 594.5,719.78125 C 591.43929,716.14408 588.86315,712.09687 585.875,708.4375 C 584.9375,710.875 584,713.3125 583.0625,715.75 z M 590.8125,729.59375 C 609.37777,758.89004 613.295,794.41387 612.9375,828.46875 C 613.14159,833.64401 612.42094,840.29795 613.0625,844.53125 C 625.38106,838.4285 639.80162,842.09135 652.84375,842.34375 C 655.16087,843.567 656.03585,843.99618 654.75,840.9375 C 650.58545,826.98465 652.90172,812.3245 656.55504,798.52986 C 662.92191,772.23922 677.18332,747.44188 699.375,731.5 C 690.75791,768.73706 693.65842,808.06161 693.28125,845.46875 C 705.53469,838.55885 720.56004,842.02262 733.3125,845.21875 C 736.70472,848.75355 735.60185,844.48927 735.5,841.40625 C 735.01691,820.03567 739.63133,798.33662 749.1875,779.25 C 755.15016,768.56273 763.43088,759.44621 771.625,750.375 C 763.75344,784.2131 762.4221,819.71093 768.90625,853.875 C 770.6311,852.46382 773.51306,853.42086 774.5625,853.5 C 784.24619,832.26318 790.91362,808.11938 809.45266,792.75815 C 811.32595,792.38693 808.00448,801.2831 807.96875,804.65625 C 804.43387,826.50206 800.79359,848.79859 799.18454,870.87536 C 790.40075,873.21707 802.03289,873.1989 802.65329,874.93786 C 810.5764,885.50366 807.31628,899.34258 806.28494,911.2912 C 799.22089,956.32475 784.14263,998.65314 770.33139,1041.971 C 758.25663,1074.9203 742.95719,1100.8235 722.44331,1129.1725 C 711.49074,1142.7239 699.19859,1157.0238 681.59956,1161.6725 C 661.44355,1167.9138 637.3928,1172.5494 619,1161.7188 C 601.71034,1149.3774 597.97607,1126.0099 599.73774,1106.0324 C 599.78653,1090.2062 604.6766,1077.5203 604.14834,1062.5406 C 603.6101,1047.2777 601.85699,1031.9759 597.60573,1015.6743 C 593.35447,999.37268 588.56248,990.75636 581.48667,974.10092 C 574.24556,957.05636 566.41652,937.35229 563.28125,917.8125 C 561.53177,899.18536 566.17296,880.68988 569.0625,862.5625 C 572.35873,859.72554 567.46451,857.36591 566.75,854.375 C 559.14887,837.35992 558.34253,817.6001 564.00766,799.81502 C 571.13786,774.74272 579.76853,750.18261 588.6875,725.6875 C 589.39583,726.98958 590.10417,728.29167 590.8125,729.59375 z"
+       id="path4201"
+       sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+       clip-path="url(#clipPath4177)"
+       transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)" />
+    <path
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4130);enable-background:accumulate"
+       d="M 735.05635,733.03834 L 737.81177,754.12715 L 782.2228,738.73894 L 787.07343,716.34919 L 783.13726,694.29697 L 760.68563,657.70396 L 752.40559,688.0089 L 735.05635,733.03834 z"
+       id="path4203"
+       sodipodi:nodetypes="cccccccc"
+       clip-path="url(#clipPath3631)"
+       transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
+    <path
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4141);enable-background:accumulate"
+       d="M 831.81321,730.29452 L 847.63558,745.19938 L 868.49031,748.09932 L 866.90002,708.17334 L 875.22563,677.66492 L 868.06064,671.32386 L 846.36395,692.26626 L 831.81321,730.29452 z"
+       id="path4205"
+       sodipodi:nodetypes="cccccccc"
+       clip-path="url(#clipPath3631)"
+       transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
+    <g
+       id="g8317"
+       style="filter:url(#filter8333)"
+       clip-path="url(#clipPath8338)"
+       transform="translate(276,136)">
+      <path
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+         clip-path="none"
+         sodipodi:nodetypes="ccccc"
+         id="path4209"
+         d="M 964.00012,754.69487 L 982.42893,762.15966 L 991.5,725.19519 L 976.62969,730.03405 L 964.00012,754.69487 z"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <rect
+         y="757.19519"
+         x="-55"
+         height="177"
+         width="182"
+         id="rect8315"
+         style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+    </g>
+    <g
+       id="g8346"
+       style="filter:url(#filter8354)"
+       clip-path="url(#clipPath8359)"
+       transform="translate(276,136)">
+      <path
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+         clip-path="none"
+         sodipodi:nodetypes="ccccccc"
+         id="path4207"
+         d="M 910.14441,746.31415 L 942.75736,751.48808 L 942.39617,727.61189 L 949.5847,697.92968 L 941.13358,692.66603 L 919.31164,719.1768 L 910.14441,746.31415 z"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <rect
+         y="696.19519"
+         x="-22"
+         height="176"
+         width="165"
+         id="rect8344"
+         style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer16"
+     inkscape:label="Left Foot"
+     style="display:inline">
+    <path
+       style="opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+       d="M 1036.164,1071.8338 C 1042.9581,1090.7366 1046.6577,1105.1335 1048.0543,1123.0457 C 1049.4509,1140.958 1044.2716,1174.8465 1045.1538,1193.7018 C 1046.0356,1212.547 1053.2875,1233.8008 1072.4984,1242.6707 C 1091.9173,1251.6365 1121.8177,1252.882 1146.6183,1239.5251 C 1171.4189,1226.1681 1204.0193,1169.1996 1217.5925,1142.2164 C 1231.2164,1115.1325 1256.3536,1027.719 1262.2533,992.44781 C 1268.1531,957.1766 1264.8039,951.14704 1257.6359,943.39232 C 1260.2762,915.55217 1256.1361,888.45689 1270.7455,856.20614 C 1240.4965,868.03184 1233.3632,896.36684 1222.4266,921.71122 C 1214.4257,870.77829 1222.6358,850.43803 1225.7455,820.49186 C 1196.6808,835.26977 1182.884,867.60588 1180.7455,913.349 C 1169.8216,912.0448 1159.3541,908.91477 1147.1741,912.63471 C 1146.9101,866.61137 1145.7106,835.7453 1156.0847,798.42822 C 1102.8293,819.45508 1093.1375,905.02232 1100.0312,911.20614 C 1089.1484,911.74114 1078.6602,909.90884 1067.1741,914.06329 C 1067.813,871.49194 1066.9136,829.15468 1037.1741,791.20614 C 1037.1741,791.20614 1006.2161,872.12848 1005.7455,894.77757 C 1005.275,917.42666 1015.1971,934.94345 1015.1971,934.94345 C 1015.1971,934.94345 1006.6291,971.68396 1008.8985,993.17568 C 1011.1944,1014.9171 1029.3414,1052.8519 1036.164,1071.8338 z"
+       id="path8848"
+       sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+    <path
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3587);enable-background:accumulate"
+       d="M 719.5,738.69519 L 737.81177,754.12715 L 782.2228,738.73894 L 805.5,713.19519 L 816.96397,732.41584 L 847.63558,745.19938 L 872.73295,750.92775 L 892,723.19519 L 908.02309,747.02126 L 947,752.19519 L 957.24541,745.99667 L 964.00012,754.69487 L 989.5,765.69519 L 991.5,725.19519 L 955.94866,710.6576 L 923.45591,689.1305 L 883.0038,677.66492 L 861.69668,662.13148 L 840,685.19519 L 755.02878,638.61208 L 722,676.69519 L 719.5,738.69519 z"
+       id="path3635"
+       sodipodi:nodetypes="cccccccccccccccccccccc"
+       clip-path="url(#clipPath3631)"
+       transform="translate(276,136)" />
+    <path
+       transform="translate(450.03125,73.843964)"
+       style="opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter3898);enable-background:new"
+       d="M 584,696.5 L 577.4375,713.65625 C 577.4375,713.65625 569.62598,734.02113 561.75,757.3125 C 557.81201,768.95818 553.86698,781.35395 550.8125,792.4375 C 547.75802,803.52105 545.47664,812.81736 545.3125,820.71875 C 544.91443,839.88071 551.05903,855.60705 554.25,862.46875 C 553.47847,866.02398 552.25863,871.92307 550.90625,880.5625 C 548.98583,892.83071 547.18798,907.71691 548.53125,920.4375 C 549.91334,933.52585 555.34347,948.62515 561.125,963.46875 C 566.90653,978.31235 573.17935,992.69586 576.34375,1001.5 C 582.97581,1019.9519 586.33671,1033.0763 587.65625,1050 C 588.2376,1057.4561 587.41398,1070.336 586.40625,1083.375 C 585.39852,1096.414 584.21964,1109.6764 584.71875,1120.3438 C 585.70786,1141.4836 594.04673,1167.1785 618.09375,1178.2812 C 640.86858,1188.7966 673.42057,1189.9834 701.53125,1174.8438 C 717.69117,1166.1404 731.60759,1147.7462 744.90625,1127.9375 C 758.20491,1108.1288 769.87542,1086.8841 776.84375,1073.0312 C 792.19667,1042.51 816.23728,957.56702 822.46875,920.3125 C 825.48734,902.26597 826.39041,891.24695 825.09375,882.28125 C 824.11522,875.51521 821.26556,870.13385 818.21875,866.0625 C 820.26149,838.55459 817.48668,814.69372 830.1875,786.65625 L 840.75,763.375 L 816.9375,772.6875 C 799.44775,779.52503 788.03586,791.73286 780.34375,804.75 C 780.02124,805.29577 779.78061,805.85776 779.46875,806.40625 C 779.69078,783.89104 783.87659,768.76866 786.0625,747.71875 L 788.03125,728.71875 L 771,737.375 C 740.40551,752.93071 725.30511,785.56821 721.28125,827.59375 C 717.03593,826.96828 712.44985,826.5741 707.46875,826.75 C 707.17726,787.56964 707.07246,759.71315 716.0625,727.375 L 721.65625,707.25 L 702.21875,714.90625 C 671.30938,727.11019 654.35921,756.83698 645.59375,783.28125 C 641.21102,796.50339 638.84793,809.08246 638,819.21875 C 637.76797,821.99248 637.68894,824.53007 637.6875,826.9375 C 634.44563,826.90109 631.26698,827.07339 627.625,827.4375 C 627.66662,788.43277 624.14076,747.68335 595.34375,710.9375 L 584,696.5 z M 589.8125,740.3125 C 606.61941,770.95633 607.28701,804.27978 606.75,840.0625 L 606.53125,855.125 L 618.56618,848.58579 C 627.22823,845.45277 638.12676,848.35827 650.5,847.75 L 665.17465,857.1066 L 658.84375,831.3125 C 658.7541,831.08253 658.62329,830.89581 658.59375,830.59375 C 658.39424,828.55389 658.37143,825.12068 658.71875,820.96875 C 659.41339,812.66489 661.50832,801.38351 665.34375,789.8125 C 670.49907,774.25956 678.83176,758.62002 690.46875,747.28125 C 685.78494,775.91923 687.25316,807.54059 687.45711,843.08639 L 684.69118,856.34803 L 700.1875,848.75 C 709.2169,845.99229 717.37647,848.40004 729.46875,849.84375 L 742.71507,859.28798 L 741.09375,840 C 742.54168,809.02823 749.31524,786.32192 761.8125,771.125 C 758.82562,790.90384 756.38207,812.9098 762.125,849.46875 L 763.19052,855.84193 L 760.25237,867.35878 L 770.86948,859.1906 L 780.05921,869.41258 L 778.51093,858.94898 L 781.9375,852 C 787.63852,838.78851 792.11032,825.78663 798.28125,815.34375 C 799.24111,813.71941 800.31278,812.27939 801.34375,810.78125 C 797.66309,831.9366 798.91659,850.9894 797.25,868.5625 L 792.56986,876.36948 L 799.96875,876.59375 C 803.1888,880.07736 803.83625,880.44443 804.53125,885.25 C 805.22625,890.05557 804.84987,899.65035 801.96875,916.875 C 796.40076,950.16292 770.17603,1040.0409 758.28125,1063.6875 C 751.67634,1076.8179 740.25127,1097.5832 727.65625,1116.3438 C 715.06123,1135.1043 700.29692,1151.8776 691.65625,1156.5312 C 670.16573,1168.1054 642.87545,1166.7914 626.8125,1159.375 C 612.43764,1152.738 606.27438,1135.9256 605.5,1119.375 C 605.11689,1111.187 606.11279,1098.0658 607.125,1084.9688 C 608.13721,1071.8717 618.41391,1062.398 622.54839,1048.4062 C 627.92068,1030.2254 621.10152,1011.8118 610.04839,994.46875 C 603.56184,984.29097 586.07159,970.21085 580.5,955.90625 C 574.92841,941.60165 570.13249,926.9031 569.21875,918.25 C 568.29254,909.47887 569.64125,895.22498 571.4375,883.75 C 573.23375,872.27503 575.28125,863.46875 575.28125,863.46875 L 584.70403,859.85355 L 574.21875,855.96875 C 574.21875,855.96875 565.71986,840.65865 566.125,821.15625 C 566.19611,817.73309 567.96126,808.4282 570.84375,797.96875 C 573.72624,787.5093 577.60841,775.41604 581.46875,764 C 584.51314,754.99692 587.24938,747.39655 589.8125,740.3125 z"
+       id="path3669"
+       clip-path="url(#clipPath3677)"
+       sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc" />
+    <g
+       id="g3628"
+       clip-path="url(#clipPath3636)"
+       transform="translate(276,136)">
+      <path
+         id="path8988"
+         d="M 824.48651,818.48242 L 774.98903,802.92607 L 748.11898,855.25197 L 789.13117,900.50681 L 838.62864,862.32304 L 824.48651,818.48242 z"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9024);enable-background:accumulate" />
+      <path
+         id="path8990"
+         d="M 964.49365,855.25197 L 909.33932,808.58293 L 865.4987,845.35248 L 899.43983,899.09259 L 906.51089,965.56063 L 855.59921,1000.916 L 814.58701,1012.2297 L 811.75859,1058.8987 L 868.32713,1084.3546 L 931.96674,1007.987 L 956.00837,913.23473 L 964.49365,855.25197 z"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9020);enable-background:accumulate" />
+    </g>
+    <path
+       style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9044);enable-background:accumulate"
+       d="M 1045.3322,1043.5779 L 1106.1434,1016.7078 L 1206.5525,1047.8205 L 1142.9129,1078.9332 L 1060.8885,1061.9626 L 1045.3322,1043.5779 z"
+       id="path8992" />
+    <path
+       transform="translate(450.03125,73.843964)"
+       style="opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter4185);enable-background:new"
+       d="M 583.0625,715.75 C 570.95641,750.19974 556.348,784.28333 551.3125,820.59375 C 550.48042,835.52242 555.90165,849.75318 560.15625,863.65625 C 554.24001,890.85751 550.01944,920.5562 561.3125,946.78125 C 574.82967,984.9421 596.31397,1022.4634 593.73529,1064.2495 C 592.78699,1093.5437 584.72085,1125.2436 599.125,1152.5312 C 609.32364,1171.866 632.26456,1179.8429 653.09285,1180.1988 C 680.95504,1181.3729 709.55546,1168.5772 725.09375,1144.9375 C 747.68924,1115.5658 766.89426,1083.4402 780.3324,1048.8777 C 797.22293,1003.3717 810.0042,956.31698 818.26642,908.4788 C 820.09082,895.53774 821.3675,881.00895 813.6875,869.65625 C 810.25635,862.31993 813.72957,854.09611 813.00293,846.34648 C 813.67693,821.35182 817.01525,795.68272 829.65625,773.75 C 811.92312,780.1946 794.58357,790.30971 785.65318,807.61425 C 781.7181,814.3238 778.04836,821.18838 774.28125,828 C 770.73126,797.98592 778.00088,768.35172 781.0625,738.71875 C 760.89646,747.77338 744.18578,764.37397 736.88755,785.40075 C 730.58292,800.98078 728.08533,817.71793 726.625,834.4375 C 718.37166,832.91825 709.94053,832.33595 701.5625,832.9375 C 700.59942,794.23963 701.09554,753.53035 712.53125,717.03125 C 693.85012,723.24901 677.36504,735.76676 666.90322,752.41848 C 653.05068,773.29827 645.64182,798.17243 643.84375,823.03125 C 644.42909,827.35579 643.78249,834.87134 637.5,832.90625 C 632.16882,832.9238 626.87092,833.58508 621.5625,834 C 622.71034,794.61852 618.22106,752.3718 594.5,719.78125 C 591.43929,716.14408 588.86315,712.09687 585.875,708.4375 C 584.9375,710.875 584,713.3125 583.0625,715.75 z M 590.8125,729.59375 C 609.37777,758.89004 613.295,794.41387 612.9375,828.46875 C 613.14159,833.64401 612.42094,840.29795 613.0625,844.53125 C 625.38106,838.4285 639.80162,842.09135 652.84375,842.34375 C 655.16087,843.567 656.03585,843.99618 654.75,840.9375 C 650.58545,826.98465 652.90172,812.3245 656.55504,798.52986 C 662.92191,772.23922 677.18332,747.44188 699.375,731.5 C 690.75791,768.73706 693.65842,808.06161 693.28125,845.46875 C 705.53469,838.55885 720.56004,842.02262 733.3125,845.21875 C 736.70472,848.75355 735.60185,844.48927 735.5,841.40625 C 735.01691,820.03567 739.63133,798.33662 749.1875,779.25 C 755.15016,768.56273 763.43088,759.44621 771.625,750.375 C 763.75344,784.2131 762.4221,819.71093 768.90625,853.875 C 770.6311,852.46382 773.51306,853.42086 774.5625,853.5 C 784.24619,832.26318 790.91362,808.11938 809.45266,792.75815 C 811.32595,792.38693 808.00448,801.2831 807.96875,804.65625 C 804.43387,826.50206 804.67155,848.82948 803.0625,870.90625 C 801.75012,872.28304 805.91085,873.22979 806.53125,874.96875 C 814.45436,885.53455 809.65419,899.80024 808.62285,911.74886 C 801.5588,956.78241 786.85732,1000.1282 773.04608,1043.446 C 760.97132,1076.3953 742.32638,1106.526 721.8125,1134.875 C 710.85993,1148.4264 698.56778,1162.7263 680.96875,1167.375 C 660.81274,1173.6163 637.3928,1172.5494 619,1161.7188 C 601.71034,1149.3774 597.97607,1126.0099 599.73774,1106.0324 C 599.78653,1090.2062 602.10985,1078.2316 607.65521,1063.2271 C 613.20056,1048.2226 610.12626,1031.8954 605.875,1015.5938 C 601.62374,999.2922 593.69597,989.33378 584.05342,973.38963 C 574.41087,957.44548 566.41652,937.35229 563.28125,917.8125 C 561.53177,899.18536 566.17296,880.68988 569.0625,862.5625 C 572.35873,859.72554 567.46451,857.36591 566.75,854.375 C 559.14887,837.35992 558.34253,817.6001 564.00766,799.81502 C 571.13786,774.74272 579.76853,750.18261 588.6875,725.6875 C 589.39583,726.98958 590.10417,728.29167 590.8125,729.59375 z"
+       id="path4149"
+       sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+       clip-path="url(#clipPath4177)" />
+    <path
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4130);enable-background:accumulate"
+       d="M 735.05635,733.03834 L 737.81177,754.12715 L 782.2228,738.73894 L 787.07343,716.34919 L 783.13726,694.29697 L 760.68563,657.70396 L 752.40559,688.0089 L 735.05635,733.03834 z"
+       id="path3902"
+       sodipodi:nodetypes="cccccccc"
+       clip-path="url(#clipPath3631)"
+       transform="translate(276,136)" />
+    <path
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4141);enable-background:accumulate"
+       d="M 831.81321,730.29452 L 847.63558,745.19938 L 868.49031,748.09932 L 866.90002,708.17334 L 875.22563,677.66492 L 868.06064,671.32386 L 846.36395,692.26626 L 831.81321,730.29452 z"
+       id="path4135"
+       sodipodi:nodetypes="cccccccc"
+       clip-path="url(#clipPath3631)"
+       transform="translate(276,136)" />
+    <g
+       id="g8367"
+       style="filter:url(#filter8379)"
+       clip-path="url(#clipPath8392)"
+       transform="translate(276,136)">
+      <path
+         clip-path="none"
+         sodipodi:nodetypes="ccccccc"
+         id="path4145"
+         d="M 910.14441,746.31415 L 942.75736,751.48808 L 942.39617,727.61189 L 949.5847,697.92968 L 941.13358,692.66603 L 919.31164,719.1768 L 910.14441,746.31415 z"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <rect
+         y="650.19098"
+         x="877.51953"
+         height="172.53406"
+         width="123.03658"
+         id="rect8365"
+         style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+    </g>
+    <g
+       id="g8400"
+       style="filter:url(#filter8404)"
+       clip-path="url(#clipPath8417)"
+       transform="translate(276,136)">
+      <path
+         clip-path="none"
+         sodipodi:nodetypes="ccccc"
+         id="path4147"
+         d="M 964.00012,754.69487 L 982.42893,762.15966 L 991.5,725.19519 L 976.62969,730.03405 L 964.00012,754.69487 z"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <rect
+         y="677.06104"
+         x="924.89569"
+         height="125.1579"
+         width="142.12846"
+         id="rect8398"
+         style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+    </g>
+  </g>
+</svg>
diff --git a/Documentation/logo.txt b/Documentation/logo.txt
index 296f0f7..a2e6244 100644
--- a/Documentation/logo.txt
+++ b/Documentation/logo.txt
@@ -1,13 +1,4 @@
-This is the full-colour version of the currently unofficial Linux logo
-("currently unofficial" just means that there has been no paperwork and
-that I have not really announced it yet).  It was created by Larry Ewing,
-and is freely usable as long as you acknowledge Larry as the original
-artist. 
+Tux is taking a three month sabbatical to work as a barber, so Tuz is
+standing in.  He's taken pains to ensure you'll hardly notice.
 
-Note that there are black-and-white versions of this available that
-scale down to smaller sizes and are better for letterheads or whatever
-you want to use it for: for the full range of logos take a look at
-Larry's web-page:
-
-	http://www.isc.tamu.edu/~lewing/linux/
-
+Image by Andrew McGown and Josh Bush.  Image is licensed CC BY-SA.
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 841a936..012858d 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -346,6 +346,9 @@
     sbirq	- IRQ # for CMI8330 chip (SB16)
     sbdma8	- 8bit DMA # for CMI8330 chip (SB16)
     sbdma16	- 16bit DMA # for CMI8330 chip (SB16)
+    fmport	- (optional) OPL3 I/O port
+    mpuport	- (optional) MPU401 I/O port
+    mpuirq	- (optional) MPU401 irq #
 
     This module supports multiple cards and autoprobe.
 
@@ -388,34 +391,11 @@
 
     The power-management is supported.
     
-  Module snd-cs4232
-  -----------------
-
-    Module for sound cards based on CS4232/CS4232A ISA chips.
-
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port	- port # for CS4232 chip (PnP setup - 0x534)
-    cport	- control port # for CS4232 chip (PnP setup - 0x120,0x210,0xf00)
-    mpu_port	- port # for MPU-401 UART (PnP setup - 0x300), -1 = disable
-    fm_port	- FM port # for CS4232 chip (PnP setup - 0x388), -1 = disable
-    irq		- IRQ # for CS4232 chip (5,7,9,11,12,15)
-    mpu_irq	- IRQ # for MPU-401 UART (9,11,12,15)
-    dma1	- first DMA # for CS4232 chip (0,1,3)
-    dma2	- second DMA # for Yamaha CS4232 chip (0,1,3), -1 = disable
-    
-    This module supports multiple cards. This module does not support autoprobe
-    (if ISA PnP is not used) thus main port must be specified!!! Other ports are
-    optional.
-
-    The power-management is supported.
-    
   Module snd-cs4236
   -----------------
 
-    Module for sound cards based on CS4235/CS4236/CS4236B/CS4237B/
+    Module for sound cards based on CS4232/CS4232A,
+    	       	     	   	   CS4235/CS4236/CS4236B/CS4237B/
                                    CS4238B/CS4239 ISA chips.
 
     isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
@@ -437,6 +417,9 @@
 
     The power-management is supported.
 
+    This module is aliased as snd-cs4232 since it provides the old
+    snd-cs4232 functionality, too.
+
   Module snd-cs4281
   -----------------
 
@@ -606,6 +589,7 @@
     Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
 
     port	- port # for ES-1688 chip (0x220,0x240,0x260)
+    fm_port	- port # for OPL3 (option; share the same port as default)
     mpu_port	- port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
     irq		- IRQ # for ES-1688 chip (5,7,9,10)
     mpu_irq	- IRQ # for MPU-401 port (5,7,9,10)
@@ -757,6 +741,9 @@
     model	- force the model name
     position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
     probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
+    		  When the bit 8 (0x100) is set, the lower 8 bits are used
+		  as the "fixed" codec slots; i.e. the driver probes the
+		  slots regardless what hardware reports back
     probe_only	- Only probing and no codec initialization (default=off);
 		  Useful to check the initial codec status for debugging
     bdl_pos_adj	- Specifies the DMA IRQ timing delay in samples.
@@ -1185,6 +1172,54 @@
 
     This module supports multiple devices and PnP.
     
+  Module snd-msnd-classic
+  -----------------------
+
+    Module for Turtle Beach MultiSound Classic, Tahiti or Monterey
+    soundcards.
+
+    io		- Port # for msnd-classic card
+    irq		- IRQ # for msnd-classic card
+    mem		- Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
+		  0xe0000 or 0xe8000)
+    write_ndelay - enable write ndelay (default = 1)
+    calibrate_signal - calibrate signal (default = 0)
+    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
+    digital	- Digital daughterboard present (default = 0)
+    cfg		- Config port (0x250, 0x260 or 0x270) default = PnP
+    reset	- Reset all devices
+    mpu_io	- MPU401 I/O port
+    mpu_irq	- MPU401 irq#
+    ide_io0	- IDE port #0
+    ide_io1	- IDE port #1
+    ide_irq	- IDE irq#
+    joystick_io	- Joystick I/O port
+
+    The driver requires firmware files "turtlebeach/msndinit.bin" and
+    "turtlebeach/msndperm.bin" in the proper firmware directory.
+
+    See Documentation/sound/oss/MultiSound for important information
+    about this driver.  Note that it has been discontinued, but the 
+    Voyetra Turtle Beach knowledge base entry for it is still available
+    at
+	http://www.turtlebeach.com/site/kb_ftp/790.asp
+
+  Module snd-msnd-pinnacle
+  ------------------------
+
+    Module for Turtle Beach MultiSound Pinnacle/Fiji soundcards.
+
+    io		- Port # for pinnacle/fiji card
+    irq		- IRQ # for pinnalce/fiji card
+    mem		- Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
+		  0xe0000 or 0xe8000)
+    write_ndelay - enable write ndelay (default = 1)
+    calibrate_signal - calibrate signal (default = 0)
+    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
+
+    The driver requires firmware files "turtlebeach/pndspini.bin" and
+    "turtlebeach/pndsperm.bin" in the proper firmware directory.
+
   Module snd-mtpav
   ----------------
 
@@ -1824,7 +1859,7 @@
   -------------------
 
     Module for sound cards based on the Asus AV100/AV200 chips,
-    i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe).
+    i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), and Essence STX.
 
     This module supports autoprobe and multiple cards.
 
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 0f5d26b..8eec05b 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -56,6 +56,7 @@
   sony-assamd	Sony ASSAMD
   toshiba-s06	Toshiba S06
   toshiba-rx1	Toshiba RX1
+  tyan		Tyan Thunder n6650W (S2915-E)
   ultra		Samsung Q1 Ultra Vista model
   lenovo-3000	Lenovo 3000 y410
   nec		NEC Versa S9100
@@ -261,6 +262,8 @@
 =============
   laptop	Basic Laptop config (default)
   hp		HP Spartan laptop
+  hp-dv6736	HP dv6736
+  lenovo-x200	Lenovo X200 laptop
 
 STAC9200
 ========
@@ -278,6 +281,7 @@
   gateway-m4	Gateway laptops with EAPD control
   gateway-m4-2	Gateway laptops with EAPD control
   panasonic	Panasonic CF-74
+  auto		BIOS setup (default)
 
 STAC9205/9254
 =============
@@ -285,6 +289,8 @@
   dell-m42	Dell (unknown)
   dell-m43	Dell Precision
   dell-m44	Dell Inspiron
+  eapd		Keep EAPD on (e.g. Gateway T1616)
+  auto		BIOS setup (default)
 
 STAC9220/9221
 =============
@@ -308,6 +314,7 @@
   dell-d82	Dell (unknown)
   dell-m81	Dell (unknown)
   dell-m82	Dell XPS M1210
+  auto		BIOS setup (default)
 
 STAC9202/9250/9251
 ==================
@@ -319,6 +326,7 @@
   m3		Some Gateway MX series laptops
   m5		Some Gateway MX series laptops (MP6954)
   m6		Some Gateway NX series laptops
+  auto		BIOS setup (default)
 
 STAC9227/9228/9229/927x
 =======================
@@ -328,6 +336,7 @@
   5stack	D965 5stack + SPDIF
   dell-3stack	Dell Dimension E520
   dell-bios	Fixes with Dell BIOS setup
+  auto		BIOS setup (default)
 
 STAC92HD71B*
 ============
@@ -335,7 +344,10 @@
   dell-m4-1	Dell desktops
   dell-m4-2	Dell desktops
   dell-m4-3	Dell desktops
-  hp-m4		HP dv laptops
+  hp-m4		HP mini 1000
+  hp-dv5	HP dv series
+  hp-hdx	HP HDX series
+  auto		BIOS setup (default)
 
 STAC92HD73*
 ===========
@@ -345,13 +357,16 @@
   dell-m6-dmic	Dell desktops/laptops with digital mics
   dell-m6	Dell desktops/laptops with both type of mics
   dell-eq	Dell desktops/laptops
+  auto		BIOS setup (default)
 
 STAC92HD83*
 ===========
   ref		Reference board
   mic-ref	Reference board with power managment for ports
+  dell-s14	Dell laptop
+  auto		BIOS setup (default)
 
 STAC9872
 ========
-  vaio		Setup for VAIO FE550G/SZ110
-  vaio-ar Setup for VAIO AR
+  vaio		VAIO laptop without SPDIF
+  auto		BIOS setup (default)
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index 8d68fff..c5948f2 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -109,6 +109,13 @@
 Since 2.6.29 kernel, the driver has a more robust probing method, so
 this error might happen rarely, though.
 
+On a machine with a broken BIOS, sometimes you need to force the
+driver to probe the codec slots the hardware doesn't report for use.
+In such a case, turn the bit 8 (0x100) of `probe_mask` option on.
+Then the rest 8 bits are passed as the codec slots to probe
+unconditionally.  For example, `probe_mask=0x103` will force to probe
+the codec slots 0 and 1 no matter what the hardware reports.
+
 
 Interrupt Handling
 ~~~~~~~~~~~~~~~~~~
@@ -358,10 +365,26 @@
   to this file.
 init_verbs::
   The extra verbs to execute at initialization.  You can add a verb by
-  writing to this file.  Pass tree numbers, nid, verb and parameter.
+  writing to this file.  Pass three numbers: nid, verb and parameter
+  (separated with a space).
 hints::
-  Shows hint strings for codec parsers for any use.  Right now it's
-  not used.
+  Shows / stores hint strings for codec parsers for any use.
+  Its format is `key = value`.  For example, passing `hp_detect = yes`
+  to IDT/STAC codec parser will result in the disablement of the
+  headphone detection.
+init_pin_configs::
+  Shows the initial pin default config values set by BIOS.
+driver_pin_configs::
+  Shows the pin default values set by the codec parser explicitly.
+  This doesn't show all pin values but only the changed values by
+  the parser.  That is, if the parser doesn't change the pin default
+  config values by itself, this will contain nothing.
+user_pin_configs::
+  Shows the pin default config values to override the BIOS setup.
+  Writing this (with two numbers, NID and value) appends the new
+  value.  The given will be used instead of the initial BIOS value at
+  the next reconfiguration time.  Note that this config will override
+  even the driver pin configs, too.
 reconfig::
   Triggers the codec re-configuration.  When any value is written to
   this file, the driver re-initialize and parses the codec tree
@@ -371,6 +394,14 @@
   Resets the codec, removes the mixer elements and PCM stuff of the
   specified codec, and clear all init verbs and hints.
 
+For example, when you want to change the pin default configuration
+value of the pin widget 0x14 to 0x9993013f, and let the driver
+re-configure based on that state, run like below:
+------------------------------------------------------------------------
+  # echo 0x14 0x9993013f > /sys/class/sound/hwC0D0/user_pin_configs
+  # echo 1 > /sys/class/sound/hwC0D0/reconfig  
+------------------------------------------------------------------------
+
 
 Power-Saving
 ~~~~~~~~~~~~
@@ -461,6 +492,16 @@
 There are some other useful options.  See `--help` option output for
 details.
 
+When a probe error occurs or when the driver obviously assigns a
+mismatched model, it'd be helpful to load the driver with
+`probe_only=1` option (at best after the cold reboot) and run
+alsa-info at this state.  With this option, the driver won't configure
+the mixer and PCM but just tries to probe the codec slot.  After
+probing, the proc file is available, so you can get the raw codec
+information before modified by the driver.  Of course, the driver
+isn't usable with `probe_only=1`.  But you can continue the
+configuration via hwdep sysfs file if hda-reconfig option is enabled.
+
 
 hda-verb
 ~~~~~~~~
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt
index 46f9684..9e67632 100644
--- a/Documentation/sound/alsa/soc/dapm.txt
+++ b/Documentation/sound/alsa/soc/dapm.txt
@@ -116,6 +116,9 @@
 SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
 	ARRAY_SIZE(wm8731_output_mixer_controls)),
 
+If you dont want the mixer elements prefixed with the name of the mixer widget,
+you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
+as for SND_SOC_DAPM_MIXER.
 
 2.3 Platform/Machine domain Widgets
 -----------------------------------
diff --git a/Documentation/sound/oss/CS4232 b/Documentation/sound/oss/CS4232
deleted file mode 100644
index 7d6af7a..0000000
--- a/Documentation/sound/oss/CS4232
+++ /dev/null
@@ -1,23 +0,0 @@
-To configure the Crystal CS423x sound chip and activate its DSP functions,
-modules may be loaded in this order:
-  
-	modprobe sound
-	insmod ad1848
-	insmod uart401
-	insmod cs4232 io=* irq=* dma=* dma2=*
-  
-This is the meaning of the parameters:
-  
-	io--I/O address of the Windows Sound System (normally 0x534)
-	irq--IRQ of this device
-	dma and dma2--DMA channels (DMA2 may be 0)
-  
-On some cards, the board attempts to do non-PnP setup, and fails.  If you
-have problems, use Linux' PnP facilities. 
-  
-To get MIDI facilities add
-  
-	insmod opl3 io=*
-  
-where "io" is the I/O address of the OPL3 synthesizer. This will be shown
-in /proc/sys/pnp and is normally 0x388.
diff --git a/Documentation/sound/oss/Introduction b/Documentation/sound/oss/Introduction
index f04ba6b..75d967f 100644
--- a/Documentation/sound/oss/Introduction
+++ b/Documentation/sound/oss/Introduction
@@ -80,7 +80,7 @@
     additional features.
 
 2.  The commercial OSS driver may be obtained from the site:
-    http://www/opensound.com.  This may be used for cards that
+    http://www.opensound.com.  This may be used for cards that
     are unsupported by the kernel driver, or may be used
     by other operating systems.  
 
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
index 2704819..6c3c625 100644
--- a/Documentation/usb/usbmon.txt
+++ b/Documentation/usb/usbmon.txt
@@ -229,16 +229,26 @@
 	int status;		/* 28: */
 	unsigned int length;	/* 32: Length of data (submitted or actual) */
 	unsigned int len_cap;	/* 36: Delivered length */
-	unsigned char setup[8];	/* 40: Only for Control 'S' */
-};				/* 48 bytes total */
+	union {			/* 40: */
+		unsigned char setup[SETUP_LEN];	/* Only for Control S-type */
+		struct iso_rec {		/* Only for ISO */
+			int error_count;
+			int numdesc;
+		} iso;
+	} s;
+	int interval;		/* 48: Only for Interrupt and ISO */
+	int start_frame;	/* 52: For ISO */
+	unsigned int xfer_flags; /* 56: copy of URB's transfer_flags */
+	unsigned int ndesc;	/* 60: Actual number of ISO descriptors */
+};				/* 64 total length */
 
 These events can be received from a character device by reading with read(2),
-with an ioctl(2), or by accessing the buffer with mmap.
+with an ioctl(2), or by accessing the buffer with mmap. However, read(2)
+only returns first 48 bytes for compatibility reasons.
 
 The character device is usually called /dev/usbmonN, where N is the USB bus
 number. Number zero (/dev/usbmon0) is special and means "all buses".
-However, this feature is not implemented yet. Note that specific naming
-policy is set by your Linux distribution.
+Note that specific naming policy is set by your Linux distribution.
 
 If you create /dev/usbmon0 by hand, make sure that it is owned by root
 and has mode 0600. Otherwise, unpriviledged users will be able to snoop
@@ -279,9 +289,10 @@
 This call returns the current size of the buffer in bytes.
 
  MON_IOCX_GET, defined as _IOW(MON_IOC_MAGIC, 6, struct mon_get_arg)
+ MON_IOCX_GETX, defined as _IOW(MON_IOC_MAGIC, 10, struct mon_get_arg)
 
-This call waits for events to arrive if none were in the kernel buffer,
-then returns the first event. Its argument is a pointer to the following
+These calls wait for events to arrive if none were in the kernel buffer,
+then return the first event. The argument is a pointer to the following
 structure:
 
 struct mon_get_arg {
@@ -294,6 +305,8 @@
 pointed by hdr contains the next event structure, and the data buffer contains
 the data, if any. The event is removed from the kernel buffer.
 
+The MON_IOCX_GET copies 48 bytes, MON_IOCX_GETX copies 64 bytes.
+
  MON_IOCX_MFETCH, defined as _IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg)
 
 This ioctl is primarily used when the application accesses the buffer
diff --git a/MAINTAINERS b/MAINTAINERS
index 2711451..bc919b6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1271,6 +1271,12 @@
 T:	git kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
 S:	Maintained
 
+CRYPTOGRAPHIC RANDOM NUMBER GENERATOR
+P:	Neil Horman
+M:	nhorman@tuxdriver.com
+L:	linux-crypto@vger.kernel.org
+S:	Maintained
+
 CS5535 Audio ALSA driver
 P:	Jaya Kumar
 M:	jayakumar.alsa@gmail.com
@@ -1471,8 +1477,6 @@
 S:	Supported
 
 DOCUMENTATION (/Documentation directory)
-P:	Michael Kerrisk
-M:	mtk.manpages@gmail.com
 P:	Randy Dunlap
 M:	rdunlap@xenotime.net
 L:	linux-doc@vger.kernel.org
@@ -2220,6 +2224,11 @@
 L:	linux1394-devel@lists.sourceforge.net
 S:	Maintained
 
+INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
+P:	Mimi Zohar
+M:	zohar@us.ibm.com
+S:	Supported
+
 IMS TWINTURBO FRAMEBUFFER DRIVER
 L:	linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:	Orphan
@@ -2881,7 +2890,7 @@
 M:	mtk.manpages@gmail.com
 W:	http://www.kernel.org/doc/man-pages
 L:	linux-man@vger.kernel.org
-S:	Supported
+S:	Maintained
 
 MARVELL LIBERTAS WIRELESS DRIVER
 P:	Dan Williams
@@ -3354,10 +3363,8 @@
 PARISC ARCHITECTURE
 P:	Kyle McMartin
 M:	kyle@mcmartin.ca
-P:	Matthew Wilcox
-M:	matthew@wil.cx
-P:	Grant Grundler
-M:	grundler@parisc-linux.org
+P:	Helge Deller
+M:	deller@gmx.de
 L:	linux-parisc@vger.kernel.org
 W:	http://www.parisc-linux.org/
 T:	git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
@@ -3856,6 +3863,7 @@
 L:	linux-kernel@vger.kernel.org
 L:	linux-security-module@vger.kernel.org (suggested Cc:)
 T:	git kernel.org:pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
+W:	http://security.wiki.kernel.org/
 S:	Supported
 
 SECURITY CONTACT
@@ -4297,6 +4305,19 @@
 W:	http://sourceforge.net/projects/tlan/
 S:	Maintained
 
+TOMOYO SECURITY MODULE
+P:	Kentaro Takeda
+M:	takedakn@nttdata.co.jp
+P:	Tetsuo Handa
+M:	penguin-kernel@I-love.SAKURA.ne.jp
+L:	linux-kernel@vger.kernel.org (kernel issues)
+L:	tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for developers and users in English)
+L:	tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
+L:	tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
+W:	http://tomoyo.sourceforge.jp/
+T:	quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.2.x/tomoyo-lsm/patches/
+S:	Maintained
+
 TOSHIBA ACPI EXTRAS DRIVER
 P:	John Belmonte
 M:	toshiba_acpi@memebeam.org
diff --git a/Makefile b/Makefile
index d04ee0a..1ab3ebf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 29
-EXTRAVERSION = -rc7
-NAME = Erotic Pickled Herring
+EXTRAVERSION =
+NAME = Temporary Tasmanian Devil
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -566,6 +566,12 @@
 # disable pointer signed / unsigned warnings in gcc 4.0
 KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)
 
+# disable invalid "can't wrap" optimzations for signed / pointers
+KBUILD_CFLAGS	+= $(call cc-option,-fwrapv)
+
+# revert to pre-gcc-4.4 behaviour of .eh_frame
+KBUILD_CFLAGS	+= $(call cc-option,-fno-dwarf2-cfi-asm)
+
 # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
 # But warn user when we do so
 warn-assign = \
@@ -904,12 +910,18 @@
 # and if the SCM is know a tag from the SCM is appended.
 # The appended tag is determined by the SCM used.
 #
-# Currently, only git is supported.
-# Other SCMs can edit scripts/setlocalversion and add the appropriate
-# checks as needed.
+# .scmversion is used when generating rpm packages so we do not loose
+# the version information from the SCM when we do the build of the kernel
+# from the copied source
 ifdef CONFIG_LOCALVERSION_AUTO
-	_localver-auto = $(shell $(CONFIG_SHELL) \
-	                  $(srctree)/scripts/setlocalversion $(srctree))
+
+ifeq ($(wildcard .scmversion),)
+        _localver-auto = $(shell $(CONFIG_SHELL) \
+                         $(srctree)/scripts/setlocalversion $(srctree))
+else
+        _localver-auto = $(shell cat .scmversion 2> /dev/null)
+endif
+
 	localver-auto  = $(LOCALVERSION)$(_localver-auto)
 endif
 
@@ -1537,7 +1549,7 @@
       cmd_depmod = \
 	if [ -r System.map -a -x $(DEPMOD) ]; then                              \
 		$(DEPMOD) -ae -F System.map                                     \
-		$(if $(strip $(INSTALL_MOD_PATH)), -b $(INSTALL_MOD_PATH) -r)   \
+		$(if $(strip $(INSTALL_MOD_PATH)), -b $(INSTALL_MOD_PATH) )     \
 		$(KERNELRELEASE);                                               \
 	fi
 
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 49a6ba9..159d041 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -111,6 +111,7 @@
 	.globl mcount_call
 mcount_call:
 	bl ftrace_stub
+	ldr lr, [fp, #-4]			@ restore lr
 	ldmia sp!, {r0-r3, pc}
 
 ENTRY(ftrace_caller)
@@ -122,6 +123,7 @@
 	.globl ftrace_call
 ftrace_call:
 	bl ftrace_stub
+	ldr lr, [fp, #-4]			@ restore lr
 	ldmia sp!, {r0-r3, pc}
 
 #else
@@ -133,6 +135,7 @@
 	adr r0, ftrace_stub
 	cmp r0, r2
 	bne trace
+	ldr lr, [fp, #-4]			@ restore lr
 	ldmia sp!, {r0-r3, pc}
 
 trace:
@@ -141,6 +144,7 @@
 	sub r0, r0, #MCOUNT_INSN_SIZE
 	mov lr, pc
 	mov pc, r2
+	mov lr, r1				@ restore lr
 	ldmia sp!, {r0-r3, pc}
 
 #endif /* CONFIG_DYNAMIC_FTRACE */
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index 36f81d9..6ff7919 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -88,7 +88,7 @@
  * disable irqs for the duration.  Note - these functions are almost
  * entirely coded in assembly.
  */
-void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs)
+void __naked set_fiq_regs(struct pt_regs *regs)
 {
 	register unsigned long tmp;
 	asm volatile (
@@ -106,7 +106,7 @@
 	: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
 }
 
-void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs)
+void __naked get_fiq_regs(struct pt_regs *regs)
 {
 	register unsigned long tmp;
 	asm volatile (
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 134af97..b7f2332 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -347,6 +347,111 @@
 void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  Compact Flash (PCMCIA or IDE)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) || \
+    defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
+
+static struct at91_cf_data cf0_data;
+
+static struct resource cf0_resources[] = {
+	[0] = {
+		.start	= AT91_CHIPSELECT_4,
+		.end	= AT91_CHIPSELECT_4 + SZ_256M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+	}
+};
+
+static struct platform_device cf0_device = {
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &cf0_data,
+	},
+	.resource	= cf0_resources,
+	.num_resources	= ARRAY_SIZE(cf0_resources),
+};
+
+static struct at91_cf_data cf1_data;
+
+static struct resource cf1_resources[] = {
+	[0] = {
+		.start	= AT91_CHIPSELECT_5,
+		.end	= AT91_CHIPSELECT_5 + SZ_256M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+	}
+};
+
+static struct platform_device cf1_device = {
+	.id		= 1,
+	.dev		= {
+				.platform_data	= &cf1_data,
+	},
+	.resource	= cf1_resources,
+	.num_resources	= ARRAY_SIZE(cf1_resources),
+};
+
+void __init at91_add_device_cf(struct at91_cf_data *data)
+{
+	unsigned long ebi0_csa;
+	struct platform_device *pdev;
+
+	if (!data)
+		return;
+
+	/*
+	 * assign CS4 or CS5 to SMC with Compact Flash logic support,
+	 * we assume SMC timings are configured by board code,
+	 * except True IDE where timings are controlled by driver
+	 */
+	ebi0_csa = at91_sys_read(AT91_MATRIX_EBI0CSA);
+	switch (data->chipselect) {
+	case 4:
+		at91_set_A_periph(AT91_PIN_PD6, 0);  /* EBI0_NCS4/CFCS0 */
+		ebi0_csa |= AT91_MATRIX_EBI0_CS4A_SMC_CF1;
+		cf0_data = *data;
+		pdev = &cf0_device;
+		break;
+	case 5:
+		at91_set_A_periph(AT91_PIN_PD7, 0);  /* EBI0_NCS5/CFCS1 */
+		ebi0_csa |= AT91_MATRIX_EBI0_CS5A_SMC_CF2;
+		cf1_data = *data;
+		pdev = &cf1_device;
+		break;
+	default:
+		printk(KERN_ERR "AT91 CF: bad chip-select requested (%u)\n",
+		       data->chipselect);
+		return;
+	}
+	at91_sys_write(AT91_MATRIX_EBI0CSA, ebi0_csa);
+
+	if (data->det_pin) {
+		at91_set_gpio_input(data->det_pin, 1);
+		at91_set_deglitch(data->det_pin, 1);
+	}
+
+	if (data->irq_pin) {
+		at91_set_gpio_input(data->irq_pin, 1);
+		at91_set_deglitch(data->irq_pin, 1);
+	}
+
+	if (data->vcc_pin)
+		/* initially off */
+		at91_set_gpio_output(data->vcc_pin, 0);
+
+	/* enable EBI controlled pins */
+	at91_set_A_periph(AT91_PIN_PD5, 1);  /* NWAIT */
+	at91_set_A_periph(AT91_PIN_PD8, 0);  /* CFCE1 */
+	at91_set_A_periph(AT91_PIN_PD9, 0);  /* CFCE2 */
+	at91_set_A_periph(AT91_PIN_PD14, 0); /* CFNRW */
+
+	pdev->name = (data->flags & AT91_CF_TRUE_IDE) ? "at91_ide" : "at91_cf";
+	platform_device_register(pdev);
+}
+#else
+void __init at91_add_device_cf(struct at91_cf_data *data) {}
+#endif
 
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index 0b3ae21..793fe7b 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -56,6 +56,9 @@
 	u8	vcc_pin;		/* power switching */
 	u8	rst_pin;		/* card reset */
 	u8	chipselect;		/* EBI Chip Select number */
+	u8	flags;
+#define AT91_CF_TRUE_IDE	0x01
+#define AT91_IDE_SWAP_A0_A2	0x02
 };
 extern void __init at91_add_device_cf(struct at91_cf_data *data);
 
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 88f7e88..05f0f4f 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -4,6 +4,8 @@
 
 #ifndef __ASSEMBLY__
 
+struct i2c_board_info;
+
 struct ep93xx_eth_data
 {
 	unsigned char	dev_addr[6];
diff --git a/arch/arm/mach-mx1/devices.c b/arch/arm/mach-mx1/devices.c
index 686d8d2..a956441 100644
--- a/arch/arm/mach-mx1/devices.c
+++ b/arch/arm/mach-mx1/devices.c
@@ -23,6 +23,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+
+#include <mach/irqs.h>
 #include <mach/hardware.h>
 
 static struct resource imx_csi_resources[] = {
diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c
index 2e4b185..3200cf6 100644
--- a/arch/arm/mach-mx1/mx1ads.c
+++ b/arch/arm/mach-mx1/mx1ads.c
@@ -21,6 +21,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include <mach/irqs.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/imx-uart.h>
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 38c88fb..e39cd2c 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -178,7 +178,9 @@
 #ifdef CONFIG_I2C2_OMAP_BEAGLE
 	omap_register_i2c_bus(2, 400, NULL, 0);
 #endif
-	omap_register_i2c_bus(3, 400, NULL, 0);
+	/* Bus 3 is attached to the DVI port where devices like the pico DLP
+	 * projector don't work reliably with 400kHz */
+	omap_register_i2c_bus(3, 100, NULL, 0);
 	return 0;
 }
 
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index a4ecf62..8373736 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -434,6 +434,10 @@
 /*****************************************************************************
  * XOR engine
  ****************************************************************************/
+struct mv_xor_platform_shared_data orion5x_xor_shared_data = {
+	.dram		= &orion5x_mbus_dram_info,
+};
+
 static struct resource orion5x_xor_shared_resources[] = {
 	{
 		.name	= "xor low",
@@ -451,6 +455,9 @@
 static struct platform_device orion5x_xor_shared = {
 	.name		= MV_XOR_SHARED_NAME,
 	.id		= 0,
+	.dev		= {
+		.platform_data	= &orion5x_xor_shared_data,
+	},
 	.num_resources	= ARRAY_SIZE(orion5x_xor_shared_resources),
 	.resource	= orion5x_xor_shared_resources,
 };
diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c
index 6d48e00..a6fff78 100644
--- a/arch/arm/mach-pxa/e740.c
+++ b/arch/arm/mach-pxa/e740.c
@@ -135,6 +135,11 @@
 	/* IrDA */
 	GPIO38_GPIO | MFP_LPM_DRIVE_HIGH,
 
+	/* Audio power control */
+	GPIO16_GPIO,  /* AC97 codec AVDD2 supply (analogue power) */
+	GPIO40_GPIO,  /* Mic amp power */
+	GPIO41_GPIO,  /* Headphone amp power */
+
 	/* PC Card */
 	GPIO8_GPIO,   /* CD0 */
 	GPIO44_GPIO,  /* CD1 */
diff --git a/arch/arm/mach-pxa/e750.c b/arch/arm/mach-pxa/e750.c
index be1ab8e..665066f 100644
--- a/arch/arm/mach-pxa/e750.c
+++ b/arch/arm/mach-pxa/e750.c
@@ -133,6 +133,11 @@
 	/* IrDA */
 	GPIO38_GPIO | MFP_LPM_DRIVE_HIGH,
 
+	/* Audio power control */
+	GPIO4_GPIO,  /* Headphone amp power */
+	GPIO7_GPIO,  /* Speaker amp power */
+	GPIO37_GPIO, /* Headphone detect */
+
 	/* PC Card */
 	GPIO8_GPIO,   /* CD0 */
 	GPIO44_GPIO,  /* CD1 */
diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c
index da6e442..295ec41 100644
--- a/arch/arm/mach-pxa/h5000.c
+++ b/arch/arm/mach-pxa/h5000.c
@@ -153,6 +153,13 @@
 	GPIO23_SSP1_SCLK,
 	GPIO25_SSP1_TXD,
 	GPIO26_SSP1_RXD,
+
+	/* I2S */
+	GPIO28_I2S_BITCLK_OUT,
+	GPIO29_I2S_SDATA_IN,
+	GPIO30_I2S_SDATA_OUT,
+	GPIO31_I2S_SYNC,
+	GPIO32_I2S_SYSCLK,
 };
 
 /*
diff --git a/arch/arm/mach-pxa/include/mach/eseries-gpio.h b/arch/arm/mach-pxa/include/mach/eseries-gpio.h
index efbd2aa..f3e5509 100644
--- a/arch/arm/mach-pxa/include/mach/eseries-gpio.h
+++ b/arch/arm/mach-pxa/include/mach/eseries-gpio.h
@@ -45,6 +45,21 @@
 /* e7xx IrDA power control */
 #define GPIO_E7XX_IR_OFF         38
 
+/* e740 audio control GPIOs */
+#define GPIO_E740_WM9705_nAVDD2  16
+#define GPIO_E740_MIC_ON         40
+#define GPIO_E740_AMP_ON         41
+
+/* e750 audio control GPIOs */
+#define GPIO_E750_HP_AMP_OFF      4
+#define GPIO_E750_SPK_AMP_OFF     7
+#define GPIO_E750_HP_DETECT      37
+
+/* e800 audio control GPIOs */
+#define GPIO_E800_HP_DETECT      81
+#define GPIO_E800_HP_AMP_OFF     82
+#define GPIO_E800_SPK_AMP_ON     83
+
 /* ASIC related GPIOs */
 #define GPIO_ESERIES_TMIO_IRQ        5
 #define GPIO_ESERIES_TMIO_PCLR      19
diff --git a/arch/arm/mach-pxa/include/mach/regs-ssp.h b/arch/arm/mach-pxa/include/mach/regs-ssp.h
index cf31986..018f6d6 100644
--- a/arch/arm/mach-pxa/include/mach/regs-ssp.h
+++ b/arch/arm/mach-pxa/include/mach/regs-ssp.h
@@ -50,7 +50,7 @@
 #define SSCR0_TUM	(1 << 23)	/* Transmit FIFO underrun interrupt mask */
 #define SSCR0_FRDC	(0x07000000)	/* Frame rate divider control (mask) */
 #define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24)	/* Time slots per frame [1..8] */
-#define SSCR0_ADC	(1 << 30)	/* Audio clock select */
+#define SSCR0_ACS	(1 << 30)	/* Audio clock select */
 #define SSCR0_MOD	(1 << 31)	/* Mode (normal or network) */
 #endif
 
@@ -109,6 +109,11 @@
 #define SSSR_TINT		(1 << 19)	/* Receiver Time-out Interrupt */
 #define SSSR_PINT		(1 << 18)	/* Peripheral Trailing Byte Interrupt */
 
+#if defined(CONFIG_PXA3xx)
+#define SSPSP_EDMYSTOP(x)	((x) << 28)     /* Extended Dummy Stop */
+#define SSPSP_EDMYSTRT(x)	((x) << 26)     /* Extended Dummy Start */
+#endif
+
 #define SSPSP_FSRT		(1 << 25)	/* Frame Sync Relative Timing */
 #define SSPSP_DMYSTOP(x)	((x) << 23)	/* Dummy Stop */
 #define SSPSP_SFRMWDTH(x)	((x) << 16)	/* Serial Frame Width */
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 6d447c9..0d62d31 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -105,6 +105,12 @@
 	GPIO57_nIOIS16,
 	GPIO104_PSKTSEL,
 
+	/* I2S */
+	GPIO28_I2S_BITCLK_OUT,
+	GPIO29_I2S_SDATA_IN,
+	GPIO30_I2S_SDATA_OUT,
+	GPIO31_I2S_SYNC,
+
 	/* MMC */
 	GPIO32_MMC_CLK,
 	GPIO112_MMC_CMD,
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 552b4c7..440c014 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -28,7 +28,7 @@
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
 static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 6078f09..8331e8d 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -29,13 +29,14 @@
 
 #include <mach/bast-map.h>
 #include <mach/bast-irq.h>
-#include <mach/usb-control.h>
 #include <mach/regs-gpio.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
 
+#include <plat/usb-control.h>
 #include <plat/devs.h>
+
 #include "usb-simtec.h"
 
 /* control power and monitor over-current events on various Simtec
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index 919856c..9e34785 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -29,8 +29,8 @@
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
-#include <asm/plat-s3c24xx/regs-s3c2412-iis.h>
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-s3c2412-iis.h>
+#include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
 #define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c
index 5b5ee0b..69b6cf3 100644
--- a/arch/arm/mach-s3c2440/dma.c
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -28,7 +28,7 @@
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
 static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
index 2a58a4d..8430e582 100644
--- a/arch/arm/mach-s3c2443/dma.c
+++ b/arch/arm/mach-s3c2443/dma.c
@@ -29,7 +29,7 @@
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
 #define MAP(x) { \
diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c
index 3c4d471..25f7935 100644
--- a/arch/arm/mach-s3c6410/mach-smdk6410.c
+++ b/arch/arm/mach-s3c6410/mach-smdk6410.c
@@ -129,7 +129,7 @@
 	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
 };
 
-struct map_desc smdk6410_iodesc[] = {};
+static struct map_desc smdk6410_iodesc[] = {};
 
 static struct platform_device *smdk6410_devices[] __initdata = {
 #ifdef CONFIG_SMDK6410_SD_CH0
@@ -146,7 +146,7 @@
 
 static struct i2c_board_info i2c_devs0[] __initdata = {
 	{ I2C_BOARD_INFO("24c08", 0x50), },
-	{ I2C_BOARD_INFO("WM8580", 0X1b), },
+	{ I2C_BOARD_INFO("wm8580", 0x1b), },
 };
 
 static struct i2c_board_info i2c_devs1[] __initdata = {
diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c
index c3ba6a9..70997d5 100644
--- a/arch/arm/mm/copypage-feroceon.c
+++ b/arch/arm/mm/copypage-feroceon.c
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 
-static void __attribute__((naked))
+static void __naked
 feroceon_copy_user_page(void *kto, const void *kfrom)
 {
 	asm("\
diff --git a/arch/arm/mm/copypage-v3.c b/arch/arm/mm/copypage-v3.c
index 70ed96c..de9c068 100644
--- a/arch/arm/mm/copypage-v3.c
+++ b/arch/arm/mm/copypage-v3.c
@@ -15,7 +15,7 @@
  *
  * FIXME: do we need to handle cache stuff...
  */
-static void __attribute__((naked))
+static void __naked
 v3_copy_user_page(void *kto, const void *kfrom)
 {
 	asm("\n\
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index 1601698..7370a71 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -44,7 +44,7 @@
  * instruction.  If your processor does not supply this, you have to write your
  * own copy_user_highpage that does the right thing.
  */
-static void __attribute__((naked))
+static void __naked
 mc_copy_user_page(void *from, void *to)
 {
 	asm volatile(
diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c
index 3ec93da..9ab0984 100644
--- a/arch/arm/mm/copypage-v4wb.c
+++ b/arch/arm/mm/copypage-v4wb.c
@@ -22,7 +22,7 @@
  * instruction.  If your processor does not supply this, you have to write your
  * own copy_user_highpage that does the right thing.
  */
-static void __attribute__((naked))
+static void __naked
 v4wb_copy_user_page(void *kto, const void *kfrom)
 {
 	asm("\
diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c
index 0f1188e..300efaf 100644
--- a/arch/arm/mm/copypage-v4wt.c
+++ b/arch/arm/mm/copypage-v4wt.c
@@ -20,7 +20,7 @@
  * dirty data in the cache.  However, we do have to ensure that
  * subsequent reads are up to date.
  */
-static void __attribute__((naked))
+static void __naked
 v4wt_copy_user_page(void *kto, const void *kfrom)
 {
 	asm("\
diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c
index 39a9945..bc4525f 100644
--- a/arch/arm/mm/copypage-xsc3.c
+++ b/arch/arm/mm/copypage-xsc3.c
@@ -29,7 +29,7 @@
  * if we eventually end up using our copied page.
  *
  */
-static void __attribute__((naked))
+static void __naked
 xsc3_mc_copy_user_page(void *kto, const void *kfrom)
 {
 	asm("\
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index d18f239..76824d3 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -42,7 +42,7 @@
  * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
  * and merged as appropriate.
  */
-static void __attribute__((naked))
+static void __naked
 mc_copy_user_page(void *from, void *to)
 {
 	/*
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 310e479..f1ef561 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -490,26 +490,30 @@
  */
 void dma_cache_maint(const void *start, size_t size, int direction)
 {
-	const void *end = start + size;
+	void (*inner_op)(const void *, const void *);
+	void (*outer_op)(unsigned long, unsigned long);
 
-	BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end - 1));
+	BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(start + size - 1));
 
 	switch (direction) {
 	case DMA_FROM_DEVICE:		/* invalidate only */
-		dmac_inv_range(start, end);
-		outer_inv_range(__pa(start), __pa(end));
+		inner_op = dmac_inv_range;
+		outer_op = outer_inv_range;
 		break;
 	case DMA_TO_DEVICE:		/* writeback only */
-		dmac_clean_range(start, end);
-		outer_clean_range(__pa(start), __pa(end));
+		inner_op = dmac_clean_range;
+		outer_op = outer_clean_range;
 		break;
 	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */
-		dmac_flush_range(start, end);
-		outer_flush_range(__pa(start), __pa(end));
+		inner_op = dmac_flush_range;
+		outer_op = outer_flush_range;
 		break;
 	default:
 		BUG();
 	}
+
+	inner_op(start, start + size);
+	outer_op(__pa(start), __pa(start) + size);
 }
 EXPORT_SYMBOL(dma_cache_maint);
 
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 34df4d9..80fd3b6 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -382,7 +382,7 @@
 	for_each_node(node)
 		bootmem_free_node(node, mi);
 
-	high_memory = __va(memend_pfn << PAGE_SHIFT);
+	high_memory = __va((memend_pfn << PAGE_SHIFT) - 1) + 1;
 
 	/*
 	 * This doesn't seem to be used by the Linux memory manager any
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 5358fcc..f7457fe 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -124,7 +124,7 @@
 {
 	if (addr < PHYS_OFFSET)
 		return 0;
-	if (addr + size > __pa(high_memory))
+	if (addr + size >= __pa(high_memory - 1))
 		return 0;
 
 	return 1;
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index deaff58..04a100c 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -18,7 +18,8 @@
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
 obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
 obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
-obj-$(CONFIG_I2C_OMAP) += i2c.o
+i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
+obj-y += $(i2c-omap-m) $(i2c-omap-y)
 
 # OMAP mailbox framework
 obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index 0843b88..6825fbb 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -200,20 +200,16 @@
 };
 
 /*
- * 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());
+	unsigned long long ret;
+
+	ret = (unsigned long long)omap_32k_read();
+	ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift;
+	return ret;
 }
 
 static int __init omap_init_clocksource_32k(void)
diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h
index ef70e2b..e746ec7 100644
--- a/arch/arm/plat-omap/include/mach/common.h
+++ b/arch/arm/plat-omap/include/mach/common.h
@@ -35,7 +35,7 @@
 extern struct sys_timer omap_timer;
 extern void omap_serial_init(void);
 extern void omap_serial_enable_clocks(int enable);
-#ifdef CONFIG_I2C_OMAP
+#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
 				 struct i2c_board_info const *info,
 				 unsigned len);
diff --git a/arch/arm/plat-omap/include/mach/pm.h b/arch/arm/plat-omap/include/mach/pm.h
index 2a9c27a..37e2f0f 100644
--- a/arch/arm/plat-omap/include/mach/pm.h
+++ b/arch/arm/plat-omap/include/mach/pm.h
@@ -108,7 +108,7 @@
 	!defined(CONFIG_ARCH_OMAP15XX) && \
 	!defined(CONFIG_ARCH_OMAP16XX) && \
 	!defined(CONFIG_ARCH_OMAP24XX)
-#error "Power management for this processor not implemented yet"
+#warning "Power management for this processor not implemented yet"
 #endif
 
 #ifndef __ASSEMBLER__
diff --git a/arch/arm/mach-s3c2410/include/mach/audio.h b/arch/arm/plat-s3c/include/plat/audio.h
similarity index 100%
rename from arch/arm/mach-s3c2410/include/mach/audio.h
rename to arch/arm/plat-s3c/include/plat/audio.h
diff --git a/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h b/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
similarity index 93%
rename from include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h
rename to arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
index 25d4058..0fad757 100644
--- a/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h
+++ b/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
@@ -33,6 +33,9 @@
 #define S3C2412_IISCON_RXDMA_ACTIVE	(1 << 1)
 #define S3C2412_IISCON_IIS_ACTIVE	(1 << 0)
 
+#define S3C64XX_IISMOD_IMS_PCLK		(0 << 10)
+#define S3C64XX_IISMOD_IMS_SYSMUX	(1 << 10)
+
 #define S3C2412_IISMOD_MASTER_INTERNAL	(0 << 10)
 #define S3C2412_IISMOD_MASTER_EXTERNAL	(1 << 10)
 #define S3C2412_IISMOD_SLAVE		(2 << 10)
@@ -44,8 +47,8 @@
 #define S3C2412_IISMOD_LR_LLOW		(0 << 7)
 #define S3C2412_IISMOD_LR_RLOW		(1 << 7)
 #define S3C2412_IISMOD_SDF_IIS		(0 << 5)
-#define S3C2412_IISMOD_SDF_MSB		(0 << 5)
-#define S3C2412_IISMOD_SDF_LSB		(0 << 5)
+#define S3C2412_IISMOD_SDF_MSB		(1 << 5)
+#define S3C2412_IISMOD_SDF_LSB		(2 << 5)
 #define S3C2412_IISMOD_SDF_MASK		(3 << 5)
 #define S3C2412_IISMOD_RCLK_256FS	(0 << 3)
 #define S3C2412_IISMOD_RCLK_512FS	(1 << 3)
diff --git a/arch/arm/mach-s3c2410/include/mach/usb-control.h b/arch/arm/plat-s3c/include/plat/usb-control.h
similarity index 83%
rename from arch/arm/mach-s3c2410/include/mach/usb-control.h
rename to arch/arm/plat-s3c/include/plat/usb-control.h
index cd91d15..822c87f 100644
--- a/arch/arm/mach-s3c2410/include/mach/usb-control.h
+++ b/arch/arm/plat-s3c/include/plat/usb-control.h
@@ -1,9 +1,9 @@
-/* arch/arm/mach-s3c2410/include/mach/usb-control.h
+/* arch/arm/plat-s3c/include/plat/usb-control.h
  *
  * Copyright (c) 2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C2410 - usb port information
+ * S3C - USB host port information
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,7 +11,7 @@
 */
 
 #ifndef __ASM_ARCH_USBCONTROL_H
-#define __ASM_ARCH_USBCONTROL_H "arch/arm/mach-s3c2410/include/mach/usb-control.h"
+#define __ASM_ARCH_USBCONTROL_H
 
 #define S3C_HCDFLG_USED	(1)
 
diff --git a/include/asm-arm/plat-s3c24xx/regs-iis.h b/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
similarity index 100%
rename from include/asm-arm/plat-s3c24xx/regs-iis.h
rename to arch/arm/plat-s3c24xx/include/plat/regs-iis.h
diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c
index 136c982..ad1b968 100644
--- a/arch/arm/plat-s3c64xx/clock.c
+++ b/arch/arm/plat-s3c64xx/clock.c
@@ -248,7 +248,7 @@
 	&clk_48m,
 };
 
-void s3c64xx_register_clocks(void)
+void __init s3c64xx_register_clocks(void)
 {
 	struct clk *clkp;
 	int ret;
diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c
index cc62941..ee9188a 100644
--- a/arch/arm/plat-s3c64xx/gpiolib.c
+++ b/arch/arm/plat-s3c64xx/gpiolib.c
@@ -417,4 +417,4 @@
 	return 0;
 }
 
-arch_initcall(s3c64xx_gpiolib_init);
+core_initcall(s3c64xx_gpiolib_init);
diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h
index 2846f55..f865bf4 100644
--- a/arch/arm/plat-s3c64xx/include/plat/irqs.h
+++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h
@@ -117,7 +117,7 @@
 #define IRQ_ONENAND1		S3C64XX_IRQ_VIC1(12)
 #define IRQ_NFC			S3C64XX_IRQ_VIC1(13)
 #define IRQ_CFCON		S3C64XX_IRQ_VIC1(14)
-#define IRQ_UHOST		S3C64XX_IRQ_VIC1(15)
+#define IRQ_USBH		S3C64XX_IRQ_VIC1(15)
 #define IRQ_SPI0		S3C64XX_IRQ_VIC1(16)
 #define IRQ_SPI1		S3C64XX_IRQ_VIC1(17)
 #define IRQ_IIC			S3C64XX_IRQ_VIC1(18)
diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c
index ebb305c..cf52482 100644
--- a/arch/arm/plat-s3c64xx/irq-eint.c
+++ b/arch/arm/plat-s3c64xx/irq-eint.c
@@ -14,12 +14,15 @@
 
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 
 #include <asm/hardware/vic.h>
 
 #include <plat/regs-irqtype.h>
+#include <plat/regs-gpio.h>
+#include <plat/gpio-cfg.h>
 
 #include <mach/map.h>
 #include <plat/cpu.h>
@@ -74,6 +77,7 @@
 static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
 {
 	int offs = eint_offset(irq);
+	int pin;
 	int shift;
 	u32 ctrl, mask;
 	u32 newvalue = 0;
@@ -125,6 +129,15 @@
 	ctrl |= newvalue << shift;
 	__raw_writel(ctrl, reg);
 
+	/* set the GPIO pin appropriately */
+
+	if (offs < 23)
+		pin = S3C64XX_GPN(offs);
+	else
+		pin = S3C64XX_GPM(offs - 23);
+
+	s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(2));
+
 	return 0;
 }
 
@@ -181,7 +194,7 @@
 	s3c_irq_demux_eint(20, 27);
 }
 
-int __init s3c64xx_init_irq_eint(void)
+static int __init s3c64xx_init_irq_eint(void)
 {
 	int irq;
 
diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c
index a94f1d5..f22edf7 100644
--- a/arch/arm/plat-s3c64xx/irq.c
+++ b/arch/arm/plat-s3c64xx/irq.c
@@ -207,7 +207,7 @@
 
 static void __init s3c64xx_uart_irq(struct uart_irq *uirq)
 {
-	void *reg_base = uirq->regs;
+	void __iomem *reg_base = uirq->regs;
 	unsigned int irq;
 	int offs;
 
diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c
index 8d9a0ca..05b1752 100644
--- a/arch/arm/plat-s3c64xx/s3c6400-clock.c
+++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c
@@ -36,7 +36,7 @@
  * ext_xtal_mux for want of an actual name from the manual.
 */
 
-struct clk clk_ext_xtal_mux = {
+static struct clk clk_ext_xtal_mux = {
 	.name		= "ext_xtal",
 	.id		= -1,
 };
@@ -63,7 +63,7 @@
 	void __iomem		*reg_divider;
 };
 
-struct clk clk_fout_apll = {
+static struct clk clk_fout_apll = {
 	.name		= "fout_apll",
 	.id		= -1,
 };
@@ -78,7 +78,7 @@
 	.nr_sources	= ARRAY_SIZE(clk_src_apll_list),
 };
 
-struct clksrc_clk clk_mout_apll = {
+static struct clksrc_clk clk_mout_apll = {
 	.clk	= {
 		.name		= "mout_apll",
 		.id		= -1,
@@ -88,7 +88,7 @@
 	.sources	= &clk_src_apll,
 };
 
-struct clk clk_fout_epll = {
+static struct clk clk_fout_epll = {
 	.name		= "fout_epll",
 	.id		= -1,
 };
@@ -103,7 +103,7 @@
 	.nr_sources	= ARRAY_SIZE(clk_src_epll_list),
 };
 
-struct clksrc_clk clk_mout_epll = {
+static struct clksrc_clk clk_mout_epll = {
 	.clk	= {
 		.name		= "mout_epll",
 		.id		= -1,
@@ -123,7 +123,7 @@
 	.nr_sources	= ARRAY_SIZE(clk_src_mpll_list),
 };
 
-struct clksrc_clk clk_mout_mpll = {
+static struct clksrc_clk clk_mout_mpll = {
 	.clk = {
 		.name		= "mout_mpll",
 		.id		= -1,
@@ -145,7 +145,7 @@
 	return rate;
 }
 
-struct clk clk_dout_mpll = {
+static struct clk clk_dout_mpll = {
 	.name		= "dout_mpll",
 	.id		= -1,
 	.parent		= &clk_mout_mpll.clk,
@@ -189,10 +189,10 @@
 };
 
 static struct clk *clkset_uhost_list[] = {
+	&clk_48m,
 	&clk_mout_epll.clk,
 	&clk_dout_mpll,
 	&clk_fin_epll,
-	&clk_48m,
 };
 
 static struct clk_sources clkset_uhost = {
@@ -239,10 +239,12 @@
 
 	rate = clk_round_rate(clk, rate);
 	div = clk_get_rate(clk->parent) / rate;
+	if (div > 16)
+		return -EINVAL;
 
 	val = __raw_readl(reg);
-	val &= ~sclk->mask;
-	val |= (rate - 1) << sclk->shift;
+	val &= ~(0xf << sclk->shift);
+	val |= (div - 1) << sclk->shift;
 	__raw_writel(val, reg);
 
 	return 0;
@@ -351,7 +353,7 @@
 
 static struct clksrc_clk clk_usbhost = {
 	.clk	= {
-		.name		= "usb-host-bus",
+		.name		= "usb-bus-host",
 		.id		= -1,
 		.ctrlbit        = S3C_CLKCON_SCLK_UHOST,
 		.enable		= s3c64xx_sclk_ctrl,
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index fd23c0e..b4211d8 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: Sun Nov 30 16:39:36 2008
+# Last update: Thu Mar 12 18:01:45 2009
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -1811,7 +1811,7 @@
 jade			MACH_JADE		JADE			1821
 ks8695_softplc		MACH_KS8695_SOFTPLC	KS8695_SOFTPLC		1822
 gprisc3			MACH_GPRISC3		GPRISC3			1823
-stamp9260		MACH_STAMP9260		STAMP9260		1824
+stamp9g20		MACH_STAMP9G20		STAMP9G20		1824
 smdk6430		MACH_SMDK6430		SMDK6430		1825
 smdkc100		MACH_SMDKC100		SMDKC100		1826
 tavorevb		MACH_TAVOREVB		TAVOREVB		1827
@@ -1993,4 +1993,134 @@
 benzina			MACH_BENZINA		BENZINA			2003
 blaze			MACH_BLAZE		BLAZE			2004
 linkstation_ls_hgl	MACH_LINKSTATION_LS_HGL	LINKSTATION_LS_HGL	2005
-htcvenus		MACH_HTCVENUS		HTCVENUS		2006
+htckovsky		MACH_HTCVENUS		HTCVENUS		2006
+sony_prs505		MACH_SONY_PRS505	SONY_PRS505		2007
+hanlin_v3		MACH_HANLIN_V3		HANLIN_V3		2008
+sapphira		MACH_SAPPHIRA		SAPPHIRA		2009
+dack_sda_01		MACH_DACK_SDA_01	DACK_SDA_01		2010
+armbox			MACH_ARMBOX		ARMBOX			2011
+harris_rvp		MACH_HARRIS_RVP		HARRIS_RVP		2012
+ribaldo			MACH_RIBALDO		RIBALDO			2013
+agora			MACH_AGORA		AGORA			2014
+omap3_mini		MACH_OMAP3_MINI		OMAP3_MINI		2015
+a9sam6432_b		MACH_A9SAM6432_B	A9SAM6432_B		2016
+usg2410			MACH_USG2410		USG2410			2017
+pc72052_i10_revb	MACH_PC72052_I10_REVB	PC72052_I10_REVB	2018
+mx35_exm32		MACH_MX35_EXM32		MX35_EXM32		2019
+topas910		MACH_TOPAS910		TOPAS910		2020
+hyena			MACH_HYENA		HYENA			2021
+pospax			MACH_POSPAX		POSPAX			2022
+hdl_gx			MACH_HDL_GX		HDL_GX			2023
+ctera_4bay		MACH_CTERA_4BAY		CTERA_4BAY		2024
+ctera_plug_c		MACH_CTERA_PLUG_C	CTERA_PLUG_C		2025
+crwea_plug_i		MACH_CRWEA_PLUG_I	CRWEA_PLUG_I		2026
+egauge2			MACH_EGAUGE2		EGAUGE2			2027
+didj			MACH_DIDJ		DIDJ			2028
+m_s3c2443		MACH_MEISTER		MEISTER			2029
+htcblackstone		MACH_HTCBLACKSTONE	HTCBLACKSTONE		2030
+cpuat9g20		MACH_CPUAT9G20		CPUAT9G20		2031
+smdk6440		MACH_SMDK6440		SMDK6440		2032
+omap_35xx_mvp		MACH_OMAP_35XX_MVP	OMAP_35XX_MVP		2033
+ctera_plug_i		MACH_CTERA_PLUG_I	CTERA_PLUG_I		2034
+pvg610_100		MACH_PVG610		PVG610			2035
+hprw6815		MACH_HPRW6815		HPRW6815		2036
+omap3_oswald		MACH_OMAP3_OSWALD	OMAP3_OSWALD		2037
+nas4220b		MACH_NAS4220B		NAS4220B		2038
+htcraphael_cdma		MACH_HTCRAPHAEL_CDMA	HTCRAPHAEL_CDMA		2039
+htcdiamond_cdma		MACH_HTCDIAMOND_CDMA	HTCDIAMOND_CDMA		2040
+scaler			MACH_SCALER		SCALER			2041
+zylonite2		MACH_ZYLONITE2		ZYLONITE2		2042
+aspenite		MACH_ASPENITE		ASPENITE		2043
+teton			MACH_TETON		TETON			2044
+ttc_dkb			MACH_TTC_DKB		TTC_DKB			2045
+bishop2			MACH_BISHOP2		BISHOP2			2046
+ippv5			MACH_IPPV5		IPPV5			2047
+farm926			MACH_FARM926		FARM926			2048
+mmccpu			MACH_MMCCPU		MMCCPU			2049
+sgmsfl			MACH_SGMSFL		SGMSFL			2050
+tt8000			MACH_TT8000		TT8000			2051
+zrn4300lp		MACH_ZRN4300LP		ZRN4300LP		2052
+mptc			MACH_MPTC		MPTC			2053
+h6051			MACH_H6051		H6051			2054
+pvg610_101		MACH_PVG610_101		PVG610_101		2055
+stamp9261_pc_evb	MACH_STAMP9261_PC_EVB	STAMP9261_PC_EVB	2056
+pelco_odysseus		MACH_PELCO_ODYSSEUS	PELCO_ODYSSEUS		2057
+tny_a9260		MACH_TNY_A9260		TNY_A9260		2058
+tny_a9g20		MACH_TNY_A9G20		TNY_A9G20		2059
+aesop_mp2530f		MACH_AESOP_MP2530F	AESOP_MP2530F		2060
+dx900			MACH_DX900		DX900			2061
+cpodc2			MACH_CPODC2		CPODC2			2062
+tilt_8925		MACH_TILT_8925		TILT_8925		2063
+davinci_dm357_evm	MACH_DAVINCI_DM357_EVM	DAVINCI_DM357_EVM	2064
+swordfish		MACH_SWORDFISH		SWORDFISH		2065
+corvus			MACH_CORVUS		CORVUS			2066
+taurus			MACH_TAURUS		TAURUS			2067
+axm			MACH_AXM		AXM			2068
+axc			MACH_AXC		AXC			2069
+baby			MACH_BABY		BABY			2070
+mp200			MACH_MP200		MP200			2071
+pcm043			MACH_PCM043		PCM043			2072
+hanlin_v3c		MACH_HANLIN_V3C		HANLIN_V3C		2073
+kbk9g20			MACH_KBK9G20		KBK9G20			2074
+adsturbog5		MACH_ADSTURBOG5		ADSTURBOG5		2075
+avenger_lite1		MACH_AVENGER_LITE1	AVENGER_LITE1		2076
+suc82x			MACH_SUC		SUC			2077
+at91sam7s256		MACH_AT91SAM7S256	AT91SAM7S256		2078
+mendoza			MACH_MENDOZA		MENDOZA			2079
+kira			MACH_KIRA		KIRA			2080
+mx1hbm			MACH_MX1HBM		MX1HBM			2081
+quatro43xx		MACH_QUATRO43XX		QUATRO43XX		2082
+quatro4230		MACH_QUATRO4230		QUATRO4230		2083
+nsb400			MACH_NSB400		NSB400			2084
+drp255			MACH_DRP255		DRP255			2085
+thoth			MACH_THOTH		THOTH			2086
+firestone		MACH_FIRESTONE		FIRESTONE		2087
+asusp750		MACH_ASUSP750		ASUSP750		2088
+ctera_dl		MACH_CTERA_DL		CTERA_DL		2089
+socr			MACH_SOCR		SOCR			2090
+htcoxygen		MACH_HTCOXYGEN		HTCOXYGEN		2091
+heroc			MACH_HEROC		HEROC			2092
+zeno6800		MACH_ZENO6800		ZENO6800		2093
+sc2mcs			MACH_SC2MCS		SC2MCS			2094
+gene100			MACH_GENE100		GENE100			2095
+as353x			MACH_AS353X		AS353X			2096
+sheevaplug		MACH_SHEEVAPLUG		SHEEVAPLUG		2097
+at91sam9g20		MACH_AT91SAM9G20	AT91SAM9G20		2098
+mv88f6192gtw_fe		MACH_MV88F6192GTW_FE	MV88F6192GTW_FE		2099
+cc9200			MACH_CC9200		CC9200			2100
+sm9200			MACH_SM9200		SM9200			2101
+tp9200			MACH_TP9200		TP9200			2102
+snapperdv		MACH_SNAPPERDV		SNAPPERDV		2103
+avengers_lite		MACH_AVENGERS_LITE	AVENGERS_LITE		2104
+avengers_lite1		MACH_AVENGERS_LITE1	AVENGERS_LITE1		2105
+omap3axon		MACH_OMAP3AXON		OMAP3AXON		2106
+ma8xx			MACH_MA8XX		MA8XX			2107
+mp201ek			MACH_MP201EK		MP201EK			2108
+davinci_tux		MACH_DAVINCI_TUX	DAVINCI_TUX		2109
+mpa1600			MACH_MPA1600		MPA1600			2110
+pelco_troy		MACH_PELCO_TROY		PELCO_TROY		2111
+nsb667			MACH_NSB667		NSB667			2112
+rovers5_4mpix		MACH_ROVERS5_4MPIX	ROVERS5_4MPIX		2113
+twocom			MACH_TWOCOM		TWOCOM			2114
+ubisys_p9_rcu3r2	MACH_UBISYS_P9_RCU3R2	UBISYS_P9_RCU3R2	2115
+hero_espresso		MACH_HERO_ESPRESSO	HERO_ESPRESSO		2116
+afeusb			MACH_AFEUSB		AFEUSB			2117
+t830			MACH_T830		T830			2118
+spd8020_cc		MACH_SPD8020_CC		SPD8020_CC		2119
+om_3d7k			MACH_OM_3D7K		OM_3D7K			2120
+picocom2		MACH_PICOCOM2		PICOCOM2		2121
+uwg4mx27		MACH_UWG4MX27		UWG4MX27		2122
+uwg4mx31		MACH_UWG4MX31		UWG4MX31		2123
+cherry			MACH_CHERRY		CHERRY			2124
+mx51_babbage		MACH_MX51_BABBAGE	MX51_BABBAGE		2125
+s3c2440turkiye		MACH_S3C2440TURKIYE	S3C2440TURKIYE		2126
+tx37			MACH_TX37		TX37			2127
+sbc2800_9g20		MACH_SBC2800_9G20	SBC2800_9G20		2128
+benzglb			MACH_BENZGLB		BENZGLB			2129
+benztd			MACH_BENZTD		BENZTD			2130
+cartesio_plus		MACH_CARTESIO_PLUS	CARTESIO_PLUS		2131
+solrad_g20		MACH_SOLRAD_G20		SOLRAD_G20		2132
+mx27wallace		MACH_MX27WALLACE	MX27WALLACE		2133
+fmzwebmodul		MACH_FMZWEBMODUL	FMZWEBMODUL		2134
+rd78x00_masa		MACH_RD78X00_MASA	RD78X00_MASA		2135
+smallogger		MACH_SMALLOGGER		SMALLOGGER		2136
diff --git a/arch/avr32/boards/hammerhead/flash.c b/arch/avr32/boards/hammerhead/flash.c
index a98c6dd..559bbcb0 100644
--- a/arch/avr32/boards/hammerhead/flash.c
+++ b/arch/avr32/boards/hammerhead/flash.c
@@ -15,7 +15,6 @@
 #include <linux/mtd/physmap.h>
 #include <linux/usb/isp116x.h>
 #include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
 #include <linux/delay.h>
 
 #include <mach/portmux.h>
diff --git a/arch/avr32/include/asm/uaccess.h b/arch/avr32/include/asm/uaccess.h
index ed09239..245b2ee2 100644
--- a/arch/avr32/include/asm/uaccess.h
+++ b/arch/avr32/include/asm/uaccess.h
@@ -230,10 +230,10 @@
 	asm volatile(							\
 		"1:	ld." suffix "	%1, %3			\n"	\
 		"2:						\n"	\
-		"	.section .fixup, \"ax\"			\n"	\
+		"	.subsection 1				\n"	\
 		"3:	mov	%0, %4				\n"	\
 		"	rjmp	2b				\n"	\
-		"	.previous				\n"	\
+		"	.subsection 0				\n"	\
 		"	.section __ex_table, \"a\"		\n"	\
 		"	.long	1b, 3b				\n"	\
 		"	.previous				\n"	\
@@ -295,10 +295,10 @@
 	asm volatile(							\
 		"1:	st." suffix "	%1, %3			\n"	\
 		"2:						\n"	\
-		"	.section .fixup, \"ax\"			\n"	\
+		"	.subsection 1				\n"	\
 		"3:	mov	%0, %4				\n"	\
 		"	rjmp	2b				\n"	\
-		"	.previous				\n"	\
+		"	.subsection 0				\n"	\
 		"	.section __ex_table, \"a\"		\n"	\
 		"	.long	1b, 3b				\n"	\
 		"	.previous				\n"	\
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 33d4937..009a801 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -150,10 +150,10 @@
 	tlbmiss_restore
 	sub	sp, 4
 	stmts	--sp, r0-lr
-	rcall	save_full_context_ex
+	call	save_full_context_ex
 	mfsr	r12, SYSREG_ECR
 	mov	r11, sp
-	rcall	do_page_fault
+	call	do_page_fault
 	rjmp	ret_from_exception
 
 	.align	2
@@ -250,7 +250,7 @@
 
 	.global ret_from_fork
 ret_from_fork:
-	rcall   schedule_tail
+	call   schedule_tail
 
 	/* check for syscall tracing */
 	get_thread_info r0
@@ -261,7 +261,7 @@
 
 syscall_trace_enter:
 	pushm	r8-r12
-	rcall	syscall_trace
+	call	syscall_trace
 	popm	r8-r12
 	rjmp	syscall_trace_cont
 
@@ -269,14 +269,14 @@
 	bld	r1, TIF_SYSCALL_TRACE
 	brcc	1f
 	unmask_interrupts
-	rcall	syscall_trace
+	call	syscall_trace
 	mask_interrupts
 	ld.w	r1, r0[TI_flags]
 
 1:	bld	r1, TIF_NEED_RESCHED
 	brcc	2f
 	unmask_interrupts
-	rcall	schedule
+	call	schedule
 	mask_interrupts
 	ld.w	r1, r0[TI_flags]
 	rjmp	1b
@@ -287,7 +287,7 @@
 	unmask_interrupts
 	mov	r12, sp
 	mov	r11, r0
-	rcall	do_notify_resume
+	call	do_notify_resume
 	mask_interrupts
 	ld.w	r1, r0[TI_flags]
 	rjmp	1b
@@ -394,7 +394,7 @@
 
 	mfsr	r12, SYSREG_ECR
 	mov	r11, sp
-	rcall	do_critical_exception
+	call	do_critical_exception
 
 	/* We should never get here... */
 bad_return:
@@ -407,18 +407,18 @@
 do_bus_error_write:
 	sub	sp, 4
 	stmts	--sp, r0-lr
-	rcall	save_full_context_ex
+	call	save_full_context_ex
 	mov	r11, 1
 	rjmp	1f
 
 do_bus_error_read:
 	sub	sp, 4
 	stmts	--sp, r0-lr
-	rcall	save_full_context_ex
+	call	save_full_context_ex
 	mov	r11, 0
 1:	mfsr	r12, SYSREG_BEAR
 	mov	r10, sp
-	rcall	do_bus_error
+	call	do_bus_error
 	rjmp	ret_from_exception
 
 	.align	1
@@ -433,7 +433,7 @@
 1:	pushm	r8, r9	/* PC and SR */
 	mfsr	r12, SYSREG_ECR
 	mov	r11, sp
-	rcall	do_nmi
+	call	do_nmi
 	popm	r8-r9
 	mtsr	SYSREG_RAR_NMI, r8
 	tst	r0, r0
@@ -457,29 +457,29 @@
 handle_address_fault:
 	sub	sp, 4
 	stmts	--sp, r0-lr
-	rcall	save_full_context_ex
+	call	save_full_context_ex
 	mfsr	r12, SYSREG_ECR
 	mov	r11, sp
-	rcall	do_address_exception
+	call	do_address_exception
 	rjmp	ret_from_exception
 
 handle_protection_fault:
 	sub	sp, 4
 	stmts	--sp, r0-lr
-	rcall	save_full_context_ex
+	call	save_full_context_ex
 	mfsr	r12, SYSREG_ECR
 	mov	r11, sp
-	rcall	do_page_fault
+	call	do_page_fault
 	rjmp	ret_from_exception
 
 	.align	1
 do_illegal_opcode_ll:
 	sub	sp, 4
 	stmts	--sp, r0-lr
-	rcall	save_full_context_ex
+	call	save_full_context_ex
 	mfsr	r12, SYSREG_ECR
 	mov	r11, sp
-	rcall	do_illegal_opcode
+	call	do_illegal_opcode
 	rjmp	ret_from_exception
 
 do_dtlb_modified:
@@ -513,11 +513,11 @@
 do_fpe_ll:
 	sub	sp, 4
 	stmts	--sp, r0-lr
-	rcall	save_full_context_ex
+	call	save_full_context_ex
 	unmask_interrupts
 	mov	r12, 26
 	mov	r11, sp
-	rcall	do_fpe
+	call	do_fpe
 	rjmp	ret_from_exception
 
 ret_from_exception:
@@ -553,7 +553,7 @@
 	lddsp	r4, sp[REG_SR]
 	bld	r4, SYSREG_GM_OFFSET
 	brcs	1f
-	rcall	preempt_schedule_irq
+	call	preempt_schedule_irq
 1:
 #endif
 
@@ -582,7 +582,7 @@
 	bld	r1, TIF_NEED_RESCHED
 	brcc	1f
 	unmask_interrupts
-	rcall	schedule
+	call	schedule
 	mask_interrupts
 	ld.w	r1, r0[TI_flags]
 	rjmp	fault_exit_work
@@ -593,7 +593,7 @@
 	unmask_interrupts
 	mov	r12, sp
 	mov	r11, r0
-	rcall	do_notify_resume
+	call	do_notify_resume
 	mask_interrupts
 	ld.w	r1, r0[TI_flags]
 	rjmp	fault_exit_work
@@ -616,10 +616,10 @@
 
 .Ldebug_fixup_cont:
 #ifdef CONFIG_TRACE_IRQFLAGS
-	rcall	trace_hardirqs_off
+	call	trace_hardirqs_off
 #endif
 	mov	r12, sp
-	rcall	do_debug
+	call	do_debug
 	mov	sp, r12
 
 	lddsp	r2, sp[REG_SR]
@@ -643,7 +643,7 @@
 	mtsr	SYSREG_RSR_DBG, r11
 	mtsr	SYSREG_RAR_DBG, r10
 #ifdef CONFIG_TRACE_IRQFLAGS
-	rcall	trace_hardirqs_on
+	call	trace_hardirqs_on
 1:
 #endif
 	ldmts	sp++, r0-lr
@@ -676,7 +676,7 @@
 #ifdef CONFIG_TRACE_IRQFLAGS
 	bld	r11, SYSREG_GM_OFFSET
 	brcc	1f
-	rcall	trace_hardirqs_on
+	call	trace_hardirqs_on
 1:
 #endif
 	mfsr	r2, SYSREG_SR
@@ -747,7 +747,7 @@
 	mov	r11, sp
 	mov	r12, \level
 
-	rcall	do_IRQ
+	call	do_IRQ
 
 	lddsp	r4, sp[REG_SR]
 	bfextu	r4, r4, SYSREG_M0_OFFSET, 3
@@ -767,7 +767,7 @@
 
 1:
 #ifdef CONFIG_TRACE_IRQFLAGS
-	rcall	trace_hardirqs_on
+	call	trace_hardirqs_on
 #endif
 	popm	r8-r9
 	mtsr	rar_int\level, r8
@@ -807,7 +807,7 @@
 	lddsp	r4, sp[REG_SR]
 	bld	r4, SYSREG_GM_OFFSET
 	brcs	1b
-	rcall	preempt_schedule_irq
+	call	preempt_schedule_irq
 #endif
 	rjmp	1b
 	.endm
diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S
index 673178e..f7244cd 100644
--- a/arch/avr32/kernel/syscall-stubs.S
+++ b/arch/avr32/kernel/syscall-stubs.S
@@ -61,7 +61,7 @@
 __sys_mmap2:
 	pushm	lr
 	st.w	--sp, ARG6
-	rcall	sys_mmap2
+	call	sys_mmap2
 	sub	sp, -4
 	popm	pc
 
@@ -70,7 +70,7 @@
 __sys_sendto:
 	pushm	lr
 	st.w	--sp, ARG6
-	rcall	sys_sendto
+	call	sys_sendto
 	sub	sp, -4
 	popm	pc
 
@@ -79,7 +79,7 @@
 __sys_recvfrom:
 	pushm	lr
 	st.w	--sp, ARG6
-	rcall	sys_recvfrom
+	call	sys_recvfrom
 	sub	sp, -4
 	popm	pc
 
@@ -88,7 +88,7 @@
 __sys_pselect6:
 	pushm	lr
 	st.w	--sp, ARG6
-	rcall	sys_pselect6
+	call	sys_pselect6
 	sub	sp, -4
 	popm	pc
 
@@ -97,7 +97,7 @@
 __sys_splice:
 	pushm	lr
 	st.w	--sp, ARG6
-	rcall	sys_splice
+	call	sys_splice
 	sub	sp, -4
 	popm	pc
 
@@ -106,7 +106,7 @@
 __sys_epoll_pwait:
 	pushm	lr
 	st.w	--sp, ARG6
-	rcall	sys_epoll_pwait
+	call	sys_epoll_pwait
 	sub	sp, -4
 	popm	pc
 
@@ -115,6 +115,6 @@
 __sys_sync_file_range:
 	pushm	lr
 	st.w	--sp, ARG6
-	rcall	sys_sync_file_range
+	call	sys_sync_file_range
 	sub	sp, -4
 	popm	pc
diff --git a/arch/avr32/lib/strnlen_user.S b/arch/avr32/lib/strnlen_user.S
index 65ce11a..e46f4724 100644
--- a/arch/avr32/lib/strnlen_user.S
+++ b/arch/avr32/lib/strnlen_user.S
@@ -48,7 +48,7 @@
 	lddpc	lr, _task_size
 	sub	r11, lr, r12
 	mov	r9, r11
-	rcall	__strnlen_user
+	call	__strnlen_user
 	cp.w	r12, r9
 	brgt	1f
 	popm	pc
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index 8f1f97d..0c1f86e 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -1129,6 +1129,7 @@
 
 config PM_WAKEUP_BY_GPIO
 	bool "Allow Wakeup from Standby by GPIO"
+	depends on PM && !BF54x
 
 config PM_WAKEUP_GPIO_NUMBER
 	int "GPIO number"
@@ -1168,6 +1169,12 @@
 	default n
 	help
 	  Enable General-Purpose Wake-Up (Voltage Regulator Power-Up)
+	  (all processors, except ADSP-BF549). This option sets
+	  the general-purpose wake-up enable (GPWE) control bit to enable
+	  wake-up upon detection of an active low signal on the /GPW (PH7) pin.
+	  On ADSP-BF549 this option enables the the same functionality on the
+	  /MRXON pin also PH7.
+
 endmenu
 
 menu "CPU Frequency scaling"
diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug
index 5f981d9..79e7e63 100644
--- a/arch/blackfin/Kconfig.debug
+++ b/arch/blackfin/Kconfig.debug
@@ -21,12 +21,6 @@
 config HAVE_ARCH_KGDB
 	def_bool y
 
-config KGDB_TESTCASE
-	tristate "KGDB: for test case in expect"
-	default n
-	help
-	  This is a kgdb test case for automated testing.
-
 config DEBUG_VERBOSE
 	bool "Verbose fault messages"
 	default y
diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig
index 4fdb9e0..281f4b6 100644
--- a/arch/blackfin/configs/BF518F-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Fri Jan  9 17:58:41 2009
+# Linux kernel version: 2.6.28
+# Fri Feb 20 10:01:44 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -133,10 +133,15 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=0
 CONFIG_BF_REV_MAX=2
@@ -426,7 +431,17 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
-# CONFIG_NET_DSA is not set
+CONFIG_NET_DSA=y
+# CONFIG_NET_DSA_TAG_DSA is not set
+# CONFIG_NET_DSA_TAG_EDSA is not set
+# CONFIG_NET_DSA_TAG_TRAILER is not set
+CONFIG_NET_DSA_TAG_STPID=y
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_NET_DSA_KSZ8893M=y
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -529,6 +544,8 @@
 #
 # 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
@@ -561,7 +578,9 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -607,6 +626,7 @@
 # CONFIG_SMC91X is not set
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 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
@@ -764,7 +784,23 @@
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
+# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -788,8 +824,10 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -861,10 +899,18 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
 
 #
 # Platform RTC drivers
@@ -1062,12 +1108,20 @@
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB_TESTCASE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_HWERR is not set
@@ -1100,6 +1154,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
index 833128b..a50050f 100644
--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -327,8 +327,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 # CONFIG_MPU is not set
 
 #
diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
index 334c94b..0a2a00d 100644
--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
@@ -290,8 +290,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 # CONFIG_MPU is not set
 
 #
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
index 9d73343..eb02758 100644
--- a/arch/blackfin/configs/BF533-STAMP_defconfig
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -290,8 +290,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 # CONFIG_MPU is not set
 
 #
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
index 4fb4108..9e62b9f 100644
--- a/arch/blackfin/configs/BF537-STAMP_defconfig
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -298,8 +298,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 # CONFIG_MPU is not set
 
 #
@@ -568,15 +568,7 @@
 # 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 is not set
-CONFIG_MTD_NAND_IDS=m
-# CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_NANDSIM is not set
-CONFIG_MTD_NAND_PLATFORM=m
+# CONFIG_MTD_NAND is not set
 # CONFIG_MTD_ONENAND is not set
 
 #
diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig
index cb32f56..dd6ad6be 100644
--- a/arch/blackfin/configs/BF538-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF538-EZKIT_defconfig
@@ -306,8 +306,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 # CONFIG_MPU is not set
 
 #
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index 0f869761..6bc2fb1 100644
--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -361,8 +361,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 # CONFIG_BFIN_L2_CACHEABLE is not set
 # CONFIG_MPU is not set
 
@@ -680,7 +680,7 @@
 CONFIG_SCSI_DMA=y
 # CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
+# CONFIG_SCSI_PROC_FS is not set
 
 #
 # SCSI support type (disk, tape, CD-ROM)
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index 042c7ad..69714fb 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -329,8 +329,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 # CONFIG_BFIN_L2_CACHEABLE is not set
 # CONFIG_MPU is not set
 
diff --git a/arch/blackfin/configs/BlackStamp_defconfig b/arch/blackfin/configs/BlackStamp_defconfig
index 3a20e28..017c6ea 100644
--- a/arch/blackfin/configs/BlackStamp_defconfig
+++ b/arch/blackfin/configs/BlackStamp_defconfig
@@ -288,8 +288,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 # CONFIG_MPU is not set
 
 #
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
index 865ed85..d880ef7 100644
--- a/arch/blackfin/configs/CM-BF527_defconfig
+++ b/arch/blackfin/configs/CM-BF527_defconfig
@@ -332,8 +332,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 # CONFIG_MPU is not set
 
 #
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
index efe9741..f410430 100644
--- a/arch/blackfin/configs/CM-BF548_defconfig
+++ b/arch/blackfin/configs/CM-BF548_defconfig
@@ -336,8 +336,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 CONFIG_L1_MAX_PIECE=16
 # CONFIG_MPU is not set
 
@@ -595,7 +595,7 @@
 CONFIG_SCSI_DMA=y
 # CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
+# CONFIG_SCSI_PROC_FS is not set
 
 #
 # SCSI support type (disk, tape, CD-ROM)
diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig
index eae83b5..7db9387 100644
--- a/arch/blackfin/configs/IP0X_defconfig
+++ b/arch/blackfin/configs/IP0X_defconfig
@@ -612,7 +612,7 @@
 CONFIG_SCSI=y
 # CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
+# CONFIG_SCSI_PROC_FS is not set
 
 #
 # SCSI support type (disk, tape, CD-ROM)
diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig
index fa580af..a46529c 100644
--- a/arch/blackfin/configs/SRV1_defconfig
+++ b/arch/blackfin/configs/SRV1_defconfig
@@ -282,8 +282,8 @@
 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_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
 CONFIG_L1_MAX_PIECE=16
 
 #
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 606ecfd..09c3141 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -1,3 +1,4 @@
 include include/asm-generic/Kbuild.asm
 
+unifdef-y += bfin_sport.h
 unifdef-y += fixed_code.h
diff --git a/arch/blackfin/include/asm/bfin_sport.h b/arch/blackfin/include/asm/bfin_sport.h
index fe88a2c..65a651d 100644
--- a/arch/blackfin/include/asm/bfin_sport.h
+++ b/arch/blackfin/include/asm/bfin_sport.h
@@ -1,30 +1,9 @@
 /*
- * File:         include/asm-blackfin/bfin_sport.h
- * Based on:
- * Author:       Roy Huang (roy.huang@analog.com)
+ * bfin_sport.h - userspace header for bfin sport driver
  *
- * Created:      Thu Aug. 24 2006
- * Description:
+ * Copyright 2004-2008 Analog Devices Inc.
  *
- * 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
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __BFIN_SPORT_H__
@@ -42,11 +21,10 @@
 #define NORM_FORMAT	0x0
 #define ALAW_FORMAT	0x2
 #define ULAW_FORMAT	0x3
-struct sport_register;
 
 /* Function driver which use sport must initialize the structure */
 struct sport_config {
-	/*TDM (multichannels), I2S or other mode */
+	/* TDM (multichannels), I2S or other mode */
 	unsigned int mode:3;
 
 	/* if TDM mode is selected, channels must be set */
@@ -72,12 +50,18 @@
 	int serial_clk;
 	int fsync_clk;
 
-	unsigned int data_format:2;	/*Normal, u-law or a-law */
+	unsigned int data_format:2;	/* Normal, u-law or a-law */
 
 	int word_len;		/* How length of the word in bits, 3-32 bits */
 	int dma_enabled;
 };
 
+/* Userspace interface */
+#define SPORT_IOC_MAGIC		'P'
+#define SPORT_IOC_CONFIG	_IOWR('P', 0x01, struct sport_config)
+
+#ifdef __KERNEL__
+
 struct sport_register {
 	unsigned short tcr1;
 	unsigned short reserved0;
@@ -117,9 +101,6 @@
 	unsigned long mrcs3;
 };
 
-#define SPORT_IOC_MAGIC		'P'
-#define SPORT_IOC_CONFIG	_IOWR('P', 0x01, struct sport_config)
-
 struct sport_dev {
 	struct cdev cdev;	/* Char device structure */
 
@@ -149,6 +130,8 @@
 	struct sport_config config;
 };
 
+#endif
+
 #define SPORT_TCR1	0
 #define	SPORT_TCR2	1
 #define	SPORT_TCLKDIV	2
@@ -169,4 +152,4 @@
 #define SPORT_MRCS2	22
 #define SPORT_MRCS3	23
 
-#endif				/*__BFIN_SPORT_H__*/
+#endif
diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h
index 76f53d8..343b563 100644
--- a/arch/blackfin/include/asm/ipipe.h
+++ b/arch/blackfin/include/asm/ipipe.h
@@ -35,9 +35,9 @@
 #include <asm/atomic.h>
 #include <asm/traps.h>
 
-#define IPIPE_ARCH_STRING     "1.8-00"
+#define IPIPE_ARCH_STRING     "1.9-00"
 #define IPIPE_MAJOR_NUMBER    1
-#define IPIPE_MINOR_NUMBER    8
+#define IPIPE_MINOR_NUMBER    9
 #define IPIPE_PATCH_NUMBER    0
 
 #ifdef CONFIG_SMP
@@ -83,9 +83,9 @@
 				"%2 = CYCLES2\n"		\
 				"CC = %2 == %0\n"		\
 				"if ! CC jump 1b\n"		\
-				: "=r" (((unsigned long *)&t)[1]),	\
-				  "=r" (((unsigned long *)&t)[0]),	\
-				  "=r" (__cy2)				\
+				: "=d,a" (((unsigned long *)&t)[1]),	\
+				  "=d,a" (((unsigned long *)&t)[0]),	\
+				  "=d,a" (__cy2)				\
 				: /*no input*/ : "CC");			\
 	t;								\
 	})
@@ -118,35 +118,40 @@
 
 #define __ipipe_disable_irq(irq)	(irq_desc[irq].chip->mask(irq))
 
-#define __ipipe_lock_root()					\
-	set_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags)
+static inline int __ipipe_check_tickdev(const char *devname)
+{
+	return 1;
+}
 
-#define __ipipe_unlock_root()					\
-	clear_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags)
+static inline void __ipipe_lock_root(void)
+{
+	set_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status));
+}
+
+static inline void __ipipe_unlock_root(void)
+{
+	clear_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status));
+}
 
 void __ipipe_enable_pipeline(void);
 
 #define __ipipe_hook_critical_ipi(ipd) do { } while (0)
 
-#define __ipipe_sync_pipeline(syncmask)					\
-	do {								\
-		struct ipipe_domain *ipd = ipipe_current_domain;	\
-		if (likely(ipd != ipipe_root_domain || !test_bit(IPIPE_ROOTLOCK_FLAG, &ipd->flags))) \
-			__ipipe_sync_stage(syncmask);			\
-	} while (0)
+#define __ipipe_sync_pipeline  ___ipipe_sync_pipeline
+void ___ipipe_sync_pipeline(unsigned long syncmask);
 
 void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
 
 int __ipipe_get_irq_priority(unsigned irq);
 
-int __ipipe_get_irqthread_priority(unsigned irq);
-
 void __ipipe_stall_root_raw(void);
 
 void __ipipe_unstall_root_raw(void);
 
 void __ipipe_serial_debug(const char *fmt, ...);
 
+asmlinkage void __ipipe_call_irqtail(unsigned long addr);
+
 DECLARE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
 
 extern unsigned long __ipipe_core_clock;
@@ -162,42 +167,25 @@
 
 #define __ipipe_run_irqtail()  /* Must be a macro */			\
 	do {								\
-		asmlinkage void __ipipe_call_irqtail(void);		\
 		unsigned long __pending;				\
-		CSYNC();					\
+		CSYNC();						\
 		__pending = bfin_read_IPEND();				\
 		if (__pending & 0x8000) {				\
 			__pending &= ~0x8010;				\
 			if (__pending && (__pending & (__pending - 1)) == 0) \
-				__ipipe_call_irqtail();			\
+				__ipipe_call_irqtail(__ipipe_irq_tail_hook); \
 		}							\
 	} while (0)
 
 #define __ipipe_run_isr(ipd, irq)					\
 	do {								\
 		if (ipd == ipipe_root_domain) {				\
-			/*						\
-			 * Note: the I-pipe implements a threaded interrupt model on \
-			 * this arch for Linux external IRQs. The interrupt handler we \
-			 * call here only wakes up the associated IRQ thread. \
-			 */						\
-			if (ipipe_virtual_irq_p(irq)) {			\
-				/* No irqtail here; virtual interrupts have no effect \
-				   on IPEND so there is no need for processing \
-				   deferral. */				\
-				local_irq_enable_nohead(ipd);		\
+			local_irq_enable_hw();				\
+			if (ipipe_virtual_irq_p(irq))			\
 				ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
-				local_irq_disable_nohead(ipd);		\
-			} else						\
-				/*					\
-				 * No need to run the irqtail here either; \
-				 * we can't be preempted by hw IRQs, so	\
-				 * non-Linux IRQs cannot stack over the short \
-				 * thread wakeup code. Which in turn means \
-				 * that no irqtail condition could be pending \
-				 * for domains above Linux in the pipeline. \
-				 */					\
+			else						\
 				ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
+			local_irq_disable_hw();				\
 		} else {						\
 			__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
 			local_irq_enable_nohead(ipd);			\
@@ -217,42 +205,24 @@
 
 int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
 
-#define IS_SYSIRQ(irq)		((irq) > IRQ_CORETMR && (irq) <= SYS_IRQS)
-#define IS_GPIOIRQ(irq)		((irq) >= GPIO_IRQ_BASE && (irq) < NR_IRQS)
-
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+#define IRQ_SYSTMR		IRQ_CORETMR
+#define IRQ_PRIOTMR		IRQ_CORETMR
+#else
 #define IRQ_SYSTMR		IRQ_TIMER0
 #define IRQ_PRIOTMR		CONFIG_IRQ_TIMER0
+#endif
 
-#if defined(CONFIG_BF531) || defined(CONFIG_BF532) || defined(CONFIG_BF533)
-#define PRIO_GPIODEMUX(irq)	CONFIG_PFA
-#elif defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537)
-#define PRIO_GPIODEMUX(irq)	CONFIG_IRQ_PROG_INTA
-#elif defined(CONFIG_BF52x)
-#define PRIO_GPIODEMUX(irq)	((irq) == IRQ_PORTF_INTA ? CONFIG_IRQ_PORTF_INTA : \
-				 (irq) == IRQ_PORTG_INTA ? CONFIG_IRQ_PORTG_INTA : \
-				 (irq) == IRQ_PORTH_INTA ? CONFIG_IRQ_PORTH_INTA : \
-				 -1)
-#elif defined(CONFIG_BF561)
-#define PRIO_GPIODEMUX(irq)	((irq) == IRQ_PROG0_INTA ? CONFIG_IRQ_PROG0_INTA : \
-				 (irq) == IRQ_PROG1_INTA ? CONFIG_IRQ_PROG1_INTA : \
-				 (irq) == IRQ_PROG2_INTA ? CONFIG_IRQ_PROG2_INTA : \
-				 -1)
+#ifdef CONFIG_BF561
 #define bfin_write_TIMER_DISABLE(val)	bfin_write_TMRS8_DISABLE(val)
 #define bfin_write_TIMER_ENABLE(val)	bfin_write_TMRS8_ENABLE(val)
 #define bfin_write_TIMER_STATUS(val)	bfin_write_TMRS8_STATUS(val)
 #define bfin_read_TIMER_STATUS()	bfin_read_TMRS8_STATUS()
 #elif defined(CONFIG_BF54x)
-#define PRIO_GPIODEMUX(irq)	((irq) == IRQ_PINT0 ? CONFIG_IRQ_PINT0 : \
-				 (irq) == IRQ_PINT1 ? CONFIG_IRQ_PINT1 : \
-				 (irq) == IRQ_PINT2 ? CONFIG_IRQ_PINT2 : \
-				 (irq) == IRQ_PINT3 ? CONFIG_IRQ_PINT3 : \
-				 -1)
 #define bfin_write_TIMER_DISABLE(val)	bfin_write_TIMER_DISABLE0(val)
 #define bfin_write_TIMER_ENABLE(val)	bfin_write_TIMER_ENABLE0(val)
 #define bfin_write_TIMER_STATUS(val)	bfin_write_TIMER_STATUS0(val)
 #define bfin_read_TIMER_STATUS(val)	bfin_read_TIMER_STATUS0(val)
-#else
-# error "no PRIO_GPIODEMUX() for this part"
 #endif
 
 #define __ipipe_root_tick_p(regs)	((regs->ipend & 0x10) != 0)
@@ -275,4 +245,6 @@
 
 #endif /* !CONFIG_IPIPE */
 
+#define ipipe_update_tick_evtdev(evtdev)	do { } while (0)
+
 #endif	/* !__ASM_BLACKFIN_IPIPE_H */
diff --git a/arch/blackfin/include/asm/ipipe_base.h b/arch/blackfin/include/asm/ipipe_base.h
index cb1025a..3e8acbd 100644
--- a/arch/blackfin/include/asm/ipipe_base.h
+++ b/arch/blackfin/include/asm/ipipe_base.h
@@ -1,5 +1,5 @@
 /*   -*- linux-c -*-
- *   include/asm-blackfin/_baseipipe.h
+ *   include/asm-blackfin/ipipe_base.h
  *
  *   Copyright (C) 2007 Philippe Gerum.
  *
@@ -27,8 +27,9 @@
 #define IPIPE_NR_XIRQS		NR_IRQS
 #define IPIPE_IRQ_ISHIFT	5	/* 2^5 for 32bits arch. */
 
-/* Blackfin-specific, global domain flags */
-#define IPIPE_ROOTLOCK_FLAG	1	/* Lock pipeline for root */
+/* Blackfin-specific, per-cpu pipeline status */
+#define IPIPE_SYNCDEFER_FLAG	15
+#define IPIPE_SYNCDEFER_MASK	(1L << IPIPE_SYNCDEFER_MASK)
 
  /* Blackfin traps -- i.e. exception vector numbers */
 #define IPIPE_NR_FAULTS		52 /* We leave a gap after VEC_ILL_RES. */
@@ -48,11 +49,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/bitops.h>
-
-extern int test_bit(int nr, const void *addr);
-
-
 extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
 
 static inline void __ipipe_stall_root(void)
diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h
index 3d97790..7645e85 100644
--- a/arch/blackfin/include/asm/irq.h
+++ b/arch/blackfin/include/asm/irq.h
@@ -61,20 +61,38 @@
 #define raw_irqs_disabled_flags(flags)	(!irqs_enabled_from_flags_hw(flags))
 #define local_test_iflag_hw(x)		irqs_enabled_from_flags_hw(x)
 
-#define local_save_flags(x)						\
-	do {								\
-		(x) = __ipipe_test_root() ? \
+#define local_save_flags(x)					 \
+	do {							 \
+		(x) = __ipipe_test_root() ?			 \
 			__all_masked_irq_flags : bfin_irq_flags; \
+		barrier();					 \
 	} while (0)
 
-#define local_irq_save(x)				\
-	do {						\
-		(x) = __ipipe_test_and_stall_root();	\
+#define local_irq_save(x)					 \
+	do {						 	 \
+		(x) = __ipipe_test_and_stall_root() ?		 \
+			__all_masked_irq_flags : bfin_irq_flags; \
+		barrier();					 \
 	} while (0)
 
-#define local_irq_restore(x)	__ipipe_restore_root(x)
-#define local_irq_disable()	__ipipe_stall_root()
-#define local_irq_enable()	__ipipe_unstall_root()
+static inline void local_irq_restore(unsigned long x)
+{
+	barrier();
+	__ipipe_restore_root(x == __all_masked_irq_flags);
+}
+
+#define local_irq_disable()			\
+	do {					\
+		__ipipe_stall_root();		\
+		barrier();			\
+	} while (0)
+
+static inline void local_irq_enable(void)
+{
+	barrier();
+	__ipipe_unstall_root();
+}
+
 #define irqs_disabled()		__ipipe_test_root()
 
 #define local_save_flags_hw(x) \
diff --git a/arch/blackfin/include/asm/thread_info.h b/arch/blackfin/include/asm/thread_info.h
index e721ce5..2920087 100644
--- a/arch/blackfin/include/asm/thread_info.h
+++ b/arch/blackfin/include/asm/thread_info.h
@@ -122,6 +122,7 @@
 #define TIF_MEMDIE              4
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_FREEZE              6       /* is freezing for suspend */
+#define TIF_IRQ_SYNC            7       /* sync pipeline stage */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -130,6 +131,7 @@
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_FREEZE             (1<<TIF_FREEZE)
+#define _TIF_IRQ_SYNC           (1<<TIF_IRQ_SYNC)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 4a92a86..fd4d432 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -15,13 +15,15 @@
     obj-y += time.o
 endif
 
-CFLAGS_kgdb_test.o := -mlong-calls -O0
-
 obj-$(CONFIG_IPIPE)                  += ipipe.o
 obj-$(CONFIG_IPIPE_TRACE_MCOUNT)     += mcount.o
 obj-$(CONFIG_BFIN_GPTIMERS)          += gptimers.o
 obj-$(CONFIG_CPLB_INFO)              += cplbinfo.o
 obj-$(CONFIG_MODULES)                += module.o
 obj-$(CONFIG_KGDB)                   += kgdb.o
-obj-$(CONFIG_KGDB_TESTCASE)          += kgdb_test.o
+obj-$(CONFIG_KGDB_TESTS)             += kgdb_test.o
 obj-$(CONFIG_EARLY_PRINTK)           += early_printk.o
+
+# the kgdb test puts code into L2 and without linker
+# relaxation, we need to force long calls to/from it
+CFLAGS_kgdb_test.o := -mlong-calls -O0
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
index 0e28f75..d6c0677 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
@@ -53,9 +53,13 @@
 
 	i_d = i_i = 0;
 
+#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
 	/* Set up the zero page.  */
 	d_tbl[i_d].addr = 0;
 	d_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
+	i_tbl[i_i].addr = 0;
+	i_tbl[i_i++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
+#endif
 
 	/* Cover kernel memory with 4M pages.  */
 	addr = 0;
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c
index 339be5a..a5de8d4 100644
--- a/arch/blackfin/kernel/ipipe.c
+++ b/arch/blackfin/kernel/ipipe.c
@@ -35,14 +35,8 @@
 #include <asm/atomic.h>
 #include <asm/io.h>
 
-static int create_irq_threads;
-
 DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
 
-static DEFINE_PER_CPU(unsigned long, pending_irqthread_mask);
-
-static DEFINE_PER_CPU(int [IVG13 + 1], pending_irq_count);
-
 asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
 
 static void __ipipe_no_irqtail(void);
@@ -93,6 +87,7 @@
  */
 void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
 {
+	struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
 	struct ipipe_domain *this_domain, *next_domain;
 	struct list_head *head, *pos;
 	int m_ack, s = -1;
@@ -104,7 +99,6 @@
 	 * interrupt.
 	 */
 	m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
-
 	this_domain = ipipe_current_domain;
 
 	if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control)))
@@ -114,49 +108,28 @@
 		next_domain = list_entry(head, struct ipipe_domain, p_link);
 		if (likely(test_bit(IPIPE_WIRED_FLAG, &next_domain->irqs[irq].control))) {
 			if (!m_ack && next_domain->irqs[irq].acknowledge != NULL)
-				next_domain->irqs[irq].acknowledge(irq, irq_desc + irq);
-			if (test_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags))
-				s = __test_and_set_bit(IPIPE_STALL_FLAG,
-						       &ipipe_root_cpudom_var(status));
+				next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
+			if (test_bit(IPIPE_SYNCDEFER_FLAG, &p->status))
+				s = __test_and_set_bit(IPIPE_STALL_FLAG, &p->status);
 			__ipipe_dispatch_wired(next_domain, irq);
-				goto finalize;
-			return;
+			goto out;
 		}
 	}
 
 	/* Ack the interrupt. */
 
 	pos = head;
-
 	while (pos != &__ipipe_pipeline) {
 		next_domain = list_entry(pos, struct ipipe_domain, p_link);
-		/*
-		 * For each domain handling the incoming IRQ, mark it
-		 * as pending in its log.
-		 */
 		if (test_bit(IPIPE_HANDLE_FLAG, &next_domain->irqs[irq].control)) {
-			/*
-			 * Domains that handle this IRQ are polled for
-			 * acknowledging it by decreasing priority
-			 * order. The interrupt must be made pending
-			 * _first_ in the domain's status flags before
-			 * the PIC is unlocked.
-			 */
 			__ipipe_set_irq_pending(next_domain, irq);
-
 			if (!m_ack && next_domain->irqs[irq].acknowledge != NULL) {
-				next_domain->irqs[irq].acknowledge(irq, irq_desc + irq);
+				next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
 				m_ack = 1;
 			}
 		}
-
-		/*
-		 * If the domain does not want the IRQ to be passed
-		 * down the interrupt pipe, exit the loop now.
-		 */
 		if (!test_bit(IPIPE_PASS_FLAG, &next_domain->irqs[irq].control))
 			break;
-
 		pos = next_domain->p_link.next;
 	}
 
@@ -166,18 +139,24 @@
 	 * immediately to the current domain if the interrupt has been
 	 * marked as 'sticky'. This search does not go beyond the
 	 * current domain in the pipeline. We also enforce the
-	 * additional root stage lock (blackfin-specific). */
+	 * additional root stage lock (blackfin-specific).
+	 */
+	if (test_bit(IPIPE_SYNCDEFER_FLAG, &p->status))
+		s = __test_and_set_bit(IPIPE_STALL_FLAG, &p->status);
 
-	if (test_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags))
-		s = __test_and_set_bit(IPIPE_STALL_FLAG,
-				       &ipipe_root_cpudom_var(status));
-finalize:
+	/*
+	 * If the interrupt preempted the head domain, then do not
+	 * even try to walk the pipeline, unless an interrupt is
+	 * pending for it.
+	 */
+	if (test_bit(IPIPE_AHEAD_FLAG, &this_domain->flags) &&
+	    ipipe_head_cpudom_var(irqpend_himask) == 0)
+		goto out;
 
 	__ipipe_walk_pipeline(head);
-
+out:
 	if (!s)
-		__clear_bit(IPIPE_STALL_FLAG,
-			    &ipipe_root_cpudom_var(status));
+		__clear_bit(IPIPE_STALL_FLAG, &p->status);
 }
 
 int __ipipe_check_root(void)
@@ -187,7 +166,7 @@
 
 void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
 {
-	struct irq_desc *desc = irq_desc + irq;
+	struct irq_desc *desc = irq_to_desc(irq);
 	int prio = desc->ic_prio;
 
 	desc->depth = 0;
@@ -199,7 +178,7 @@
 
 void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
 {
-	struct irq_desc *desc = irq_desc + irq;
+	struct irq_desc *desc = irq_to_desc(irq);
 	int prio = desc->ic_prio;
 
 	if (ipd != &ipipe_root &&
@@ -236,15 +215,18 @@
 {
 	unsigned long flags;
 
-	/* We need to run the IRQ tail hook whenever we don't
+	/*
+	 * We need to run the IRQ tail hook whenever we don't
 	 * propagate a syscall to higher domains, because we know that
 	 * important operations might be pending there (e.g. Xenomai
-	 * deferred rescheduling). */
+	 * deferred rescheduling).
+	 */
 
-	if (!__ipipe_syscall_watched_p(current, regs->orig_p0)) {
+	if (regs->orig_p0 < NR_syscalls) {
 		void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
 		hook();
-		return 0;
+		if ((current->flags & PF_EVNOTIFY) == 0)
+			return 0;
 	}
 
 	/*
@@ -312,112 +294,46 @@
 {
 	unsigned long flags;
 
+#ifdef CONFIG_IPIPE_DEBUG
 	if (irq >= IPIPE_NR_IRQS ||
 	    (ipipe_virtual_irq_p(irq)
 	     && !test_bit(irq - IPIPE_VIRQ_BASE, &__ipipe_virtual_irq_map)))
 		return -EINVAL;
+#endif
 
 	local_irq_save_hw(flags);
-
 	__ipipe_handle_irq(irq, NULL);
-
 	local_irq_restore_hw(flags);
 
 	return 1;
 }
 
-/* Move Linux IRQ to threads. */
-
-static int do_irqd(void *__desc)
+asmlinkage void __ipipe_sync_root(void)
 {
-	struct irq_desc *desc = __desc;
-	unsigned irq = desc - irq_desc;
-	int thrprio = desc->thr_prio;
-	int thrmask = 1 << thrprio;
-	int cpu = smp_processor_id();
-	cpumask_t cpumask;
+	unsigned long flags;
 
-	sigfillset(&current->blocked);
-	current->flags |= PF_NOFREEZE;
-	cpumask = cpumask_of_cpu(cpu);
-	set_cpus_allowed(current, cpumask);
-	ipipe_setscheduler_root(current, SCHED_FIFO, 50 + thrprio);
+	BUG_ON(irqs_disabled());
 
-	while (!kthread_should_stop()) {
-		local_irq_disable();
-		if (!(desc->status & IRQ_SCHEDULED)) {
-			set_current_state(TASK_INTERRUPTIBLE);
-resched:
-			local_irq_enable();
-			schedule();
-			local_irq_disable();
-		}
-		__set_current_state(TASK_RUNNING);
-		/*
-		 * If higher priority interrupt servers are ready to
-		 * run, reschedule immediately. We need this for the
-		 * GPIO demux IRQ handler to unmask the interrupt line
-		 * _last_, after all GPIO IRQs have run.
-		 */
-		if (per_cpu(pending_irqthread_mask, cpu) & ~(thrmask|(thrmask-1)))
-			goto resched;
-		if (--per_cpu(pending_irq_count[thrprio], cpu) == 0)
-			per_cpu(pending_irqthread_mask, cpu) &= ~thrmask;
-		desc->status &= ~IRQ_SCHEDULED;
-		desc->thr_handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs));
-		local_irq_enable();
-	}
-	__set_current_state(TASK_RUNNING);
-	return 0;
+	local_irq_save_hw(flags);
+
+	clear_thread_flag(TIF_IRQ_SYNC);
+
+	if (ipipe_root_cpudom_var(irqpend_himask) != 0)
+		__ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
+
+	local_irq_restore_hw(flags);
 }
 
-static void kick_irqd(unsigned irq, void *cookie)
+void ___ipipe_sync_pipeline(unsigned long syncmask)
 {
-	struct irq_desc *desc = irq_desc + irq;
-	int thrprio = desc->thr_prio;
-	int thrmask = 1 << thrprio;
-	int cpu = smp_processor_id();
+	struct ipipe_domain *ipd = ipipe_current_domain;
 
-	if (!(desc->status & IRQ_SCHEDULED)) {
-		desc->status |= IRQ_SCHEDULED;
-		per_cpu(pending_irqthread_mask, cpu) |= thrmask;
-		++per_cpu(pending_irq_count[thrprio], cpu);
-		wake_up_process(desc->thread);
-	}
-}
-
-int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc)
-{
-	if (desc->thread || !create_irq_threads)
-		return 0;
-
-	desc->thread = kthread_create(do_irqd, desc, "IRQ %d", irq);
-	if (desc->thread == NULL) {
-		printk(KERN_ERR "irqd: could not create IRQ thread %d!\n", irq);
-		return -ENOMEM;
+	if (ipd == ipipe_root_domain) {
+		if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
+			return;
 	}
 
-	wake_up_process(desc->thread);
-
-	desc->thr_handler = ipipe_root_domain->irqs[irq].handler;
-	ipipe_root_domain->irqs[irq].handler = &kick_irqd;
-
-	return 0;
-}
-
-void __init ipipe_init_irq_threads(void)
-{
-	unsigned irq;
-	struct irq_desc *desc;
-
-	create_irq_threads = 1;
-
-	for (irq = 0; irq < NR_IRQS; irq++) {
-		desc = irq_desc + irq;
-		if (desc->action != NULL ||
-			(desc->status & IRQ_NOREQUEST) != 0)
-			ipipe_start_irq_thread(irq, desc);
-	}
+	__ipipe_sync_stage(syncmask);
 }
 
 EXPORT_SYMBOL(show_stack);
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c
index 75724ee..7fd1265 100644
--- a/arch/blackfin/kernel/irqchip.c
+++ b/arch/blackfin/kernel/irqchip.c
@@ -144,11 +144,15 @@
 #endif
 	generic_handle_irq(irq);
 
-#ifndef CONFIG_IPIPE	/* Useless and bugous over the I-pipe: IRQs are threaded. */
-	/* If we're the only interrupt running (ignoring IRQ15 which is for
-	   syscalls), lower our priority to IRQ14 so that softirqs run at
-	   that level.  If there's another, lower-level interrupt, irq_exit
-	   will defer softirqs to that.  */
+#ifndef CONFIG_IPIPE
+	/*
+	 * If we're the only interrupt running (ignoring IRQ15 which
+	 * is for syscalls), lower our priority to IRQ14 so that
+	 * softirqs run at that level.  If there's another,
+	 * lower-level interrupt, irq_exit will defer softirqs to
+	 * that. If the interrupt pipeline is enabled, we are already
+	 * running at IRQ14 priority, so we don't need this code.
+	 */
 	CSYNC();
 	pending = bfin_read_IPEND() & ~0x8000;
 	other_ints = pending & (pending - 1);
diff --git a/arch/blackfin/kernel/kgdb_test.c b/arch/blackfin/kernel/kgdb_test.c
index 3dba9c1..dbcf3e4 100644
--- a/arch/blackfin/kernel/kgdb_test.c
+++ b/arch/blackfin/kernel/kgdb_test.c
@@ -20,6 +20,7 @@
 static char cmdline[256];
 static unsigned long len;
 
+#ifndef CONFIG_SMP
 static int num1 __attribute__((l1_data));
 
 void kgdb_l1_test(void) __attribute__((l1_text));
@@ -32,6 +33,8 @@
 	printk(KERN_ALERT "L1(after change) : data variable addr = 0x%p, data value is %d\n", &num1, num1);
 	return ;
 }
+#endif
+
 #if L2_LENGTH
 
 static int num2 __attribute__((l2));
@@ -59,10 +62,12 @@
 static int test_proc_output(char *buf)
 {
 	kgdb_test("hello world!", 12, 0x55, 0x10);
+#ifndef CONFIG_SMP
 	kgdb_l1_test();
-	#if L2_LENGTH
+#endif
+#if L2_LENGTH
 	kgdb_l2_test();
-	#endif
+#endif
 
 	return 0;
 }
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 594e325..d76618d 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -45,6 +45,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/dma.h>
 #include <asm/fixed_code.h>
+#include <asm/cacheflush.h>
 #include <asm/mem_map.h>
 
 #define TEXT_OFFSET 0
@@ -240,7 +241,7 @@
 
 			} else if (addr >= FIXED_CODE_START
 			    && addr + sizeof(tmp) <= FIXED_CODE_END) {
-				memcpy(&tmp, (const void *)(addr), sizeof(tmp));
+				copy_from_user_page(0, 0, 0, &tmp, (const void *)(addr), sizeof(tmp));
 				copied = sizeof(tmp);
 
 			} else
@@ -320,7 +321,7 @@
 
 			} else if (addr >= FIXED_CODE_START
 			    && addr + sizeof(data) <= FIXED_CODE_END) {
-				memcpy((void *)(addr), &data, sizeof(data));
+				copy_to_user_page(0, 0, 0, (void *)(addr), &data, sizeof(data));
 				copied = sizeof(data);
 
 			} else
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index e5c1162..a58687b 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -889,6 +889,10 @@
 			       CPU, bfin_revid());
 	}
 
+	/* We can't run on BF548-0.1 due to ANOMALY 05000448 */
+	if (bfin_cpuid() == 0x27de && bfin_revid() == 1)
+		panic("You can't run on this processor due to 05000448\n");
+
 	printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
 
 	printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n",
@@ -1141,12 +1145,12 @@
 		icache_size = 0;
 
 	seq_printf(m, "cache size\t: %d KB(L1 icache) "
-		"%d KB(L1 dcache-%s) %d KB(L2 cache)\n",
+		"%d KB(L1 dcache%s) %d KB(L2 cache)\n",
 		icache_size, dcache_size,
 #if defined CONFIG_BFIN_WB
-		"wb"
+		"-wb"
 #elif defined CONFIG_BFIN_WT
-		"wt"
+		"-wt"
 #endif
 		"", 0);
 
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index 172b4c58..1bbacfb 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -134,7 +134,10 @@
 
 	write_seqlock(&xtime_lock);
 #if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE)
-/* FIXME: Here TIMIL0 is not set when IPIPE enabled, why? */
+	/*
+	 * TIMIL0 is latched in __ipipe_grab_irq() when the I-Pipe is
+	 * enabled.
+	 */
 	if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) {
 #endif
 		do_timer(1);
diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c
index 0e17534..41f2eac 100644
--- a/arch/blackfin/mach-bf518/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf518/boards/ezbrd.c
@@ -113,7 +113,6 @@
 	.name = "bfin_mac",
 	.dev.platform_data = &bfin_mii_bus,
 };
-#endif
 
 #if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
 static struct dsa_platform_data ksz8893m_switch_data = {
@@ -132,6 +131,7 @@
 	.dev.platform_data = &ksz8893m_switch_data,
 };
 #endif
+#endif
 
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -171,6 +171,7 @@
 };
 #endif
 
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #if defined(CONFIG_NET_DSA_KSZ8893M) \
 	|| defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
 /* SPI SWITCH CHIP */
@@ -179,10 +180,11 @@
 	.bits_per_word = 8,
 };
 #endif
+#endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -259,6 +261,7 @@
 	},
 #endif
 
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #if defined(CONFIG_NET_DSA_KSZ8893M) \
 	|| defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
 	{
@@ -271,24 +274,15 @@
 		.mode = SPI_MODE_3,
 	},
 #endif
+#endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc_dummy",
+		.modalias = "mmc_spi",
 		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -630,11 +624,10 @@
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 	&bfin_mii_bus,
 	&bfin_mac_device,
-#endif
-
 #if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
 	&ksz8893m_switch_device,
 #endif
+#endif
 
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
 	&bfin_spi0_device,
diff --git a/arch/blackfin/mach-bf518/include/mach/anomaly.h b/arch/blackfin/mach-bf518/include/mach/anomaly.h
index e5b4bef..c847bb1 100644
--- a/arch/blackfin/mach-bf518/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf518/include/mach/anomaly.h
@@ -2,12 +2,12 @@
  * File: include/asm-blackfin/mach-bf518/anomaly.h
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
- * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2004-2009 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
 /* This file shoule be up to date with:
- *  - ????
+ *  - Revision B, 02/03/2009; ADSP-BF512/BF514/BF516/BF518 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
@@ -19,6 +19,8 @@
 #define ANOMALY_05000122 (1)
 /* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
+/* Incorrect Timer Pulse Width in Single-Shot PWM_OUT Mode with External Clock */
+#define ANOMALY_05000254 (1)
 /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
 #define ANOMALY_05000265 (1)
 /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
@@ -53,6 +55,12 @@
 #define ANOMALY_05000443 (1)
 /* Incorrect L1 Instruction Bank B Memory Map Location */
 #define ANOMALY_05000444 (1)
+/* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
+#define ANOMALY_05000452 (1)
+/* PWM_TRIPB Signal Not Available on PG10 */
+#define ANOMALY_05000453 (1)
+/* PPI_FS3 is Driven One Half Cycle Later Than PPI Data */
+#define ANOMALY_05000455 (1)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000125 (0)
@@ -65,15 +73,20 @@
 #define ANOMALY_05000263 (0)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000273 (0)
+#define ANOMALY_05000278 (0)
 #define ANOMALY_05000285 (0)
+#define ANOMALY_05000305 (0)
 #define ANOMALY_05000307 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000312 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (0)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (0)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000432 (0)
+#define ANOMALY_05000447 (0)
+#define ANOMALY_05000448 (0)
 
 #endif
diff --git a/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
index b50a63b..e21c1c3 100644
--- a/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
+++ b/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
@@ -144,7 +144,7 @@
 	 CH_UART0_TX,
 	 CH_UART0_RX,
 #endif
-#ifdef CONFIG_BFIN_UART0_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	 CONFIG_UART0_CTS_PIN,
 	 CONFIG_UART0_RTS_PIN,
 #endif
@@ -158,7 +158,7 @@
 	 CH_UART1_TX,
 	 CH_UART1_RX,
 #endif
-#ifdef CONFIG_BFIN_UART1_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	 CONFIG_UART1_CTS_PIN,
 	 CONFIG_UART1_RTS_PIN,
 #endif
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index 856c097..48e69ee 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -487,9 +487,9 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -585,23 +585,13 @@
 		.controller_data = &ad9960_spi_chip_info,
 	},
 #endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc_dummy",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+		.modalias = "mmc_spi",
+		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index 83606fc..7fe480e 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -256,9 +256,9 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -366,23 +366,13 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc_dummy",
+		.modalias = "mmc_spi",
 		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf527/include/mach/anomaly.h b/arch/blackfin/mach-bf527/include/mach/anomaly.h
index 035e8d8..df6808d 100644
--- a/arch/blackfin/mach-bf527/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf527/include/mach/anomaly.h
@@ -2,7 +2,7 @@
  * File: include/asm-blackfin/mach-bf527/anomaly.h
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
- * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2004-2009 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
@@ -167,12 +167,16 @@
 #define ANOMALY_05000263 (0)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000273 (0)
+#define ANOMALY_05000278 (0)
 #define ANOMALY_05000285 (0)
+#define ANOMALY_05000305 (0)
 #define ANOMALY_05000307 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000312 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000363 (0)
 #define ANOMALY_05000412 (0)
+#define ANOMALY_05000447 (0)
+#define ANOMALY_05000448 (0)
 
 #endif
diff --git a/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h
index 75722d6..e8c41fd 100644
--- a/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h
+++ b/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h
@@ -144,7 +144,7 @@
 	 CH_UART0_TX,
 	 CH_UART0_RX,
 #endif
-#ifdef CONFIG_BFIN_UART0_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	 CONFIG_UART0_CTS_PIN,
 	 CONFIG_UART0_RTS_PIN,
 #endif
@@ -158,7 +158,7 @@
 	 CH_UART1_TX,
 	 CH_UART1_RX,
 #endif
-#ifdef CONFIG_BFIN_UART1_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	 CONFIG_UART1_CTS_PIN,
 	 CONFIG_UART1_RTS_PIN,
 #endif
diff --git a/arch/blackfin/mach-bf533/boards/Kconfig b/arch/blackfin/mach-bf533/boards/Kconfig
index 308c98d..8d8b3e7 100644
--- a/arch/blackfin/mach-bf533/boards/Kconfig
+++ b/arch/blackfin/mach-bf533/boards/Kconfig
@@ -38,9 +38,4 @@
 	help
 	  Core support for IP04/IP04 open hardware IP-PBX.
 
-config GENERIC_BF533_BOARD
-	bool "Generic"
-	help
-	  Generic or Custom board support.
-
 endchoice
diff --git a/arch/blackfin/mach-bf533/boards/Makefile b/arch/blackfin/mach-bf533/boards/Makefile
index 9afbe72..ff1e832 100644
--- a/arch/blackfin/mach-bf533/boards/Makefile
+++ b/arch/blackfin/mach-bf533/boards/Makefile
@@ -2,7 +2,6 @@
 # arch/blackfin/mach-bf533/boards/Makefile
 #
 
-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
diff --git a/arch/blackfin/mach-bf533/boards/blackstamp.c b/arch/blackfin/mach-bf533/boards/blackstamp.c
index 015c18f..0765872 100644
--- a/arch/blackfin/mach-bf533/boards/blackstamp.c
+++ b/arch/blackfin/mach-bf533/boards/blackstamp.c
@@ -101,9 +101,9 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -129,23 +129,13 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc_dummy",
+		.modalias = "mmc_spi",
 		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index e7061c7..e897487 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -96,9 +96,9 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -138,23 +138,13 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc_dummy",
+		.modalias = "mmc_spi",
 		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c
deleted file mode 100644
index 986eeec..0000000
--- a/arch/blackfin/mach-bf533/boards/generic_board.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * File:         arch/blackfin/mach-bf533/generic_board.c
- * Based on:     arch/blackfin/mach-bf533/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
- *
- * Created:      2005
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               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/device.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-
-/*
- * Name the Board for the /proc/cpuinfo
- */
-const char bfin_board_name[] = "UNKNOWN BOARD";
-
-#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
-static struct platform_device rtc_device = {
-	.name = "rtc-bfin",
-	.id   = -1,
-};
-#endif
-
-/*
- *  Driver needs to know address, irq and flag pin.
- */
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-static struct resource smc91x_resources[] = {
-	{
-		.start = 0x20300300,
-		.end = 0x20300300 + 16,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = IRQ_PROG_INTB,
-		.end = IRQ_PROG_INTB,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	}, {
-		.start = IRQ_PF7,
-		.end = IRQ_PF7,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},
-};
-
-static struct platform_device smc91x_device = {
-	.name = "smc91x",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(smc91x_resources),
-	.resource = smc91x_resources,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-#ifdef CONFIG_BFIN_SIR0
-static struct resource bfin_sir0_resources[] = {
-	{
-		.start = 0xFFC00400,
-		.end = 0xFFC004FF,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.start = CH_UART0_RX,
-		.end = CH_UART0_RX+1,
-		.flags = IORESOURCE_DMA,
-	},
-};
-
-static struct platform_device bfin_sir0_device = {
-	.name = "bfin_sir",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(bfin_sir0_resources),
-	.resource = bfin_sir0_resources,
-};
-#endif
-#endif
-
-static struct platform_device *generic_board_devices[] __initdata = {
-#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
-	&rtc_device,
-#endif
-
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-	&smc91x_device,
-#endif
-
-#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-#ifdef CONFIG_BFIN_SIR0
-	&bfin_sir0_device,
-#endif
-#endif
-};
-
-static int __init generic_board_init(void)
-{
-	printk(KERN_INFO "%s(): registering device resources\n", __func__);
-	return platform_add_devices(generic_board_devices, ARRAY_SIZE(generic_board_devices));
-}
-
-arch_initcall(generic_board_init);
diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
index e30b1b7..f19b6337 100644
--- a/arch/blackfin/mach-bf533/boards/ip0x.c
+++ b/arch/blackfin/mach-bf533/boards/ip0x.c
@@ -127,8 +127,8 @@
 #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 = {
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 /*
  * CPOL (Clock Polarity)
  *  0 - Active high SCK
@@ -152,14 +152,13 @@
 /* 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)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc",
+		.modalias = "mmc_spi",
 		.max_speed_hz = 2,
 		.bus_num = 1,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 	},
 #endif
 };
diff --git a/arch/blackfin/mach-bf533/include/mach/anomaly.h b/arch/blackfin/mach-bf533/include/mach/anomaly.h
index 0d3a034..1cf893e 100644
--- a/arch/blackfin/mach-bf533/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf533/include/mach/anomaly.h
@@ -2,7 +2,7 @@
  * File: include/asm-blackfin/mach-bf533/anomaly.h
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
- * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2004-2009 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
@@ -160,7 +160,7 @@
 #define ANOMALY_05000301 (__SILICON_REVISION__ < 6)
 /* SSYNCs After Writes To DMA MMR Registers May Not Be Handled Correctly */
 #define ANOMALY_05000302 (__SILICON_REVISION__ < 5)
-/* New Feature: Additional Hysteresis on SPORT Input Pins (Not Available On Older Silicon) */
+/* SPORT_HYS Bit in PLL_CTL Register Is Not Functional */
 #define ANOMALY_05000305 (__SILICON_REVISION__ < 5)
 /* New Feature: Additional PPI Frame Sync Sampling Options (Not Available On Older Silicon) */
 #define ANOMALY_05000306 (__SILICON_REVISION__ < 5)
@@ -278,9 +278,12 @@
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (1)
+#define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
+#define ANOMALY_05000447 (0)
+#define ANOMALY_05000448 (0)
 
 #endif
diff --git a/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h
index f3d9e49..5f517f5 100644
--- a/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h
+++ b/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h
@@ -134,7 +134,7 @@
 	CH_UART_TX,
 	CH_UART_RX,
 #endif
-#ifdef CONFIG_BFIN_UART0_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	CONFIG_UART0_CTS_PIN,
 	CONFIG_UART0_RTS_PIN,
 #endif
diff --git a/arch/blackfin/mach-bf537/boards/Kconfig b/arch/blackfin/mach-bf537/boards/Kconfig
index 42a57b0..77c59da 100644
--- a/arch/blackfin/mach-bf537/boards/Kconfig
+++ b/arch/blackfin/mach-bf537/boards/Kconfig
@@ -33,9 +33,4 @@
 	help
 	  Board supply package for CSP Minotaur
 
-config GENERIC_BF537_BOARD
-	bool "Generic"
-	help
-	  Generic or Custom board support.
-
 endchoice
diff --git a/arch/blackfin/mach-bf537/boards/Makefile b/arch/blackfin/mach-bf537/boards/Makefile
index 7168cc1..68b98a7a 100644
--- a/arch/blackfin/mach-bf537/boards/Makefile
+++ b/arch/blackfin/mach-bf537/boards/Makefile
@@ -2,7 +2,6 @@
 # arch/blackfin/mach-bf537/boards/Makefile
 #
 
-obj-$(CONFIG_GENERIC_BF537_BOARD)      += generic_board.o
 obj-$(CONFIG_BFIN537_STAMP)            += stamp.o
 obj-$(CONFIG_BFIN537_BLUETECHNIX_CM)   += cm_bf537.o
 obj-$(CONFIG_BFIN537_BLUETECHNIX_TCM)  += tcm_bf537.o
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
index 9cd8fb2..41c75b9 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
@@ -108,9 +108,9 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -160,23 +160,13 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc_dummy",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+		.modalias = "mmc_spi",
+		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 7,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 1,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
deleted file mode 100644
index da710fd..0000000
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- * File:         arch/blackfin/mach-bf537/boards/generic_board.c
- * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
- * Author:       Aidan Williams <aidan@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/etherdevice.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 <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/usb/sl811.h>
-#include <asm/dma.h>
-#include <asm/bfin5xx_spi.h>
-#include <asm/reboot.h>
-#include <asm/portmux.h>
-#include <linux/spi/ad7877.h>
-
-/*
- * Name the Board for the /proc/cpuinfo
- */
-const char bfin_board_name[] = "UNKNOWN BOARD";
-
-/*
- *  Driver needs to know address, irq and flag pin.
- */
-
-#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
-#include <linux/usb/isp1760.h>
-static struct resource bfin_isp1760_resources[] = {
-	[0] = {
-		.start  = 0x203C0000,
-		.end    = 0x203C0000 + 0x000fffff,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = IRQ_PF7,
-		.end    = IRQ_PF7,
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct isp1760_platform_data isp1760_priv = {
-	.is_isp1761 = 0,
-	.port1_disable = 0,
-	.bus_width_16 = 1,
-	.port1_otg = 0,
-	.analog_oc = 0,
-	.dack_polarity_high = 0,
-	.dreq_polarity_high = 0,
-};
-
-static struct platform_device bfin_isp1760_device = {
-	.name           = "isp1760-hcd",
-	.id             = 0,
-	.dev = {
-		.platform_data = &isp1760_priv,
-	},
-	.num_resources  = ARRAY_SIZE(bfin_isp1760_resources),
-	.resource       = bfin_isp1760_resources,
-};
-#endif
-
-#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
-static struct resource bfin_pcmcia_cf_resources[] = {
-	{
-		.start = 0x20310000, /* IO PORT */
-		.end = 0x20312000,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = 0x20311000, /* Attribute Memory */
-		.end = 0x20311FFF,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = IRQ_PF4,
-		.end = IRQ_PF4,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	}, {
-		.start = 6, /* Card Detect PF6 */
-		.end = 6,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device bfin_pcmcia_cf_device = {
-	.name = "bfin_cf_pcmcia",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(bfin_pcmcia_cf_resources),
-	.resource = bfin_pcmcia_cf_resources,
-};
-#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_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-static struct resource smc91x_resources[] = {
-	{
-		.name = "smc91x-regs",
-		.start = 0x20300300,
-		.end = 0x20300300 + 16,
-		.flags = IORESOURCE_MEM,
-	}, {
-
-		.start = IRQ_PF7,
-		.end = IRQ_PF7,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},
-};
-static struct platform_device smc91x_device = {
-	.name = "smc91x",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(smc91x_resources),
-	.resource = smc91x_resources,
-};
-#endif
-
-#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
-static struct resource dm9000_resources[] = {
-	[0] = {
-		.start	= 0x203FB800,
-		.end	= 0x203FB800 + 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 0x203FB800 + 4,
-		.end	= 0x203FB800 + 5,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= IRQ_PF9,
-		.end	= IRQ_PF9,
-		.flags	= (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
-	},
-};
-
-static struct platform_device dm9000_device = {
-	.name		= "dm9000",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(dm9000_resources),
-	.resource	= dm9000_resources,
-};
-#endif
-
-#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
-static struct resource sl811_hcd_resources[] = {
-	{
-		.start = 0x20340000,
-		.end = 0x20340000,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = 0x20340004,
-		.end = 0x20340004,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = CONFIG_USB_SL811_BFIN_IRQ,
-		.end = CONFIG_USB_SL811_BFIN_IRQ,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},
-};
-
-#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
-void sl811_port_power(struct device *dev, int is_on)
-{
-	gpio_request(CONFIG_USB_SL811_BFIN_GPIO_VBUS, "usb:SL811_VBUS");
-	gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS, is_on);
-
-}
-#endif
-
-static struct sl811_platform_data sl811_priv = {
-	.potpg = 10,
-	.power = 250,       /* == 500mA */
-#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
-	.port_power = &sl811_port_power,
-#endif
-};
-
-static struct platform_device sl811_hcd_device = {
-	.name = "sl811-hcd",
-	.id = 0,
-	.dev = {
-		.platform_data = &sl811_priv,
-	},
-	.num_resources = ARRAY_SIZE(sl811_hcd_resources),
-	.resource = sl811_hcd_resources,
-};
-#endif
-
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-static struct resource isp1362_hcd_resources[] = {
-	{
-		.start = 0x20360000,
-		.end = 0x20360000,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = 0x20360004,
-		.end = 0x20360004,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
-		.end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},
-};
-
-static struct isp1362_platform_data isp1362_priv = {
-	.sel15Kres = 1,
-	.clknotstop = 0,
-	.oc_enable = 0,
-	.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
-
-#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
-static struct platform_device bfin_mii_bus = {
-	.name = "bfin_mii_bus",
-};
-
-static struct platform_device bfin_mac_device = {
-	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
-};
-#endif
-
-#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
-static struct resource net2272_bfin_resources[] = {
-	{
-		.start = 0x20300000,
-		.end = 0x20300000 + 0x100,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = IRQ_PF7,
-		.end = IRQ_PF7,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},
-};
-
-static struct platform_device net2272_bfin_device = {
-	.name = "net2272",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(net2272_bfin_resources),
-	.resource = net2272_bfin_resources,
-};
-#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)
-static struct mtd_partition bfin_spi_flash_partitions[] = {
-	{
-		.name = "bootloader(spi)",
-		.size = 0x00020000,
-		.offset = 0,
-		.mask_flags = MTD_CAP_ROM
-	}, {
-		.name = "linux kernel(spi)",
-		.size = 0xe0000,
-		.offset = 0x20000
-	}, {
-		.name = "file system(spi)",
-		.size = 0x700000,
-		.offset = 0x00100000,
-	}
-};
-
-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 = "m25p64",
-};
-
-/* SPI flash chip (m25p64) */
-static struct bfin5xx_spi_chip spi_flash_chip_info = {
-	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_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_AD9960) || defined(CONFIG_AD9960_MODULE)
-static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_PBX)
-static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
-	.ctl_reg	= 0x4, /* send zero */
-	.enable_dma	= 0,
-	.bits_per_word	= 8,
-	.cs_change_per_word = 1,
-};
-#endif
-
-#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
-static const struct ad7877_platform_data bfin_ad7877_ts_info = {
-	.model			= 7877,
-	.vref_delay_usecs	= 50,	/* internal, no capacitor */
-	.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
-
-static struct spi_board_info bfin_spi_board_info[] __initdata = {
-#if defined(CONFIG_MTD_M25P80) \
-	|| defined(CONFIG_MTD_M25P80_MODULE)
-	{
-		/* the modalias must be the same as spi device driver name */
-		.modalias = "m25p80", /* Name of spi_driver for this device */
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
-		.platform_data = &bfin_spi_flash_data,
-		.controller_data = &spi_flash_chip_info,
-		.mode = SPI_MODE_3,
-	},
-#endif
-
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
-#if defined(CONFIG_SND_BLACKFIN_AD1836) \
-	|| defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
-	{
-		.modalias = "ad1836-spi",
-		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
-		.controller_data = &ad1836_spi_chip_info,
-	},
-#endif
-#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
-	{
-		.modalias = "ad9960-spi",
-		.max_speed_hz = 10000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = 1,
-		.controller_data = &ad9960_spi_chip_info,
-	},
-#endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-	{
-		.modalias = "spi_mmc_dummy",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-#endif
-#if defined(CONFIG_PBX)
-	{
-		.modalias = "fxs-spi",
-		.max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = 8 - CONFIG_J11_JUMPER,
-		.controller_data = &spi_si3xxx_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "fxo-spi",
-		.max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = 8 - CONFIG_J19_JUMPER,
-		.controller_data = &spi_si3xxx_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_PF6,
-		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num	= 0,
-		.chip_select  = 1,
-		.controller_data = &spi_ad7877_chip_info,
-	},
-#endif
-};
-
-/* SPI controller data */
-static struct bfin5xx_spi_master bfin_spi0_info = {
-	.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},
-};
-
-/* SPI (0) */
-static struct resource bfin_spi0_resource[] = {
-	[0] = {
-		.start = SPI0_REGBASE,
-		.end   = SPI0_REGBASE + 0xFF,
-		.flags = IORESOURCE_MEM,
-		},
-	[1] = {
-		.start = CH_SPI,
-		.end   = CH_SPI,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device bfin_spi0_device = {
-	.name = "bfin-spi",
-	.id = 0, /* Bus number */
-	.num_resources = ARRAY_SIZE(bfin_spi0_resource),
-	.resource = bfin_spi0_resource,
-	.dev = {
-		.platform_data = &bfin_spi0_info, /* Passed to driver */
-	},
-};
-#endif  /* spi master and devices */
-
-#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
-static struct platform_device bfin_fb_device = {
-	.name = "bf537-lq035",
-};
-#endif
-
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-static struct platform_device bfin_fb_adv7393_device = {
-	.name = "bfin-adv7393",
-};
-#endif
-
-#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
-static struct resource bfin_uart_resources[] = {
-	{
-		.start = 0xFFC00400,
-		.end = 0xFFC004FF,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = 0xFFC02000,
-		.end = 0xFFC020FF,
-		.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)
-#ifdef CONFIG_BFIN_SIR0
-static struct resource bfin_sir0_resources[] = {
-	{
-		.start = 0xFFC00400,
-		.end = 0xFFC004FF,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.start = CH_UART0_RX,
-		.end = CH_UART0_RX+1,
-		.flags = IORESOURCE_DMA,
-	},
-};
-
-static struct platform_device bfin_sir0_device = {
-	.name = "bfin_sir",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(bfin_sir0_resources),
-	.resource = bfin_sir0_resources,
-};
-#endif
-#ifdef CONFIG_BFIN_SIR1
-static struct resource bfin_sir1_resources[] = {
-	{
-		.start = 0xFFC02000,
-		.end = 0xFFC020FF,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.start = CH_UART1_RX,
-		.end = CH_UART1_RX+1,
-		.flags = IORESOURCE_DMA,
-	},
-};
-
-static struct platform_device bfin_sir1_device = {
-	.name = "bfin_sir",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(bfin_sir1_resources),
-	.resource = bfin_sir1_resources,
-};
-#endif
-#endif
-
-#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
-static struct resource bfin_twi0_resource[] = {
-	[0] = {
-		.start = TWI0_REGBASE,
-		.end   = TWI0_REGBASE + 0xFF,
-		.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",
-	.id = 0,
-};
-
-static struct platform_device bfin_sport1_uart_device = {
-	.name = "bfin-sport-uart",
-	.id = 1,
-};
-#endif
-
-static struct platform_device *stamp_devices[] __initdata = {
-#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
-	&bfin_pcmcia_cf_device,
-#endif
-
-#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
-	&rtc_device,
-#endif
-
-#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
-	&sl811_hcd_device,
-#endif
-
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-	&isp1362_hcd_device,
-#endif
-
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-	&smc91x_device,
-#endif
-
-#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
-	&dm9000_device,
-#endif
-
-#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
-	&bfin_mii_bus,
-	&bfin_mac_device,
-#endif
-
-#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
-	&net2272_bfin_device,
-#endif
-
-#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
-	&bfin_isp1760_device,
-#endif
-
-#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
-	&bfin_spi0_device,
-#endif
-
-#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
-	&bfin_fb_device,
-#endif
-
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-	&bfin_fb_adv7393_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)
-#ifdef CONFIG_BFIN_SIR0
-	&bfin_sir0_device,
-#endif
-#ifdef CONFIG_BFIN_SIR1
-	&bfin_sir1_device,
-#endif
-#endif
-
-#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
-	&i2c_bfin_twi_device,
-#endif
-
-#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
-	&bfin_sport0_uart_device,
-	&bfin_sport1_uart_device,
-#endif
-};
-
-static int __init generic_init(void)
-{
-	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,
-				ARRAY_SIZE(bfin_spi_board_info));
-#endif
-
-	return 0;
-}
-
-arch_initcall(generic_init);
-
-void native_machine_restart(char *cmd)
-{
-	/* workaround reboot hang when booting from SPI */
-	if ((bfin_read_SYSCR() & 0x7) == 0x3)
-		bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
-}
-
-#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
-void bfin_get_ether_addr(char *addr)
-{
-	random_ether_addr(addr);
-	printk(KERN_WARNING "%s:%s: Setting Ethernet MAC to a random one\n", __FILE__, __func__);
-}
-EXPORT_SYMBOL(bfin_get_ether_addr);
-#endif
diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
index db7d3a3..3c15981 100644
--- a/arch/blackfin/mach-bf537/boards/minotaur.c
+++ b/arch/blackfin/mach-bf537/boards/minotaur.c
@@ -134,9 +134,9 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -156,23 +156,13 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc_dummy",
+		.modalias = "mmc_spi",
 		.max_speed_hz = 5000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 5000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index 590eb3a..4e1de1e 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -289,9 +289,9 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -364,23 +364,13 @@
 		.controller_data = &ad9960_spi_chip_info,
 	},
 #endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc_dummy",
+		.modalias = "mmc_spi",
 		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 7,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index 3f4f203..53ad10f 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -108,9 +108,9 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -160,23 +160,13 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc_dummy",
+		.modalias = "mmc_spi",
 		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 7,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias = "spi_mmc",
-		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf537/include/mach/anomaly.h b/arch/blackfin/mach-bf537/include/mach/anomaly.h
index 9cb3912..1bfd80c 100644
--- a/arch/blackfin/mach-bf537/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf537/include/mach/anomaly.h
@@ -2,7 +2,7 @@
  * File: include/asm-blackfin/mach-bf537/anomaly.h
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
- * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2004-2009 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
@@ -110,7 +110,7 @@
 #define ANOMALY_05000301 (1)
 /* SSYNCs After Writes To CAN/DMA MMR Registers Are Not Always Handled Correctly */
 #define ANOMALY_05000304 (__SILICON_REVISION__ < 3)
-/* New Feature: Additional Hysteresis on SPORT Input Pins (Not Available On Older Silicon) */
+/* SPORT_HYS Bit in PLL_CTL Register Is Not Functional */
 #define ANOMALY_05000305 (__SILICON_REVISION__ < 3)
 /* SCKELOW Bit Does Not Maintain State Through Hibernate */
 #define ANOMALY_05000307 (__SILICON_REVISION__ < 3)
@@ -168,9 +168,12 @@
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
+#define ANOMALY_05000447 (0)
+#define ANOMALY_05000448 (0)
 
 #endif
diff --git a/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h
index b3f87e1..9e34700 100644
--- a/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h
+++ b/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h
@@ -144,7 +144,7 @@
 	CH_UART0_TX,
 	CH_UART0_RX,
 #endif
-#ifdef CONFIG_BFIN_UART0_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	CONFIG_UART0_CTS_PIN,
 	CONFIG_UART0_RTS_PIN,
 #endif
@@ -158,7 +158,7 @@
 	CH_UART1_TX,
 	CH_UART1_RX,
 #endif
-#ifdef CONFIG_BFIN_UART1_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	CONFIG_UART1_CTS_PIN,
 	CONFIG_UART1_RTS_PIN,
 #endif
diff --git a/arch/blackfin/mach-bf538/include/mach/anomaly.h b/arch/blackfin/mach-bf538/include/mach/anomaly.h
index e130b4f..3a56998 100644
--- a/arch/blackfin/mach-bf538/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf538/include/mach/anomaly.h
@@ -2,7 +2,7 @@
  * File: include/asm-blackfin/mach-bf538/anomaly.h
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
- * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2004-2009 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
@@ -120,13 +120,17 @@
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000230 (0)
 #define ANOMALY_05000263 (0)
+#define ANOMALY_05000305 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
+#define ANOMALY_05000447 (0)
+#define ANOMALY_05000448 (0)
 
 #endif
diff --git a/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
index 40503b6..3c2811e 100644
--- a/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
+++ b/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
@@ -144,7 +144,7 @@
 	CH_UART0_TX,
 	CH_UART0_RX,
 #endif
-#ifdef CONFIG_BFIN_UART0_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	CONFIG_UART0_CTS_PIN,
 	CONFIG_UART0_RTS_PIN,
 #endif
@@ -158,7 +158,7 @@
 	CH_UART1_TX,
 	CH_UART1_RX,
 #endif
-#ifdef CONFIG_BFIN_UART1_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	CONFIG_UART1_CTS_PIN,
 	CONFIG_UART1_RTS_PIN,
 #endif
diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h
index 23d03c5..882e40c 100644
--- a/arch/blackfin/mach-bf548/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h
@@ -2,12 +2,12 @@
  * File: include/asm-blackfin/mach-bf548/anomaly.h
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
- * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2004-2009 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
 /* This file shoule be up to date with:
- *  - Revision G, 08/07/2008; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List
+ *  - Revision H, 01/16/2009; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
@@ -91,8 +91,6 @@
 #define ANOMALY_05000371 (__SILICON_REVISION__ < 2)
 /* USB DP/DM Data Pins May Lose State When Entering Hibernate */
 #define ANOMALY_05000372 (__SILICON_REVISION__ < 1)
-/* Mobile DDR Operation Not Functional */
-#define ANOMALY_05000377 (1)
 /* Security/Authentication Speedpath Causes Authentication To Fail To Initiate */
 #define ANOMALY_05000378 (__SILICON_REVISION__ < 2)
 /* 16-Bit NAND FLASH Boot Mode Is Not Functional */
@@ -157,8 +155,22 @@
 #define ANOMALY_05000429 (__SILICON_REVISION__ < 2)
 /* Software System Reset Corrupts PLL_LOCKCNT Register */
 #define ANOMALY_05000430 (__SILICON_REVISION__ >= 2)
+/* Incorrect Use of Stack in Lockbox Firmware During Authentication */
+#define ANOMALY_05000431 (__SILICON_REVISION__ < 3)
+/* OTP Write Accesses Not Supported */
+#define ANOMALY_05000442 (__SILICON_REVISION__ < 1)
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
 #define ANOMALY_05000443 (1)
+/* CDMAPRIO and L2DMAPRIO Bits in the SYSCR Register Are Not Functional */
+#define ANOMALY_05000446 (1)
+/* UART IrDA Receiver Fails on Extended Bit Pulses */
+#define ANOMALY_05000447 (1)
+/* DDR Clock Duty Cycle Spec Violation (tCH, tCL) */
+#define ANOMALY_05000448 (__SILICON_REVISION__ == 1)
+/* Reduced Timing Margins on DDR Output Setup and Hold (tDS and tDH) */
+#define ANOMALY_05000449 (__SILICON_REVISION__ == 1)
+/* USB DMA Mode 1 Short Packet Data Corruption */
+#define ANOMALY_05000450 (1
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000125 (0)
@@ -171,6 +183,8 @@
 #define ANOMALY_05000263 (0)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000273 (0)
+#define ANOMALY_05000278 (0)
+#define ANOMALY_05000305 (0)
 #define ANOMALY_05000307 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
diff --git a/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h
index e4cf35e..c05e79c 100644
--- a/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h
+++ b/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h
@@ -63,7 +63,7 @@
 #define UART_ENABLE_INTS(x, v) UART_SET_IER(x, v)
 #define UART_DISABLE_INTS(x) UART_CLEAR_IER(x, 0xF)
 
-#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
+#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART2_CTSRTS)
 # define CONFIG_SERIAL_BFIN_CTSRTS
 
 # ifndef CONFIG_UART0_CTS_PIN
@@ -74,12 +74,12 @@
 #  define CONFIG_UART0_RTS_PIN -1
 # endif
 
-# ifndef CONFIG_UART1_CTS_PIN
-#  define CONFIG_UART1_CTS_PIN -1
+# ifndef CONFIG_UART2_CTS_PIN
+#  define CONFIG_UART2_CTS_PIN -1
 # endif
 
-# ifndef CONFIG_UART1_RTS_PIN
-#  define CONFIG_UART1_RTS_PIN -1
+# ifndef CONFIG_UART2_RTS_PIN
+#  define CONFIG_UART2_RTS_PIN -1
 # endif
 #endif
 
@@ -130,7 +130,7 @@
 	CH_UART0_TX,
 	CH_UART0_RX,
 #endif
-#ifdef CONFIG_BFIN_UART0_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	CONFIG_UART0_CTS_PIN,
 	CONFIG_UART0_RTS_PIN,
 #endif
@@ -144,6 +144,10 @@
 	CH_UART1_TX,
 	CH_UART1_RX,
 #endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+	0,
+	0,
+#endif
 	},
 #endif
 #ifdef CONFIG_SERIAL_BFIN_UART2
@@ -154,7 +158,7 @@
 	CH_UART2_TX,
 	CH_UART2_RX,
 #endif
-#ifdef CONFIG_BFIN_UART2_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	CONFIG_UART2_CTS_PIN,
 	CONFIG_UART2_RTS_PIN,
 #endif
@@ -168,6 +172,10 @@
 	CH_UART3_TX,
 	CH_UART3_RX,
 #endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+	0,
+	0,
+#endif
 	},
 #endif
 };
diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h
index 60299a7..f194625 100644
--- a/arch/blackfin/mach-bf548/include/mach/irq.h
+++ b/arch/blackfin/mach-bf548/include/mach/irq.h
@@ -123,8 +123,8 @@
 #define IRQ_MXVR_ERROR		BFIN_IRQ(51)	/* MXVR Status (Error) Interrupt */
 #define IRQ_MXVR_MSG		BFIN_IRQ(52)	/* MXVR Message Interrupt */
 #define IRQ_MXVR_PKT		BFIN_IRQ(53)	/* MXVR Packet Interrupt */
-#define IRQ_EPP1_ERROR		BFIN_IRQ(54)	/* EPPI1 Error Interrupt */
-#define IRQ_EPP2_ERROR		BFIN_IRQ(55)	/* EPPI2 Error Interrupt */
+#define IRQ_EPPI1_ERROR		BFIN_IRQ(54)	/* EPPI1 Error Interrupt */
+#define IRQ_EPPI2_ERROR		BFIN_IRQ(55)	/* EPPI2 Error Interrupt */
 #define IRQ_UART3_ERROR		BFIN_IRQ(56)	/* UART3 Status (Error) Interrupt */
 #define IRQ_HOST_ERROR		BFIN_IRQ(57)	/* HOST Status (Error) Interrupt */
 #define IRQ_PIXC_ERROR		BFIN_IRQ(59)	/* PIXC Status (Error) Interrupt */
@@ -361,8 +361,8 @@
 #define IRQ_UART2_ERR 		IRQ_UART2_ERROR
 #define IRQ_CAN0_ERR  		IRQ_CAN0_ERROR
 #define IRQ_MXVR_ERR  		IRQ_MXVR_ERROR
-#define IRQ_EPP1_ERR  		IRQ_EPP1_ERROR
-#define IRQ_EPP2_ERR  		IRQ_EPP2_ERROR
+#define IRQ_EPPI1_ERR  		IRQ_EPPI1_ERROR
+#define IRQ_EPPI2_ERR  		IRQ_EPPI2_ERROR
 #define IRQ_UART3_ERR 		IRQ_UART3_ERROR
 #define IRQ_HOST_ERR  		IRQ_HOST_ERROR
 #define IRQ_PIXC_ERR  		IRQ_PIXC_ERROR
diff --git a/arch/blackfin/mach-bf561/boards/Kconfig b/arch/blackfin/mach-bf561/boards/Kconfig
index e41a67b..e4bc6d7 100644
--- a/arch/blackfin/mach-bf561/boards/Kconfig
+++ b/arch/blackfin/mach-bf561/boards/Kconfig
@@ -19,9 +19,4 @@
 	help
 	  CM-BF561 support for EVAL- and DEV-Board.
 
-config GENERIC_BF561_BOARD
-	bool "Generic"
-	help
-	  Generic or Custom board support.
-
 endchoice
diff --git a/arch/blackfin/mach-bf561/boards/Makefile b/arch/blackfin/mach-bf561/boards/Makefile
index 04add01..3a15255 100644
--- a/arch/blackfin/mach-bf561/boards/Makefile
+++ b/arch/blackfin/mach-bf561/boards/Makefile
@@ -2,7 +2,6 @@
 # arch/blackfin/mach-bf561/boards/Makefile
 #
 
-obj-$(CONFIG_GENERIC_BF561_BOARD)      += generic_board.o
 obj-$(CONFIG_BFIN561_BLUETECHNIX_CM)   += cm_bf561.o
 obj-$(CONFIG_BFIN561_EZKIT)            += ezkit.o
 obj-$(CONFIG_BFIN561_TEPLA)            += tepla.o
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index 6880d1e..f623c6b 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -105,9 +105,9 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
-	.enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+	.enable_dma = 0,
 	.bits_per_word = 8,
 };
 #endif
@@ -155,14 +155,13 @@
 		.controller_data = &ad9960_spi_chip_info,
 	},
 #endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
-		.modalias = "spi_mmc",
+		.modalias = "mmc_spi",
 		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
-		.platform_data = NULL,
-		.controller_data = &spi_mmc_chip_info,
+		.chip_select = 5,
+		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c
deleted file mode 100644
index 0ba366a..0000000
--- a/arch/blackfin/mach-bf561/boards/generic_board.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * File:         arch/blackfin/mach-bf561/generic_board.c
- * Based on:     arch/blackfin/mach-bf533/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
- *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               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/device.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-
-const char bfin_board_name[] = "UNKNOWN BOARD";
-
-/*
- *  Driver needs to know address, irq and flag pin.
- */
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-static struct resource smc91x_resources[] = {
-	{
-		.start = 0x2C010300,
-		.end = 0x2C010300 + 16,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = IRQ_PROG_INTB,
-		.end = IRQ_PROG_INTB,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	}, {
-		.start = IRQ_PF9,
-		.end = IRQ_PF9,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},
-};
-
-static struct platform_device smc91x_device = {
-	.name = "smc91x",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(smc91x_resources),
-	.resource = smc91x_resources,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-#ifdef CONFIG_BFIN_SIR0
-static struct resource bfin_sir0_resources[] = {
-	{
-		.start = 0xFFC00400,
-		.end = 0xFFC004FF,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.start = CH_UART0_RX,
-		.end = CH_UART0_RX+1,
-		.flags = IORESOURCE_DMA,
-	},
-};
-
-static struct platform_device bfin_sir0_device = {
-	.name = "bfin_sir",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(bfin_sir0_resources),
-	.resource = bfin_sir0_resources,
-};
-#endif
-#endif
-
-static struct platform_device *generic_board_devices[] __initdata = {
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-	&smc91x_device,
-#endif
-
-#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-#ifdef CONFIG_BFIN_SIR0
-	&bfin_sir0_device,
-#endif
-#endif
-};
-
-static int __init generic_board_init(void)
-{
-	printk(KERN_INFO "%s(): registering device resources\n", __func__);
-	return platform_add_devices(generic_board_devices,
-				    ARRAY_SIZE(generic_board_devices));
-}
-
-arch_initcall(generic_board_init);
diff --git a/arch/blackfin/mach-bf561/include/mach/anomaly.h b/arch/blackfin/mach-bf561/include/mach/anomaly.h
index 1a9e175..d0b0b35 100644
--- a/arch/blackfin/mach-bf561/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf561/include/mach/anomaly.h
@@ -2,7 +2,7 @@
  * File: include/asm-blackfin/mach-bf561/anomaly.h
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
- * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2004-2009 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
@@ -224,7 +224,7 @@
 #define ANOMALY_05000301 (1)
 /* SSYNCs After Writes To DMA MMR Registers May Not Be Handled Correctly */
 #define ANOMALY_05000302 (1)
-/* New Feature: Additional Hysteresis on SPORT Input Pins (Not Available On Older Silicon) */
+/* SPORT_HYS Bit in PLL_CTL Register Is Not Functional */
 #define ANOMALY_05000305 (__SILICON_REVISION__ < 5)
 /* SCKELOW Bit Does Not Maintain State Through Hibernate */
 #define ANOMALY_05000307 (__SILICON_REVISION__ < 5)
@@ -283,8 +283,11 @@
 #define ANOMALY_05000273 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000353 (1)
+#define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
+#define ANOMALY_05000447 (0)
+#define ANOMALY_05000448 (0)
 
 #endif
diff --git a/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h
index 043bfcf..ca8c5f6 100644
--- a/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h
+++ b/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h
@@ -134,7 +134,7 @@
 	CH_UART_TX,
 	CH_UART_RX,
 #endif
-#ifdef CONFIG_BFIN_UART0_CTSRTS
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	CONFIG_UART0_CTS_PIN,
 	CONFIG_UART0_RTS_PIN,
 #endif
diff --git a/arch/blackfin/mach-common/arch_checks.c b/arch/blackfin/mach-common/arch_checks.c
index 98133b9..80d39b2 100644
--- a/arch/blackfin/mach-common/arch_checks.c
+++ b/arch/blackfin/mach-common/arch_checks.c
@@ -62,3 +62,12 @@
 #if (CONFIG_BOOT_LOAD & 0x3)
 # error "The kernel load address must be 4 byte aligned"
 #endif
+
+/* The entire kernel must be able to make a 24bit pcrel call to start of L1 */
+#if ((0xffffffff - L1_CODE_START + 1) + CONFIG_BOOT_LOAD) > 0x1000000
+# error "The kernel load address is too high; keep it below 10meg for safety"
+#endif
+
+#if ANOMALY_05000448
+# error You are using a part with anomaly 05000448, this issue causes random memory read/write failures - that means random crashes.
+#endif
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S
index 3c98dac..aa0648c 100644
--- a/arch/blackfin/mach-common/cache.S
+++ b/arch/blackfin/mach-common/cache.S
@@ -66,11 +66,33 @@
 
 /* Invalidate all instruction cache lines assocoiated with this memory area */
 ENTRY(_blackfin_icache_flush_range)
+/*
+ * Walkaround to avoid loading wrong instruction after invalidating icache
+ * and following sequence is met.
+ *
+ * 1) One instruction address is cached in the instruction cache.
+ * 2) This instruction in SDRAM is changed.
+ * 3) IFLASH[P0] is executed only once in blackfin_icache_flush_range().
+ * 4) This instruction is executed again, but the old one is loaded.
+ */
+	P0 = R0;
+	IFLUSH[P0];
 	do_flush IFLUSH, , nop
 ENDPROC(_blackfin_icache_flush_range)
 
 /* Flush all cache lines assocoiated with this area of memory. */
 ENTRY(_blackfin_icache_dcache_flush_range)
+/*
+ * Walkaround to avoid loading wrong instruction after invalidating icache
+ * and following sequence is met.
+ *
+ * 1) One instruction address is cached in the instruction cache.
+ * 2) This instruction in SDRAM is changed.
+ * 3) IFLASH[P0] is executed only once in blackfin_icache_flush_range().
+ * 4) This instruction is executed again, but the old one is loaded.
+ */
+	P0 = R0;
+	IFLUSH[P0];
 	do_flush FLUSH, IFLUSH
 ENDPROC(_blackfin_icache_dcache_flush_range)
 
diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c
index 9dddb6f..3539365 100644
--- a/arch/blackfin/mach-common/clocks-init.c
+++ b/arch/blackfin/mach-common/clocks-init.c
@@ -17,7 +17,7 @@
 #define SDGCTL_WIDTH (1 << 31)	/* SDRAM external data path width */
 #define PLL_CTL_VAL \
 	(((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \
-	 (PLL_BYPASS << 8) | (ANOMALY_05000265 ? 0x8000 : 0))
+	 (PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000))
 
 __attribute__((l1_text))
 static void do_sync(void)
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
index 4da50bc..8009a51 100644
--- a/arch/blackfin/mach-common/dpmc_modes.S
+++ b/arch/blackfin/mach-common/dpmc_modes.S
@@ -376,10 +376,22 @@
 #endif
 
 #ifdef PINT0_ASSIGN
+	PM_SYS_PUSH(PINT0_MASK_SET)
+	PM_SYS_PUSH(PINT1_MASK_SET)
+	PM_SYS_PUSH(PINT2_MASK_SET)
+	PM_SYS_PUSH(PINT3_MASK_SET)
 	PM_SYS_PUSH(PINT0_ASSIGN)
 	PM_SYS_PUSH(PINT1_ASSIGN)
 	PM_SYS_PUSH(PINT2_ASSIGN)
 	PM_SYS_PUSH(PINT3_ASSIGN)
+	PM_SYS_PUSH(PINT0_INVERT_SET)
+	PM_SYS_PUSH(PINT1_INVERT_SET)
+	PM_SYS_PUSH(PINT2_INVERT_SET)
+	PM_SYS_PUSH(PINT3_INVERT_SET)
+	PM_SYS_PUSH(PINT0_EDGE_SET)
+	PM_SYS_PUSH(PINT1_EDGE_SET)
+	PM_SYS_PUSH(PINT2_EDGE_SET)
+	PM_SYS_PUSH(PINT3_EDGE_SET)
 #endif
 
 	PM_SYS_PUSH(EBIU_AMBCTL0)
@@ -714,10 +726,22 @@
 	PM_SYS_POP(EBIU_AMBCTL0)
 
 #ifdef PINT0_ASSIGN
+	PM_SYS_POP(PINT3_EDGE_SET)
+	PM_SYS_POP(PINT2_EDGE_SET)
+	PM_SYS_POP(PINT1_EDGE_SET)
+	PM_SYS_POP(PINT0_EDGE_SET)
+	PM_SYS_POP(PINT3_INVERT_SET)
+	PM_SYS_POP(PINT2_INVERT_SET)
+	PM_SYS_POP(PINT1_INVERT_SET)
+	PM_SYS_POP(PINT0_INVERT_SET)
 	PM_SYS_POP(PINT3_ASSIGN)
 	PM_SYS_POP(PINT2_ASSIGN)
 	PM_SYS_POP(PINT1_ASSIGN)
 	PM_SYS_POP(PINT0_ASSIGN)
+	PM_SYS_POP(PINT3_MASK_SET)
+	PM_SYS_POP(PINT2_MASK_SET)
+	PM_SYS_POP(PINT1_MASK_SET)
+	PM_SYS_POP(PINT0_MASK_SET)
 #endif
 
 #ifdef SICA_IWR1
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 88de053..21e65a3 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -600,6 +600,19 @@
 	p2 = [p2];
 
 	[p2+(TASK_THREAD+THREAD_KSP)] = sp;
+#ifdef CONFIG_IPIPE
+	r0 = sp;
+	SP += -12;
+	call ___ipipe_syscall_root;
+	SP += 12;
+	cc = r0 == 1;
+	if cc jump .Lsyscall_really_exit;
+	cc = r0 == -1;
+	if cc jump .Lresume_userspace;
+	r3 = [sp + PT_R3];
+	r4 = [sp + PT_R4];
+	p0 = [sp + PT_ORIG_P0];
+#endif /* CONFIG_IPIPE */
 
 	/* Check the System Call */
 	r7 = __NR_syscall;
@@ -654,6 +667,17 @@
 	r7 =  r7 & r4;
 
 .Lsyscall_resched:
+#ifdef CONFIG_IPIPE
+	cc = BITTST(r7, TIF_IRQ_SYNC);
+	if !cc jump .Lsyscall_no_irqsync;
+	[--sp] = reti;
+	r0 = [sp++];
+	SP += -12;
+	call ___ipipe_sync_root;
+	SP += 12;
+	jump .Lresume_userspace_1;
+.Lsyscall_no_irqsync:
+#endif
 	cc = BITTST(r7, TIF_NEED_RESCHED);
 	if !cc jump .Lsyscall_sigpending;
 
@@ -685,6 +709,10 @@
 .Lsyscall_really_exit:
 	r5 = [sp + PT_RESERVED];
 	rets = r5;
+#ifdef CONFIG_IPIPE
+	[--sp] = reti;
+	r5 = [sp++];
+#endif /* CONFIG_IPIPE */
 	rts;
 ENDPROC(_system_call)
 
@@ -771,6 +799,15 @@
 ENDPROC(_resume)
 
 ENTRY(_ret_from_exception)
+#ifdef CONFIG_IPIPE
+	[--sp] = rets;
+	SP += -12;
+	call ___ipipe_check_root
+	SP += 12
+	rets = [sp++];
+	cc = r0 == 0;
+	if cc jump 4f;                /* not on behalf of Linux, get out */
+#endif /* CONFIG_IPIPE */
 	p2.l = lo(IPEND);
 	p2.h = hi(IPEND);
 
@@ -827,6 +864,28 @@
 	rts;
 ENDPROC(_ret_from_exception)
 
+#ifdef CONFIG_IPIPE
+
+_sync_root_irqs:
+	[--sp] = reti;		/* Reenable interrupts */
+	r0 = [sp++];
+	jump.l ___ipipe_sync_root
+
+_resume_kernel_from_int:
+	r0.l = _sync_root_irqs
+	r0.h = _sync_root_irqs
+	[--sp] = rets;
+	[--sp] = ( r7:4, p5:3 );
+	SP += -12;
+	call ___ipipe_call_irqtail
+	SP += 12;
+	( r7:4, p5:3 ) = [sp++];
+	rets = [sp++];
+	rts
+#else
+#define _resume_kernel_from_int	 2f
+#endif
+
 ENTRY(_return_from_int)
 	/* If someone else already raised IRQ 15, do nothing.  */
 	csync;
@@ -848,7 +907,7 @@
 	r1 = r0 - r1;
 	r2 = r0 & r1;
 	cc = r2 == 0;
-	if !cc jump 2f;
+	if !cc jump _resume_kernel_from_int;
 
 	/* Lower the interrupt level to 15.  */
 	p0.l = lo(EVT15);
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index 43c4eb9..0069c2d 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -235,6 +235,7 @@
 
 #ifdef CONFIG_IPIPE
 ENTRY(___ipipe_call_irqtail)
+	p0 = r0;
 	r0.l = 1f;
 	r0.h = 1f;
 	reti = r0;
@@ -242,9 +243,6 @@
 1:
 	[--sp] = rets;
 	[--sp] = ( r7:4, p5:3 );
-	p0.l = ___ipipe_irq_tail_hook;
-	p0.h = ___ipipe_irq_tail_hook;
-	p0 = [p0];
 	sp += -12;
 	call (p0);
 	sp += 12;
@@ -259,7 +257,7 @@
 	p0.h = hi(EVT14);
 	[p0] = r0;
 	csync;
-	r0 = 0x401f;
+	r0 = 0x401f (z);
 	sti r0;
 	raise 14;
 	[--sp] = reti;          /* IRQs on. */
@@ -277,11 +275,7 @@
 	p0.h = _bfin_irq_flags;
 	r0 = [p0];
 	sti r0;
-#if 0 /* FIXME: this actually raises scheduling latencies */
-	/* Reenable interrupts */
-	[--sp] = reti;
-	r0 = [sp++];
-#endif
 	rts;
 ENDPROC(___ipipe_call_irqtail)
+
 #endif /* CONFIG_IPIPE */
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 2024945..a7d7b2d 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -161,11 +161,15 @@
 
 static void bfin_internal_mask_irq(unsigned int irq)
 {
+	unsigned long flags;
+
 #ifdef CONFIG_BF53x
+	local_irq_save_hw(flags);
 	bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
 			     ~(1 << SIC_SYSIRQ(irq)));
 #else
 	unsigned mask_bank, mask_bit;
+	local_irq_save_hw(flags);
 	mask_bank = SIC_SYSIRQ(irq) / 32;
 	mask_bit = SIC_SYSIRQ(irq) % 32;
 	bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
@@ -175,15 +179,20 @@
 			     ~(1 << mask_bit));
 #endif
 #endif
+	local_irq_restore_hw(flags);
 }
 
 static void bfin_internal_unmask_irq(unsigned int irq)
 {
+	unsigned long flags;
+
 #ifdef CONFIG_BF53x
+	local_irq_save_hw(flags);
 	bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
 			     (1 << SIC_SYSIRQ(irq)));
 #else
 	unsigned mask_bank, mask_bit;
+	local_irq_save_hw(flags);
 	mask_bank = SIC_SYSIRQ(irq) / 32;
 	mask_bit = SIC_SYSIRQ(irq) % 32;
 	bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) |
@@ -193,6 +202,7 @@
 			     (1 << mask_bit));
 #endif
 #endif
+	local_irq_restore_hw(flags);
 }
 
 #ifdef CONFIG_PM
@@ -390,7 +400,7 @@
 static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
 {
 #ifdef CONFIG_IPIPE
-	_set_irq_handler(irq, handle_edge_irq);
+	_set_irq_handler(irq, handle_level_irq);
 #else
 	struct irq_desc *desc = irq_desc + irq;
 	/* May not call generic set_irq_handler() due to spinlock
@@ -1055,13 +1065,18 @@
 #endif
 		default:
 #ifdef CONFIG_IPIPE
-	/*
-	 * We want internal interrupt sources to be masked, because
-	 * ISRs may trigger interrupts recursively (e.g. DMA), but
-	 * interrupts are _not_ masked at CPU level. So let's handle
-	 * them as level interrupts.
-	 */
-			set_irq_handler(irq, handle_level_irq);
+			/*
+			 * We want internal interrupt sources to be
+			 * masked, because ISRs may trigger interrupts
+			 * recursively (e.g. DMA), but interrupts are
+			 * _not_ masked at CPU level. So let's handle
+			 * most of them as level interrupts, except
+			 * the timer interrupt which is special.
+			 */
+			if (irq == IRQ_SYSTMR || irq == IRQ_CORETMR)
+				set_irq_handler(irq, handle_simple_irq);
+			else
+				set_irq_handler(irq, handle_level_irq);
 #else /* !CONFIG_IPIPE */
 			set_irq_handler(irq, handle_simple_irq);
 #endif /* !CONFIG_IPIPE */
@@ -1123,9 +1138,8 @@
 
 #ifdef CONFIG_IPIPE
 	for (irq = 0; irq < NR_IRQS; irq++) {
-		struct irq_desc *desc = irq_desc + irq;
+		struct irq_desc *desc = irq_to_desc(irq);
 		desc->ic_prio = __ipipe_get_irq_priority(irq);
-		desc->thr_prio = __ipipe_get_irqthread_priority(irq);
 	}
 #endif /* CONFIG_IPIPE */
 
@@ -1208,76 +1222,21 @@
 	return IVG15;
 }
 
-int __ipipe_get_irqthread_priority(unsigned irq)
-{
-	int ient, prio;
-	int demux_irq;
-
-	/* The returned priority value is rescaled to [0..IVG13+1]
-	 * with 0 being the lowest effective priority level. */
-
-	if (irq <= IRQ_CORETMR)
-		return IVG13 - irq + 1;
-
-	/* GPIO IRQs are given the priority of the demux
-	 * interrupt. */
-	if (IS_GPIOIRQ(irq)) {
-#if defined(CONFIG_BF54x)
-		u32 bank = PINT_2_BANK(irq2pint_lut[irq - SYS_IRQS]);
-		demux_irq = (bank == 0 ? IRQ_PINT0 :
-				bank == 1 ? IRQ_PINT1 :
-				bank == 2 ? IRQ_PINT2 :
-				IRQ_PINT3);
-#elif defined(CONFIG_BF561)
-		demux_irq = (irq >= IRQ_PF32 ? IRQ_PROG2_INTA :
-				irq >= IRQ_PF16 ? IRQ_PROG1_INTA :
-				IRQ_PROG0_INTA);
-#elif defined(CONFIG_BF52x)
-		demux_irq = (irq >= IRQ_PH0 ? IRQ_PORTH_INTA :
-				irq >= IRQ_PG0 ? IRQ_PORTG_INTA :
-				IRQ_PORTF_INTA);
-#else
-		demux_irq = irq;
-#endif
-		return IVG13 - PRIO_GPIODEMUX(demux_irq) + 1;
-	}
-
-	/* The GPIO demux interrupt is given a lower priority
-	 * than the GPIO IRQs, so that its threaded handler
-	 * unmasks the interrupt line after the decoded IRQs
-	 * have been processed. */
-	prio = PRIO_GPIODEMUX(irq);
-	/* demux irq? */
-	if (prio != -1)
-		return IVG13 - prio;
-
-	for (ient = 0; ient < NR_PERI_INTS; ient++) {
-		struct ivgx *ivg = ivg_table + ient;
-		if (ivg->irqno == irq) {
-			for (prio = 0; prio <= IVG13-IVG7; prio++) {
-				if (ivg7_13[prio].ifirst <= ivg &&
-				    ivg7_13[prio].istop > ivg)
-					return IVG7 - prio;
-			}
-		}
-	}
-
-	return 0;
-}
-
 /* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */
 #ifdef CONFIG_DO_IRQ_L1
 __attribute__((l1_text))
 #endif
 asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
 {
+	struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
+	struct ipipe_domain *this_domain = ipipe_current_domain;
 	struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
 	struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
-	int irq;
+	int irq, s;
 
 	if (likely(vec == EVT_IVTMR_P)) {
 		irq = IRQ_CORETMR;
-		goto handle_irq;
+		goto core_tick;
 	}
 
 	SSYNC();
@@ -1319,24 +1278,39 @@
 	irq = ivg->irqno;
 
 	if (irq == IRQ_SYSTMR) {
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+core_tick:
+#else
 		bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */
+#endif
 		/* This is basically what we need from the register frame. */
 		__raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend;
 		__raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc;
-		if (!ipipe_root_domain_p)
-			__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
-		else
+		if (this_domain != ipipe_root_domain)
 			__raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10;
+		else
+			__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
 	}
 
-handle_irq:
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
+core_tick:
+#endif
+	if (this_domain == ipipe_root_domain) {
+		s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
+		barrier();
+	}
 
 	ipipe_trace_irq_entry(irq);
 	__ipipe_handle_irq(irq, regs);
-       ipipe_trace_irq_exit(irq);
+	ipipe_trace_irq_exit(irq);
 
-       if (ipipe_root_domain_p)
-		return !test_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status));
+	if (this_domain == ipipe_root_domain) {
+		set_thread_flag(TIF_IRQ_SYNC);
+		if (!s) {
+			__clear_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
+			return !test_bit(IPIPE_STALL_FLAG, &p->status);
+		}
+	}
 
        return 0;
 }
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index 77c9928..93eab61 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -158,10 +158,14 @@
 			kfree(msg);
 			break;
 		case BFIN_IPI_CALL_FUNC:
+			spin_unlock(&msg_queue->lock);
 			ipi_call_function(cpu, msg);
+			spin_lock(&msg_queue->lock);
 			break;
 		case BFIN_IPI_CPU_STOP:
+			spin_unlock(&msg_queue->lock);
 			ipi_cpu_stop(cpu);
+			spin_lock(&msg_queue->lock);
 			kfree(msg);
 			break;
 		default:
@@ -457,7 +461,7 @@
 	smp_flush_data.start = start;
 	smp_flush_data.end = end;
 
-	if (smp_call_function(&ipi_flush_icache, &smp_flush_data, 1))
+	if (smp_call_function(&ipi_flush_icache, &smp_flush_data, 0))
 		printk(KERN_WARNING "SMP: failed to run I-cache flush request on other CPUs\n");
 }
 EXPORT_SYMBOL_GPL(smp_icache_flush_range_others);
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
index d0532b7..9c3629b 100644
--- a/arch/blackfin/mm/init.c
+++ b/arch/blackfin/mm/init.c
@@ -104,7 +104,7 @@
 	}
 }
 
-asmlinkage void init_pda(void)
+asmlinkage void __init init_pda(void)
 {
 	unsigned int cpu = raw_smp_processor_id();
 
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
index e626e50..060df4a 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
@@ -135,11 +135,10 @@
 	if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
 		pci_addr = IS_PIC_SOFT(pcibus_info) ?
 				PHYS_TO_DMA(paddr) :
-		    		PHYS_TO_TIODMA(paddr) | dma_attributes;
+				PHYS_TO_TIODMA(paddr);
 	else
-		pci_addr = IS_PIC_SOFT(pcibus_info) ?
-				paddr :
-				paddr | dma_attributes;
+		pci_addr = paddr;
+	pci_addr |= dma_attributes;
 
 	/* Handle Bus mode */
 	if (IS_PCIX(pcibus_info))
diff --git a/arch/m68k/include/asm/param.h b/arch/m68k/include/asm/param.h
index 40d1112..85c41b7 100644
--- a/arch/m68k/include/asm/param.h
+++ b/arch/m68k/include/asm/param.h
@@ -1,5 +1,26 @@
-#ifdef __uClinux__
-#include "param_no.h"
-#else
-#include "param_mm.h"
+#ifndef _M68K_PARAM_H
+#define _M68K_PARAM_H
+
+#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() */
 #endif
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#ifdef __uClinux__
+#define EXEC_PAGESIZE	4096
+#else
+#define EXEC_PAGESIZE	8192
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP		(-1)
+#endif
+
+#define MAXHOSTNAMELEN	64	/* max length of hostname */
+
+#endif /* _M68K_PARAM_H */
diff --git a/arch/m68k/include/asm/param_mm.h b/arch/m68k/include/asm/param_mm.h
deleted file mode 100644
index 536a278..0000000
--- a/arch/m68k/include/asm/param_mm.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _M68K_PARAM_H
-#define _M68K_PARAM_H
-
-#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() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE	8192
-
-#ifndef NOGROUP
-#define NOGROUP		(-1)
-#endif
-
-#define MAXHOSTNAMELEN	64	/* max length of hostname */
-
-#endif /* _M68K_PARAM_H */
diff --git a/arch/m68k/include/asm/param_no.h b/arch/m68k/include/asm/param_no.h
deleted file mode 100644
index 6044397..0000000
--- a/arch/m68k/include/asm/param_no.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _M68KNOMMU_PARAM_H
-#define _M68KNOMMU_PARAM_H
-
-#ifdef __KERNEL__
-#define HZ CONFIG_HZ
-#define	USER_HZ		HZ
-#define	CLOCKS_PER_SEC	(USER_HZ)
-#endif
-
-#ifndef HZ
-#define HZ	100
-#endif
-
-#define EXEC_PAGESIZE	4096
-
-#ifndef NOGROUP
-#define NOGROUP		(-1)
-#endif
-
-#define MAXHOSTNAMELEN	64	/* max length of hostname */
-
-#endif /* _M68KNOMMU_PARAM_H */
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h
index e83cd2f..8c9194b 100644
--- a/arch/m68k/include/asm/ptrace.h
+++ b/arch/m68k/include/asm/ptrace.h
@@ -1,5 +1,87 @@
-#ifdef __uClinux__
-#include "ptrace_no.h"
+#ifndef _M68K_PTRACE_H
+#define _M68K_PTRACE_H
+
+#define PT_D1	   0
+#define PT_D2	   1
+#define PT_D3	   2
+#define PT_D4	   3
+#define PT_D5	   4
+#define PT_D6	   5
+#define PT_D7	   6
+#define PT_A0	   7
+#define PT_A1	   8
+#define PT_A2	   9
+#define PT_A3	   10
+#define PT_A4	   11
+#define PT_A5	   12
+#define PT_A6	   13
+#define PT_D0	   14
+#define PT_USP	   15
+#define PT_ORIG_D0 16
+#define PT_SR	   17
+#define PT_PC	   18
+
+#ifndef __ASSEMBLY__
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+struct pt_regs {
+  long     d1;
+  long     d2;
+  long     d3;
+  long     d4;
+  long     d5;
+  long     a0;
+  long     a1;
+  long     a2;
+  long     d0;
+  long     orig_d0;
+  long     stkadj;
+#ifdef CONFIG_COLDFIRE
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
+  unsigned short sr;
+  unsigned long  pc;
 #else
-#include "ptrace_mm.h"
+  unsigned short sr;
+  unsigned long  pc;
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
 #endif
+};
+
+/*
+ * This is the extended stack used by signal handlers and the context
+ * switcher: it's pushed after the normal "struct pt_regs".
+ */
+struct switch_stack {
+	unsigned long  d6;
+	unsigned long  d7;
+	unsigned long  a3;
+	unsigned long  a4;
+	unsigned long  a5;
+	unsigned long  a6;
+	unsigned long  retpc;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+
+#ifdef __KERNEL__
+
+#ifndef PS_S
+#define PS_S  (0x2000)
+#define PS_M  (0x1000)
+#endif
+
+#define user_mode(regs) (!((regs)->sr & PS_S))
+#define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
+extern void show_regs(struct pt_regs *);
+#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+#endif /* _M68K_PTRACE_H */
diff --git a/arch/m68k/include/asm/ptrace_mm.h b/arch/m68k/include/asm/ptrace_mm.h
deleted file mode 100644
index 57e763d..0000000
--- a/arch/m68k/include/asm/ptrace_mm.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef _M68K_PTRACE_H
-#define _M68K_PTRACE_H
-
-#define PT_D1	   0
-#define PT_D2	   1
-#define PT_D3	   2
-#define PT_D4	   3
-#define PT_D5	   4
-#define PT_D6	   5
-#define PT_D7	   6
-#define PT_A0	   7
-#define PT_A1	   8
-#define PT_A2	   9
-#define PT_A3	   10
-#define PT_A4	   11
-#define PT_A5	   12
-#define PT_A6	   13
-#define PT_D0	   14
-#define PT_USP	   15
-#define PT_ORIG_D0 16
-#define PT_SR	   17
-#define PT_PC	   18
-
-#ifndef __ASSEMBLY__
-
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct pt_regs {
-  long     d1;
-  long     d2;
-  long     d3;
-  long     d4;
-  long     d5;
-  long     a0;
-  long     a1;
-  long     a2;
-  long     d0;
-  long     orig_d0;
-  long     stkadj;
-  unsigned short sr;
-  unsigned long  pc;
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-};
-
-/*
- * This is the extended stack used by signal handlers and the context
- * switcher: it's pushed after the normal "struct pt_regs".
- */
-struct switch_stack {
-	unsigned long  d6;
-	unsigned long  d7;
-	unsigned long  a3;
-	unsigned long  a4;
-	unsigned long  a5;
-	unsigned long  a6;
-	unsigned long  retpc;
-};
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-
-#ifdef __KERNEL__
-
-#ifndef PS_S
-#define PS_S  (0x2000)
-#define PS_M  (0x1000)
-#endif
-
-#define user_mode(regs) (!((regs)->sr & PS_S))
-#define instruction_pointer(regs) ((regs)->pc)
-#define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
-#endif /* __KERNEL__ */
-#endif /* __ASSEMBLY__ */
-#endif /* _M68K_PTRACE_H */
diff --git a/arch/m68k/include/asm/ptrace_no.h b/arch/m68k/include/asm/ptrace_no.h
deleted file mode 100644
index 8c9194b..0000000
--- a/arch/m68k/include/asm/ptrace_no.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef _M68K_PTRACE_H
-#define _M68K_PTRACE_H
-
-#define PT_D1	   0
-#define PT_D2	   1
-#define PT_D3	   2
-#define PT_D4	   3
-#define PT_D5	   4
-#define PT_D6	   5
-#define PT_D7	   6
-#define PT_A0	   7
-#define PT_A1	   8
-#define PT_A2	   9
-#define PT_A3	   10
-#define PT_A4	   11
-#define PT_A5	   12
-#define PT_A6	   13
-#define PT_D0	   14
-#define PT_USP	   15
-#define PT_ORIG_D0 16
-#define PT_SR	   17
-#define PT_PC	   18
-
-#ifndef __ASSEMBLY__
-
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct pt_regs {
-  long     d1;
-  long     d2;
-  long     d3;
-  long     d4;
-  long     d5;
-  long     a0;
-  long     a1;
-  long     a2;
-  long     d0;
-  long     orig_d0;
-  long     stkadj;
-#ifdef CONFIG_COLDFIRE
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-  unsigned short sr;
-  unsigned long  pc;
-#else
-  unsigned short sr;
-  unsigned long  pc;
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-#endif
-};
-
-/*
- * This is the extended stack used by signal handlers and the context
- * switcher: it's pushed after the normal "struct pt_regs".
- */
-struct switch_stack {
-	unsigned long  d6;
-	unsigned long  d7;
-	unsigned long  a3;
-	unsigned long  a4;
-	unsigned long  a5;
-	unsigned long  a6;
-	unsigned long  retpc;
-};
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-
-#ifdef __KERNEL__
-
-#ifndef PS_S
-#define PS_S  (0x2000)
-#define PS_M  (0x1000)
-#endif
-
-#define user_mode(regs) (!((regs)->sr & PS_S))
-#define instruction_pointer(regs) ((regs)->pc)
-#define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
-#endif /* __KERNEL__ */
-#endif /* __ASSEMBLY__ */
-#endif /* _M68K_PTRACE_H */
diff --git a/arch/m68k/include/asm/setup.h b/arch/m68k/include/asm/setup.h
index 842f86f..4dfb395 100644
--- a/arch/m68k/include/asm/setup.h
+++ b/arch/m68k/include/asm/setup.h
@@ -1,5 +1,376 @@
-#ifdef __uClinux__
-#include "setup_no.h"
+/*
+** asm/setup.h -- Definition of the Linux/m68k setup information
+**
+** Copyright 1992 by Greg Harp
+**
+** 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.
+**
+** Created 09/29/92 by Greg Harp
+**
+** 5/2/94 Roman Hodek:
+**   Added bi_atari part of the machine dependent union bi_un; for now it
+**   contains just a model field to distinguish between TT and Falcon.
+** 26/7/96 Roman Zippel:
+**   Renamed to setup.h; added some useful macros to allow gcc some
+**   optimizations if possible.
+** 5/10/96 Geert Uytterhoeven:
+**   Redesign of the boot information structure; moved boot information
+**   structure to bootinfo.h
+*/
+
+#ifndef _M68K_SETUP_H
+#define _M68K_SETUP_H
+
+
+
+    /*
+     *  Linux/m68k Architectures
+     */
+
+#define MACH_AMIGA    1
+#define MACH_ATARI    2
+#define MACH_MAC      3
+#define MACH_APOLLO   4
+#define MACH_SUN3     5
+#define MACH_MVME147  6
+#define MACH_MVME16x  7
+#define MACH_BVME6000 8
+#define MACH_HP300    9
+#define MACH_Q40     10
+#define MACH_SUN3X   11
+
+#define COMMAND_LINE_SIZE 256
+
+#ifdef __KERNEL__
+
+#define CL_SIZE COMMAND_LINE_SIZE
+
+#ifndef __ASSEMBLY__
+extern unsigned long m68k_machtype;
+#endif /* !__ASSEMBLY__ */
+
+#if !defined(CONFIG_AMIGA)
+#  define MACH_IS_AMIGA (0)
+#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
+	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)               \
+	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                      \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+#  define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA)
 #else
-#include "setup_mm.h"
+#  define MACH_AMIGA_ONLY
+#  define MACH_IS_AMIGA (1)
+#  define MACH_TYPE (MACH_AMIGA)
 #endif
+
+#if !defined(CONFIG_ATARI)
+#  define MACH_IS_ATARI (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
+	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)               \
+	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                      \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+#  define MACH_IS_ATARI (m68k_machtype == MACH_ATARI)
+#else
+#  define MACH_ATARI_ONLY
+#  define MACH_IS_ATARI (1)
+#  define MACH_TYPE (MACH_ATARI)
+#endif
+
+#if !defined(CONFIG_MAC)
+#  define MACH_IS_MAC (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) \
+	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)                 \
+	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                        \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+#  define MACH_IS_MAC (m68k_machtype == MACH_MAC)
+#else
+#  define MACH_MAC_ONLY
+#  define MACH_IS_MAC (1)
+#  define MACH_TYPE (MACH_MAC)
+#endif
+
+#if defined(CONFIG_SUN3)
+#define MACH_IS_SUN3 (1)
+#define MACH_SUN3_ONLY (1)
+#define MACH_TYPE (MACH_SUN3)
+#else
+#define MACH_IS_SUN3 (0)
+#endif
+
+#if !defined (CONFIG_APOLLO)
+#  define MACH_IS_APOLLO (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)              \
+	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+#  define MACH_IS_APOLLO (m68k_machtype == MACH_APOLLO)
+#else
+#  define MACH_APOLLO_ONLY
+#  define MACH_IS_APOLLO (1)
+#  define MACH_TYPE (MACH_APOLLO)
+#endif
+
+#if !defined (CONFIG_MVME147)
+#  define MACH_IS_MVME147 (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+	|| defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000)               \
+	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME16x)
+#  define MACH_IS_MVME147 (m68k_machtype == MACH_MVME147)
+#else
+#  define MACH_MVME147_ONLY
+#  define MACH_IS_MVME147 (1)
+#  define MACH_TYPE (MACH_MVME147)
+#endif
+
+#if !defined (CONFIG_MVME16x)
+#  define MACH_IS_MVME16x (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+	|| defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000)               \
+	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+#  define MACH_IS_MVME16x (m68k_machtype == MACH_MVME16x)
+#else
+#  define MACH_MVME16x_ONLY
+#  define MACH_IS_MVME16x (1)
+#  define MACH_TYPE (MACH_MVME16x)
+#endif
+
+#if !defined (CONFIG_BVME6000)
+#  define MACH_IS_BVME6000 (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
+	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+#  define MACH_IS_BVME6000 (m68k_machtype == MACH_BVME6000)
+#else
+#  define MACH_BVME6000_ONLY
+#  define MACH_IS_BVME6000 (1)
+#  define MACH_TYPE (MACH_BVME6000)
+#endif
+
+#if !defined (CONFIG_HP300)
+#  define MACH_IS_HP300 (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \
+	|| defined(CONFIG_BVME6000) || defined(CONFIG_Q40) \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+#  define MACH_IS_HP300 (m68k_machtype == MACH_HP300)
+#else
+#  define MACH_HP300_ONLY
+#  define MACH_IS_HP300 (1)
+#  define MACH_TYPE (MACH_HP300)
+#endif
+
+#if !defined (CONFIG_Q40)
+#  define MACH_IS_Q40 (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
+	|| defined(CONFIG_BVME6000) || defined(CONFIG_HP300)                \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+#  define MACH_IS_Q40 (m68k_machtype == MACH_Q40)
+#else
+#  define MACH_Q40_ONLY
+#  define MACH_IS_Q40 (1)
+#  define MACH_TYPE (MACH_Q40)
+#endif
+
+#if !defined (CONFIG_SUN3X)
+#  define MACH_IS_SUN3X (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
+	|| defined(CONFIG_BVME6000) || defined(CONFIG_HP300)                \
+	|| defined(CONFIG_Q40) || defined(CONFIG_MVME147)
+#  define MACH_IS_SUN3X (m68k_machtype == MACH_SUN3X)
+#else
+#  define CONFIG_SUN3X_ONLY
+#  define MACH_IS_SUN3X (1)
+#  define MACH_TYPE (MACH_SUN3X)
+#endif
+
+#ifndef MACH_TYPE
+#  define MACH_TYPE (m68k_machtype)
+#endif
+
+#endif /* __KERNEL__ */
+
+
+    /*
+     *  CPU, FPU and MMU types
+     *
+     *  Note: we may rely on the following equalities:
+     *
+     *      CPU_68020 == MMU_68851
+     *      CPU_68030 == MMU_68030
+     *      CPU_68040 == FPU_68040 == MMU_68040
+     *      CPU_68060 == FPU_68060 == MMU_68060
+     */
+
+#define CPUB_68020     0
+#define CPUB_68030     1
+#define CPUB_68040     2
+#define CPUB_68060     3
+
+#define CPU_68020      (1<<CPUB_68020)
+#define CPU_68030      (1<<CPUB_68030)
+#define CPU_68040      (1<<CPUB_68040)
+#define CPU_68060      (1<<CPUB_68060)
+
+#define FPUB_68881     0
+#define FPUB_68882     1
+#define FPUB_68040     2                       /* Internal FPU */
+#define FPUB_68060     3                       /* Internal FPU */
+#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
+
+#define FPU_68881      (1<<FPUB_68881)
+#define FPU_68882      (1<<FPUB_68882)
+#define FPU_68040      (1<<FPUB_68040)
+#define FPU_68060      (1<<FPUB_68060)
+#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
+
+#define MMUB_68851     0
+#define MMUB_68030     1                       /* Internal MMU */
+#define MMUB_68040     2                       /* Internal MMU */
+#define MMUB_68060     3                       /* Internal MMU */
+#define MMUB_APOLLO    4                       /* Custom Apollo */
+#define MMUB_SUN3      5                       /* Custom Sun-3 */
+
+#define MMU_68851      (1<<MMUB_68851)
+#define MMU_68030      (1<<MMUB_68030)
+#define MMU_68040      (1<<MMUB_68040)
+#define MMU_68060      (1<<MMUB_68060)
+#define MMU_SUN3       (1<<MMUB_SUN3)
+#define MMU_APOLLO     (1<<MMUB_APOLLO)
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+extern unsigned long m68k_cputype;
+extern unsigned long m68k_fputype;
+extern unsigned long m68k_mmutype;
+#ifdef CONFIG_VME
+extern unsigned long vme_brdtype;
+#endif
+
+    /*
+     *  m68k_is040or060 is != 0 for a '040 or higher;
+     *  used numbers are 4 for 68040 and 6 for 68060.
+     */
+
+extern int m68k_is040or060;
+#endif /* !__ASSEMBLY__ */
+
+#if !defined(CONFIG_M68020)
+#  define CPU_IS_020 (0)
+#  define MMU_IS_851 (0)
+#  define MMU_IS_SUN3 (0)
+#elif defined(CONFIG_M68030) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
+#  define CPU_IS_020 (m68k_cputype & CPU_68020)
+#  define MMU_IS_851 (m68k_mmutype & MMU_68851)
+#  define MMU_IS_SUN3 (0)	/* Sun3 not supported with other CPU enabled */
+#else
+#  define CPU_M68020_ONLY
+#  define CPU_IS_020 (1)
+#ifdef MACH_SUN3_ONLY
+#  define MMU_IS_SUN3 (1)
+#  define MMU_IS_851 (0)
+#else
+#  define MMU_IS_SUN3 (0)
+#  define MMU_IS_851 (1)
+#endif
+#endif
+
+#if !defined(CONFIG_M68030)
+#  define CPU_IS_030 (0)
+#  define MMU_IS_030 (0)
+#elif defined(CONFIG_M68020) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
+#  define CPU_IS_030 (m68k_cputype & CPU_68030)
+#  define MMU_IS_030 (m68k_mmutype & MMU_68030)
+#else
+#  define CPU_M68030_ONLY
+#  define CPU_IS_030 (1)
+#  define MMU_IS_030 (1)
+#endif
+
+#if !defined(CONFIG_M68040)
+#  define CPU_IS_040 (0)
+#  define MMU_IS_040 (0)
+#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68060)
+#  define CPU_IS_040 (m68k_cputype & CPU_68040)
+#  define MMU_IS_040 (m68k_mmutype & MMU_68040)
+#else
+#  define CPU_M68040_ONLY
+#  define CPU_IS_040 (1)
+#  define MMU_IS_040 (1)
+#endif
+
+#if !defined(CONFIG_M68060)
+#  define CPU_IS_060 (0)
+#  define MMU_IS_060 (0)
+#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68040)
+#  define CPU_IS_060 (m68k_cputype & CPU_68060)
+#  define MMU_IS_060 (m68k_mmutype & MMU_68060)
+#else
+#  define CPU_M68060_ONLY
+#  define CPU_IS_060 (1)
+#  define MMU_IS_060 (1)
+#endif
+
+#if !defined(CONFIG_M68020) && !defined(CONFIG_M68030)
+#  define CPU_IS_020_OR_030 (0)
+#else
+#  define CPU_M68020_OR_M68030
+#  if defined(CONFIG_M68040) || defined(CONFIG_M68060)
+#    define CPU_IS_020_OR_030 (!m68k_is040or060)
+#  else
+#    define CPU_M68020_OR_M68030_ONLY
+#    define CPU_IS_020_OR_030 (1)
+#  endif
+#endif
+
+#if !defined(CONFIG_M68040) && !defined(CONFIG_M68060)
+#  define CPU_IS_040_OR_060 (0)
+#else
+#  define CPU_M68040_OR_M68060
+#  if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+#    define CPU_IS_040_OR_060 (m68k_is040or060)
+#  else
+#    define CPU_M68040_OR_M68060_ONLY
+#    define CPU_IS_040_OR_060 (1)
+#  endif
+#endif
+
+#define CPU_TYPE (m68k_cputype)
+
+#ifdef CONFIG_M68KFPU_EMU
+#  ifdef CONFIG_M68KFPU_EMU_ONLY
+#    define FPU_IS_EMU (1)
+#  else
+#    define FPU_IS_EMU (!m68k_fputype)
+#  endif
+#else
+#  define FPU_IS_EMU (0)
+#endif
+
+
+    /*
+     *  Miscellaneous
+     */
+
+#define NUM_MEMINFO	4
+
+#ifndef __ASSEMBLY__
+struct mem_info {
+	unsigned long addr;		/* physical address of memory chunk */
+	unsigned long size;		/* length of memory chunk (in bytes) */
+};
+
+extern int m68k_num_memory;		/* # of memory blocks found (and used) */
+extern int m68k_realnum_memory;		/* real # of memory blocks found */
+extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _M68K_SETUP_H */
diff --git a/arch/m68k/include/asm/setup_mm.h b/arch/m68k/include/asm/setup_mm.h
deleted file mode 100644
index 4dfb395..0000000
--- a/arch/m68k/include/asm/setup_mm.h
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
-** asm/setup.h -- Definition of the Linux/m68k setup information
-**
-** Copyright 1992 by Greg Harp
-**
-** 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.
-**
-** Created 09/29/92 by Greg Harp
-**
-** 5/2/94 Roman Hodek:
-**   Added bi_atari part of the machine dependent union bi_un; for now it
-**   contains just a model field to distinguish between TT and Falcon.
-** 26/7/96 Roman Zippel:
-**   Renamed to setup.h; added some useful macros to allow gcc some
-**   optimizations if possible.
-** 5/10/96 Geert Uytterhoeven:
-**   Redesign of the boot information structure; moved boot information
-**   structure to bootinfo.h
-*/
-
-#ifndef _M68K_SETUP_H
-#define _M68K_SETUP_H
-
-
-
-    /*
-     *  Linux/m68k Architectures
-     */
-
-#define MACH_AMIGA    1
-#define MACH_ATARI    2
-#define MACH_MAC      3
-#define MACH_APOLLO   4
-#define MACH_SUN3     5
-#define MACH_MVME147  6
-#define MACH_MVME16x  7
-#define MACH_BVME6000 8
-#define MACH_HP300    9
-#define MACH_Q40     10
-#define MACH_SUN3X   11
-
-#define COMMAND_LINE_SIZE 256
-
-#ifdef __KERNEL__
-
-#define CL_SIZE COMMAND_LINE_SIZE
-
-#ifndef __ASSEMBLY__
-extern unsigned long m68k_machtype;
-#endif /* !__ASSEMBLY__ */
-
-#if !defined(CONFIG_AMIGA)
-#  define MACH_IS_AMIGA (0)
-#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
-	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)               \
-	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                      \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
-#  define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA)
-#else
-#  define MACH_AMIGA_ONLY
-#  define MACH_IS_AMIGA (1)
-#  define MACH_TYPE (MACH_AMIGA)
-#endif
-
-#if !defined(CONFIG_ATARI)
-#  define MACH_IS_ATARI (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
-	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)               \
-	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                      \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
-#  define MACH_IS_ATARI (m68k_machtype == MACH_ATARI)
-#else
-#  define MACH_ATARI_ONLY
-#  define MACH_IS_ATARI (1)
-#  define MACH_TYPE (MACH_ATARI)
-#endif
-
-#if !defined(CONFIG_MAC)
-#  define MACH_IS_MAC (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) \
-	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)                 \
-	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                        \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
-#  define MACH_IS_MAC (m68k_machtype == MACH_MAC)
-#else
-#  define MACH_MAC_ONLY
-#  define MACH_IS_MAC (1)
-#  define MACH_TYPE (MACH_MAC)
-#endif
-
-#if defined(CONFIG_SUN3)
-#define MACH_IS_SUN3 (1)
-#define MACH_SUN3_ONLY (1)
-#define MACH_TYPE (MACH_SUN3)
-#else
-#define MACH_IS_SUN3 (0)
-#endif
-
-#if !defined (CONFIG_APOLLO)
-#  define MACH_IS_APOLLO (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
-	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)              \
-	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
-#  define MACH_IS_APOLLO (m68k_machtype == MACH_APOLLO)
-#else
-#  define MACH_APOLLO_ONLY
-#  define MACH_IS_APOLLO (1)
-#  define MACH_TYPE (MACH_APOLLO)
-#endif
-
-#if !defined (CONFIG_MVME147)
-#  define MACH_IS_MVME147 (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
-	|| defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000)               \
-	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME16x)
-#  define MACH_IS_MVME147 (m68k_machtype == MACH_MVME147)
-#else
-#  define MACH_MVME147_ONLY
-#  define MACH_IS_MVME147 (1)
-#  define MACH_TYPE (MACH_MVME147)
-#endif
-
-#if !defined (CONFIG_MVME16x)
-#  define MACH_IS_MVME16x (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
-	|| defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000)               \
-	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
-#  define MACH_IS_MVME16x (m68k_machtype == MACH_MVME16x)
-#else
-#  define MACH_MVME16x_ONLY
-#  define MACH_IS_MVME16x (1)
-#  define MACH_TYPE (MACH_MVME16x)
-#endif
-
-#if !defined (CONFIG_BVME6000)
-#  define MACH_IS_BVME6000 (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
-	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
-	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
-#  define MACH_IS_BVME6000 (m68k_machtype == MACH_BVME6000)
-#else
-#  define MACH_BVME6000_ONLY
-#  define MACH_IS_BVME6000 (1)
-#  define MACH_TYPE (MACH_BVME6000)
-#endif
-
-#if !defined (CONFIG_HP300)
-#  define MACH_IS_HP300 (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
-	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \
-	|| defined(CONFIG_BVME6000) || defined(CONFIG_Q40) \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
-#  define MACH_IS_HP300 (m68k_machtype == MACH_HP300)
-#else
-#  define MACH_HP300_ONLY
-#  define MACH_IS_HP300 (1)
-#  define MACH_TYPE (MACH_HP300)
-#endif
-
-#if !defined (CONFIG_Q40)
-#  define MACH_IS_Q40 (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
-	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
-	|| defined(CONFIG_BVME6000) || defined(CONFIG_HP300)                \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
-#  define MACH_IS_Q40 (m68k_machtype == MACH_Q40)
-#else
-#  define MACH_Q40_ONLY
-#  define MACH_IS_Q40 (1)
-#  define MACH_TYPE (MACH_Q40)
-#endif
-
-#if !defined (CONFIG_SUN3X)
-#  define MACH_IS_SUN3X (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
-	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
-	|| defined(CONFIG_BVME6000) || defined(CONFIG_HP300)                \
-	|| defined(CONFIG_Q40) || defined(CONFIG_MVME147)
-#  define MACH_IS_SUN3X (m68k_machtype == MACH_SUN3X)
-#else
-#  define CONFIG_SUN3X_ONLY
-#  define MACH_IS_SUN3X (1)
-#  define MACH_TYPE (MACH_SUN3X)
-#endif
-
-#ifndef MACH_TYPE
-#  define MACH_TYPE (m68k_machtype)
-#endif
-
-#endif /* __KERNEL__ */
-
-
-    /*
-     *  CPU, FPU and MMU types
-     *
-     *  Note: we may rely on the following equalities:
-     *
-     *      CPU_68020 == MMU_68851
-     *      CPU_68030 == MMU_68030
-     *      CPU_68040 == FPU_68040 == MMU_68040
-     *      CPU_68060 == FPU_68060 == MMU_68060
-     */
-
-#define CPUB_68020     0
-#define CPUB_68030     1
-#define CPUB_68040     2
-#define CPUB_68060     3
-
-#define CPU_68020      (1<<CPUB_68020)
-#define CPU_68030      (1<<CPUB_68030)
-#define CPU_68040      (1<<CPUB_68040)
-#define CPU_68060      (1<<CPUB_68060)
-
-#define FPUB_68881     0
-#define FPUB_68882     1
-#define FPUB_68040     2                       /* Internal FPU */
-#define FPUB_68060     3                       /* Internal FPU */
-#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
-
-#define FPU_68881      (1<<FPUB_68881)
-#define FPU_68882      (1<<FPUB_68882)
-#define FPU_68040      (1<<FPUB_68040)
-#define FPU_68060      (1<<FPUB_68060)
-#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
-
-#define MMUB_68851     0
-#define MMUB_68030     1                       /* Internal MMU */
-#define MMUB_68040     2                       /* Internal MMU */
-#define MMUB_68060     3                       /* Internal MMU */
-#define MMUB_APOLLO    4                       /* Custom Apollo */
-#define MMUB_SUN3      5                       /* Custom Sun-3 */
-
-#define MMU_68851      (1<<MMUB_68851)
-#define MMU_68030      (1<<MMUB_68030)
-#define MMU_68040      (1<<MMUB_68040)
-#define MMU_68060      (1<<MMUB_68060)
-#define MMU_SUN3       (1<<MMUB_SUN3)
-#define MMU_APOLLO     (1<<MMUB_APOLLO)
-
-#ifdef __KERNEL__
-
-#ifndef __ASSEMBLY__
-extern unsigned long m68k_cputype;
-extern unsigned long m68k_fputype;
-extern unsigned long m68k_mmutype;
-#ifdef CONFIG_VME
-extern unsigned long vme_brdtype;
-#endif
-
-    /*
-     *  m68k_is040or060 is != 0 for a '040 or higher;
-     *  used numbers are 4 for 68040 and 6 for 68060.
-     */
-
-extern int m68k_is040or060;
-#endif /* !__ASSEMBLY__ */
-
-#if !defined(CONFIG_M68020)
-#  define CPU_IS_020 (0)
-#  define MMU_IS_851 (0)
-#  define MMU_IS_SUN3 (0)
-#elif defined(CONFIG_M68030) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
-#  define CPU_IS_020 (m68k_cputype & CPU_68020)
-#  define MMU_IS_851 (m68k_mmutype & MMU_68851)
-#  define MMU_IS_SUN3 (0)	/* Sun3 not supported with other CPU enabled */
-#else
-#  define CPU_M68020_ONLY
-#  define CPU_IS_020 (1)
-#ifdef MACH_SUN3_ONLY
-#  define MMU_IS_SUN3 (1)
-#  define MMU_IS_851 (0)
-#else
-#  define MMU_IS_SUN3 (0)
-#  define MMU_IS_851 (1)
-#endif
-#endif
-
-#if !defined(CONFIG_M68030)
-#  define CPU_IS_030 (0)
-#  define MMU_IS_030 (0)
-#elif defined(CONFIG_M68020) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
-#  define CPU_IS_030 (m68k_cputype & CPU_68030)
-#  define MMU_IS_030 (m68k_mmutype & MMU_68030)
-#else
-#  define CPU_M68030_ONLY
-#  define CPU_IS_030 (1)
-#  define MMU_IS_030 (1)
-#endif
-
-#if !defined(CONFIG_M68040)
-#  define CPU_IS_040 (0)
-#  define MMU_IS_040 (0)
-#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68060)
-#  define CPU_IS_040 (m68k_cputype & CPU_68040)
-#  define MMU_IS_040 (m68k_mmutype & MMU_68040)
-#else
-#  define CPU_M68040_ONLY
-#  define CPU_IS_040 (1)
-#  define MMU_IS_040 (1)
-#endif
-
-#if !defined(CONFIG_M68060)
-#  define CPU_IS_060 (0)
-#  define MMU_IS_060 (0)
-#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68040)
-#  define CPU_IS_060 (m68k_cputype & CPU_68060)
-#  define MMU_IS_060 (m68k_mmutype & MMU_68060)
-#else
-#  define CPU_M68060_ONLY
-#  define CPU_IS_060 (1)
-#  define MMU_IS_060 (1)
-#endif
-
-#if !defined(CONFIG_M68020) && !defined(CONFIG_M68030)
-#  define CPU_IS_020_OR_030 (0)
-#else
-#  define CPU_M68020_OR_M68030
-#  if defined(CONFIG_M68040) || defined(CONFIG_M68060)
-#    define CPU_IS_020_OR_030 (!m68k_is040or060)
-#  else
-#    define CPU_M68020_OR_M68030_ONLY
-#    define CPU_IS_020_OR_030 (1)
-#  endif
-#endif
-
-#if !defined(CONFIG_M68040) && !defined(CONFIG_M68060)
-#  define CPU_IS_040_OR_060 (0)
-#else
-#  define CPU_M68040_OR_M68060
-#  if defined(CONFIG_M68020) || defined(CONFIG_M68030)
-#    define CPU_IS_040_OR_060 (m68k_is040or060)
-#  else
-#    define CPU_M68040_OR_M68060_ONLY
-#    define CPU_IS_040_OR_060 (1)
-#  endif
-#endif
-
-#define CPU_TYPE (m68k_cputype)
-
-#ifdef CONFIG_M68KFPU_EMU
-#  ifdef CONFIG_M68KFPU_EMU_ONLY
-#    define FPU_IS_EMU (1)
-#  else
-#    define FPU_IS_EMU (!m68k_fputype)
-#  endif
-#else
-#  define FPU_IS_EMU (0)
-#endif
-
-
-    /*
-     *  Miscellaneous
-     */
-
-#define NUM_MEMINFO	4
-
-#ifndef __ASSEMBLY__
-struct mem_info {
-	unsigned long addr;		/* physical address of memory chunk */
-	unsigned long size;		/* length of memory chunk (in bytes) */
-};
-
-extern int m68k_num_memory;		/* # of memory blocks found (and used) */
-extern int m68k_realnum_memory;		/* real # of memory blocks found */
-extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
-#endif
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68K_SETUP_H */
diff --git a/arch/m68k/include/asm/setup_no.h b/arch/m68k/include/asm/setup_no.h
deleted file mode 100644
index 45d286c..0000000
--- a/arch/m68k/include/asm/setup_no.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifdef __KERNEL__
-
-#include <asm/setup_mm.h>
-
-/* We have a bigger command line buffer. */
-#undef COMMAND_LINE_SIZE
-
-#endif  /*  __KERNEL__  */
-
-#define COMMAND_LINE_SIZE	512
diff --git a/arch/m68k/include/asm/sigcontext.h b/arch/m68k/include/asm/sigcontext.h
index bff6d40..523db2a 100644
--- a/arch/m68k/include/asm/sigcontext.h
+++ b/arch/m68k/include/asm/sigcontext.h
@@ -1,5 +1,24 @@
+#ifndef _ASM_M68k_SIGCONTEXT_H
+#define _ASM_M68k_SIGCONTEXT_H
+
+struct sigcontext {
+	unsigned long  sc_mask;		/* old sigmask */
+	unsigned long  sc_usp;		/* old user stack pointer */
+	unsigned long  sc_d0;
+	unsigned long  sc_d1;
+	unsigned long  sc_a0;
+	unsigned long  sc_a1;
 #ifdef __uClinux__
-#include "sigcontext_no.h"
-#else
-#include "sigcontext_mm.h"
+	unsigned long  sc_a5;
+#endif
+	unsigned short sc_sr;
+	unsigned long  sc_pc;
+	unsigned short sc_formatvec;
+#ifndef __uClinux__
+	unsigned long  sc_fpregs[2*3];  /* room for two fp registers */
+	unsigned long  sc_fpcntl[3];
+	unsigned char  sc_fpstate[216];
+#endif
+};
+
 #endif
diff --git a/arch/m68k/include/asm/sigcontext_mm.h b/arch/m68k/include/asm/sigcontext_mm.h
deleted file mode 100644
index 64fbe34..0000000
--- a/arch/m68k/include/asm/sigcontext_mm.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_M68k_SIGCONTEXT_H
-#define _ASM_M68k_SIGCONTEXT_H
-
-struct sigcontext {
-	unsigned long  sc_mask;		/* old sigmask */
-	unsigned long  sc_usp;		/* old user stack pointer */
-	unsigned long  sc_d0;
-	unsigned long  sc_d1;
-	unsigned long  sc_a0;
-	unsigned long  sc_a1;
-	unsigned short sc_sr;
-	unsigned long  sc_pc;
-	unsigned short sc_formatvec;
-	unsigned long  sc_fpregs[2*3];  /* room for two fp registers */
-	unsigned long  sc_fpcntl[3];
-	unsigned char  sc_fpstate[216];
-};
-
-#endif
diff --git a/arch/m68k/include/asm/sigcontext_no.h b/arch/m68k/include/asm/sigcontext_no.h
deleted file mode 100644
index 36c293f..0000000
--- a/arch/m68k/include/asm/sigcontext_no.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _ASM_M68KNOMMU_SIGCONTEXT_H
-#define _ASM_M68KNOMMU_SIGCONTEXT_H
-
-struct sigcontext {
-	unsigned long  sc_mask; 	/* old sigmask */
-	unsigned long  sc_usp;		/* old user stack pointer */
-	unsigned long  sc_d0;
-	unsigned long  sc_d1;
-	unsigned long  sc_a0;
-	unsigned long  sc_a1;
-	unsigned long  sc_a5;
-	unsigned short sc_sr;
-	unsigned long  sc_pc;
-	unsigned short sc_formatvec;
-};
-
-#endif
diff --git a/arch/m68k/include/asm/siginfo.h b/arch/m68k/include/asm/siginfo.h
index 61219d7..ca7dde8 100644
--- a/arch/m68k/include/asm/siginfo.h
+++ b/arch/m68k/include/asm/siginfo.h
@@ -1,5 +1,97 @@
-#ifdef __uClinux__
-#include "siginfo_no.h"
+#ifndef _M68K_SIGINFO_H
+#define _M68K_SIGINFO_H
+
+#ifndef __uClinux__
+#define HAVE_ARCH_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO
+#endif
+
+#include <asm-generic/siginfo.h>
+
+#ifndef __uClinux__
+
+typedef struct siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[SI_PAD_SIZE];
+
+		/* kill() */
+		struct {
+			__kernel_pid_t _pid;	/* sender's pid */
+			__kernel_uid_t _uid;	/* backwards compatibility */
+			__kernel_uid32_t _uid32; /* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			timer_t _tid;		/* timer id */
+			int _overrun;		/* overrun count */
+			char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
+			sigval_t _sigval;	/* same as below */
+			int _sys_private;       /* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			__kernel_pid_t _pid;	/* sender's pid */
+			__kernel_uid_t _uid;	/* backwards compatibility */
+			sigval_t _sigval;
+			__kernel_uid32_t _uid32; /* sender's uid */
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			__kernel_pid_t _pid;	/* which child */
+			__kernel_uid_t _uid;	/* backwards compatibility */
+			int _status;		/* exit code */
+			clock_t _utime;
+			clock_t _stime;
+			__kernel_uid32_t _uid32; /* sender's uid */
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			void *_addr; /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} siginfo_t;
+
+#define UID16_SIGINFO_COMPAT_NEEDED
+
+/*
+ * How these fields are to be accessed.
+ */
+#undef si_uid
+#ifdef __KERNEL__
+#define si_uid		_sifields._kill._uid32
+#define si_uid16	_sifields._kill._uid
 #else
-#include "siginfo_mm.h"
+#define si_uid		_sifields._kill._uid
+#endif
+
+#ifdef __KERNEL__
+
+#include <linux/string.h>
+
+static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
+{
+	if (from->si_code < 0)
+		memcpy(to, from, sizeof(*to));
+	else
+		/* _sigchld is currently the largest know union member */
+		memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
+}
+
+#endif /* __KERNEL__ */
+#endif /* !__uClinux__ */
+
 #endif
diff --git a/arch/m68k/include/asm/siginfo_mm.h b/arch/m68k/include/asm/siginfo_mm.h
deleted file mode 100644
index 05a8d6d..0000000
--- a/arch/m68k/include/asm/siginfo_mm.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef _M68K_SIGINFO_H
-#define _M68K_SIGINFO_H
-
-#define HAVE_ARCH_SIGINFO_T
-#define HAVE_ARCH_COPY_SIGINFO
-
-#include <asm-generic/siginfo.h>
-
-typedef struct siginfo {
-	int si_signo;
-	int si_errno;
-	int si_code;
-
-	union {
-		int _pad[SI_PAD_SIZE];
-
-		/* kill() */
-		struct {
-			__kernel_pid_t _pid;	/* sender's pid */
-			__kernel_uid_t _uid;	/* backwards compatibility */
-			__kernel_uid32_t _uid32; /* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			timer_t _tid;		/* timer id */
-			int _overrun;		/* overrun count */
-			char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
-			sigval_t _sigval;	/* same as below */
-			int _sys_private;       /* not to be passed to user */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			__kernel_pid_t _pid;	/* sender's pid */
-			__kernel_uid_t _uid;	/* backwards compatibility */
-			sigval_t _sigval;
-			__kernel_uid32_t _uid32; /* sender's uid */
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			__kernel_pid_t _pid;	/* which child */
-			__kernel_uid_t _uid;	/* backwards compatibility */
-			int _status;		/* exit code */
-			clock_t _utime;
-			clock_t _stime;
-			__kernel_uid32_t _uid32; /* sender's uid */
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-		struct {
-			void *_addr; /* faulting insn/memory ref. */
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-	} _sifields;
-} siginfo_t;
-
-#define UID16_SIGINFO_COMPAT_NEEDED
-
-/*
- * How these fields are to be accessed.
- */
-#undef si_uid
-#ifdef __KERNEL__
-#define si_uid		_sifields._kill._uid32
-#define si_uid16	_sifields._kill._uid
-#else
-#define si_uid		_sifields._kill._uid
-#endif
-
-#ifdef __KERNEL__
-
-#include <linux/string.h>
-
-static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
-{
-	if (from->si_code < 0)
-		memcpy(to, from, sizeof(*to));
-	else
-		/* _sigchld is currently the largest know union member */
-		memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
-}
-
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/arch/m68k/include/asm/siginfo_no.h b/arch/m68k/include/asm/siginfo_no.h
deleted file mode 100644
index b18e5f4..0000000
--- a/arch/m68k/include/asm/siginfo_no.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _M68KNOMMU_SIGINFO_H
-#define _M68KNOMMU_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h
index 3c19988..08788fd 100644
--- a/arch/m68k/include/asm/signal.h
+++ b/arch/m68k/include/asm/signal.h
@@ -1,5 +1,213 @@
-#ifdef __uClinux__
-#include "signal_no.h"
+#ifndef _M68K_SIGNAL_H
+#define _M68K_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifdef __KERNEL__
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define _NSIG		64
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t;		/* at least 32 bits */
+
+typedef struct {
+	unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
 #else
-#include "signal_mm.h"
-#endif
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG		32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+#define SIGBUS		 7
+#define SIGFPE		 8
+#define SIGKILL		 9
+#define SIGUSR1		10
+#define SIGSEGV		11
+#define SIGUSR2		12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGSTKFLT	16
+#define SIGCHLD		17
+#define SIGCONT		18
+#define SIGSTOP		19
+#define SIGTSTP		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGURG		23
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGIO		29
+#define SIGPOLL		SIGIO
+/*
+#define SIGLOST		29
+*/
+#define SIGPWR		30
+#define SIGSYS		31
+#define	SIGUNUSED	31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN	32
+#define SIGRTMAX	_NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP	0x00000001
+#define SA_NOCLDWAIT	0x00000002
+#define SA_SIGINFO	0x00000004
+#define SA_ONSTACK	0x08000000
+#define SA_RESTART	0x10000000
+#define SA_NODEFER	0x40000000
+#define SA_RESETHAND	0x80000000
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
+
+#include <asm-generic/signal.h>
+
+#ifdef __KERNEL__
+struct old_sigaction {
+	__sighandler_t sa_handler;
+	old_sigset_t sa_mask;
+	unsigned long sa_flags;
+	__sigrestore_t sa_restorer;
+};
+
+struct sigaction {
+	__sighandler_t sa_handler;
+	unsigned long sa_flags;
+	__sigrestore_t sa_restorer;
+	sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+struct k_sigaction {
+	struct sigaction sa;
+};
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, struct siginfo *, void *);
+	} _u;
+	sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+#define sa_handler	_u._sa_handler
+#define sa_sigaction	_u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+	void __user *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+
+#ifndef __uClinux__
+#define __HAVE_ARCH_SIG_BITOPS
+
+static inline void sigaddset(sigset_t *set, int _sig)
+{
+	asm ("bfset %0{%1,#1}"
+		: "+od" (*set)
+		: "id" ((_sig - 1) ^ 31)
+		: "cc");
+}
+
+static inline void sigdelset(sigset_t *set, int _sig)
+{
+	asm ("bfclr %0{%1,#1}"
+		: "+od" (*set)
+		: "id" ((_sig - 1) ^ 31)
+		: "cc");
+}
+
+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)
+{
+	int ret;
+	asm ("bfextu %1{%2,#1},%0"
+		: "=d" (ret)
+		: "od" (*set), "id" ((_sig-1) ^ 31)
+		: "cc");
+	return ret;
+}
+
+#define sigismember(set,sig)			\
+	(__builtin_constant_p(sig) ?		\
+	 __const_sigismember(set,sig) :		\
+	 __gen_sigismember(set,sig))
+
+static inline int sigfindinword(unsigned long word)
+{
+	asm ("bfffo %1{#0,#0},%0"
+		: "=d" (word)
+		: "d" (word & -word)
+		: "cc");
+	return word ^ 31;
+}
+
+struct pt_regs;
+extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
+
+#else
+
+#undef __HAVE_ARCH_SIG_BITOPS
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#endif /* __uClinux__ */
+#endif /* __KERNEL__ */
+
+#endif /* _M68K_SIGNAL_H */
diff --git a/arch/m68k/include/asm/signal_mm.h b/arch/m68k/include/asm/signal_mm.h
deleted file mode 100644
index 3db8a81..0000000
--- a/arch/m68k/include/asm/signal_mm.h
+++ /dev/null
@@ -1,206 +0,0 @@
-#ifndef _M68K_SIGNAL_H
-#define _M68K_SIGNAL_H
-
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-
-#define _NSIG		64
-#define _NSIG_BPW	32
-#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t;		/* at least 32 bits */
-
-typedef struct {
-	unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG		32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP		 1
-#define SIGINT		 2
-#define SIGQUIT		 3
-#define SIGILL		 4
-#define SIGTRAP		 5
-#define SIGABRT		 6
-#define SIGIOT		 6
-#define SIGBUS		 7
-#define SIGFPE		 8
-#define SIGKILL		 9
-#define SIGUSR1		10
-#define SIGSEGV		11
-#define SIGUSR2		12
-#define SIGPIPE		13
-#define SIGALRM		14
-#define SIGTERM		15
-#define SIGSTKFLT	16
-#define SIGCHLD		17
-#define SIGCONT		18
-#define SIGSTOP		19
-#define SIGTSTP		20
-#define SIGTTIN		21
-#define SIGTTOU		22
-#define SIGURG		23
-#define SIGXCPU		24
-#define SIGXFSZ		25
-#define SIGVTALRM	26
-#define SIGPROF		27
-#define SIGWINCH	28
-#define SIGIO		29
-#define SIGPOLL		SIGIO
-/*
-#define SIGLOST		29
-*/
-#define SIGPWR		30
-#define SIGSYS		31
-#define	SIGUNUSED	31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN	32
-#define SIGRTMAX	_NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK	1
-#define SS_DISABLE	2
-
-#define MINSIGSTKSZ	2048
-#define SIGSTKSZ	8192
-
-#include <asm-generic/signal.h>
-
-#ifdef __KERNEL__
-struct old_sigaction {
-	__sighandler_t sa_handler;
-	old_sigset_t sa_mask;
-	unsigned long sa_flags;
-	__sigrestore_t sa_restorer;
-};
-
-struct sigaction {
-	__sighandler_t sa_handler;
-	unsigned long sa_flags;
-	__sigrestore_t sa_restorer;
-	sigset_t sa_mask;		/* mask last for extensibility */
-};
-
-struct k_sigaction {
-	struct sigaction sa;
-};
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-	union {
-	  __sighandler_t _sa_handler;
-	  void (*_sa_sigaction)(int, struct siginfo *, void *);
-	} _u;
-	sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-};
-
-#define sa_handler	_u._sa_handler
-#define sa_sigaction	_u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-	void __user *ss_sp;
-	int ss_flags;
-	size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-#include <asm/sigcontext.h>
-
-#define __HAVE_ARCH_SIG_BITOPS
-
-static inline void sigaddset(sigset_t *set, int _sig)
-{
-	asm ("bfset %0{%1,#1}"
-		: "+od" (*set)
-		: "id" ((_sig - 1) ^ 31)
-		: "cc");
-}
-
-static inline void sigdelset(sigset_t *set, int _sig)
-{
-	asm ("bfclr %0{%1,#1}"
-		: "+od" (*set)
-		: "id" ((_sig - 1) ^ 31)
-		: "cc");
-}
-
-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)
-{
-	int ret;
-	asm ("bfextu %1{%2,#1},%0"
-		: "=d" (ret)
-		: "od" (*set), "id" ((_sig-1) ^ 31)
-		: "cc");
-	return ret;
-}
-
-#define sigismember(set,sig)			\
-	(__builtin_constant_p(sig) ?		\
-	 __const_sigismember(set,sig) :		\
-	 __gen_sigismember(set,sig))
-
-static inline int sigfindinword(unsigned long word)
-{
-	asm ("bfffo %1{#0,#0},%0"
-		: "=d" (word)
-		: "d" (word & -word)
-		: "cc");
-	return word ^ 31;
-}
-
-struct pt_regs;
-extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68K_SIGNAL_H */
diff --git a/arch/m68k/include/asm/signal_no.h b/arch/m68k/include/asm/signal_no.h
deleted file mode 100644
index 216c08b..0000000
--- a/arch/m68k/include/asm/signal_no.h
+++ /dev/null
@@ -1,159 +0,0 @@
-#ifndef _M68KNOMMU_SIGNAL_H
-#define _M68KNOMMU_SIGNAL_H
-
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-
-#define _NSIG		64
-#define _NSIG_BPW	32
-#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t;		/* at least 32 bits */
-
-typedef struct {
-	unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG		32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP		 1
-#define SIGINT		 2
-#define SIGQUIT		 3
-#define SIGILL		 4
-#define SIGTRAP		 5
-#define SIGABRT		 6
-#define SIGIOT		 6
-#define SIGBUS		 7
-#define SIGFPE		 8
-#define SIGKILL		 9
-#define SIGUSR1		10
-#define SIGSEGV		11
-#define SIGUSR2		12
-#define SIGPIPE		13
-#define SIGALRM		14
-#define SIGTERM		15
-#define SIGSTKFLT	16
-#define SIGCHLD		17
-#define SIGCONT		18
-#define SIGSTOP		19
-#define SIGTSTP		20
-#define SIGTTIN		21
-#define SIGTTOU		22
-#define SIGURG		23
-#define SIGXCPU		24
-#define SIGXFSZ		25
-#define SIGVTALRM	26
-#define SIGPROF		27
-#define SIGWINCH	28
-#define SIGIO		29
-#define SIGPOLL		SIGIO
-/*
-#define SIGLOST		29
-*/
-#define SIGPWR		30
-#define SIGSYS		31
-#define	SIGUNUSED	31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN	32
-#define SIGRTMAX	_NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK	1
-#define SS_DISABLE	2
-
-#define MINSIGSTKSZ	2048
-#define SIGSTKSZ	8192
-
-#include <asm-generic/signal.h>
-
-#ifdef __KERNEL__
-struct old_sigaction {
-	__sighandler_t sa_handler;
-	old_sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-};
-
-struct sigaction {
-	__sighandler_t sa_handler;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-	sigset_t sa_mask;		/* mask last for extensibility */
-};
-
-struct k_sigaction {
-	struct sigaction sa;
-};
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-	union {
-	  __sighandler_t _sa_handler;
-	  void (*_sa_sigaction)(int, struct siginfo *, void *);
-	} _u;
-	sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-};
-
-#define sa_handler	_u._sa_handler
-#define sa_sigaction	_u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-	void *ss_sp;
-	int ss_flags;
-	size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
-#include <asm/sigcontext.h>
-#undef __HAVE_ARCH_SIG_BITOPS
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68KNOMMU_SIGNAL_H */
diff --git a/arch/m68k/include/asm/swab.h b/arch/m68k/include/asm/swab.h
index 7d7dde1..9e3054e 100644
--- a/arch/m68k/include/asm/swab.h
+++ b/arch/m68k/include/asm/swab.h
@@ -1,5 +1,27 @@
-#ifdef __uClinux__
-#include "swab_no.h"
-#else
-#include "swab_mm.h"
+#ifndef _M68K_SWAB_H
+#define _M68K_SWAB_H
+
+#include <asm/types.h>
+#include <linux/compiler.h>
+
+#define __SWAB_64_THRU_32__
+
+#if defined (__mcfisaaplus__) || defined (__mcfisac__)
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+	__asm__("byterev %0" : "=d" (val) : "0" (val));
+	return val;
+}
+
+#define __arch_swab32 __arch_swab32
+#elif !defined(__uClinux__)
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+	__asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val));
+	return val;
+}
+#define __arch_swab32 __arch_swab32
 #endif
+
+#endif /* _M68K_SWAB_H */
diff --git a/arch/m68k/include/asm/swab_mm.h b/arch/m68k/include/asm/swab_mm.h
deleted file mode 100644
index 7221e30..0000000
--- a/arch/m68k/include/asm/swab_mm.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _M68K_SWAB_H
-#define _M68K_SWAB_H
-
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-#define __SWAB_64_THRU_32__
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
-{
-	__asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val));
-	return val;
-}
-#define __arch_swab32 __arch_swab32
-
-#endif /* _M68K_SWAB_H */
diff --git a/arch/m68k/include/asm/swab_no.h b/arch/m68k/include/asm/swab_no.h
deleted file mode 100644
index e582257..0000000
--- a/arch/m68k/include/asm/swab_no.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _M68KNOMMU_SWAB_H
-#define _M68KNOMMU_SWAB_H
-
-#include <linux/types.h>
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#  define __SWAB_64_THRU_32__
-#endif
-
-#if defined (__mcfisaaplus__) || defined (__mcfisac__)
-static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
-{
-	asm(
-			"byterev %0"
-			: "=d" (val)
-			: "0" (val)
-	   );
-	return val;
-}
-
-#define __arch_swab32 __arch_swab32
-#endif
-
-#endif /* _M68KNOMMU_SWAB_H */
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index df1d9d4..3c19027 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -1,5 +1,372 @@
-#ifdef __uClinux__
-#include "unistd_no.h"
-#else
-#include "unistd_mm.h"
-#endif
+#ifndef _ASM_M68K_UNISTD_H_
+#define _ASM_M68K_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall	  0
+#define __NR_exit		  1
+#define __NR_fork		  2
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+#define __NR_waitpid		  7
+#define __NR_creat		  8
+#define __NR_link		  9
+#define __NR_unlink		 10
+#define __NR_execve		 11
+#define __NR_chdir		 12
+#define __NR_time		 13
+#define __NR_mknod		 14
+#define __NR_chmod		 15
+#define __NR_chown		 16
+#define __NR_break		 17
+#define __NR_oldstat		 18
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+#define __NR_umount		 22
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+#define __NR_oldfstat		 28
+#define __NR_pause		 29
+#define __NR_utime		 30
+#define __NR_stty		 31
+#define __NR_gtty		 32
+#define __NR_access		 33
+#define __NR_nice		 34
+#define __NR_ftime		 35
+#define __NR_sync		 36
+#define __NR_kill		 37
+#define __NR_rename		 38
+#define __NR_mkdir		 39
+#define __NR_rmdir		 40
+#define __NR_dup		 41
+#define __NR_pipe		 42
+#define __NR_times		 43
+#define __NR_prof		 44
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+#define __NR_signal		 48
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_umount2		 52
+#define __NR_lock		 53
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+#define __NR_mpx		 56
+#define __NR_setpgid		 57
+#define __NR_ulimit		 58
+#define __NR_oldolduname	 59
+#define __NR_umask		 60
+#define __NR_chroot		 61
+#define __NR_ustat		 62
+#define __NR_dup2		 63
+#define __NR_getppid		 64
+#define __NR_getpgrp		 65
+#define __NR_setsid		 66
+#define __NR_sigaction		 67
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+#define __NR_sigsuspend		 72
+#define __NR_sigpending		 73
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+#define __NR_getrlimit		 76
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+#define __NR_select		 82
+#define __NR_symlink		 83
+#define __NR_oldlstat		 84
+#define __NR_readlink		 85
+#define __NR_uselib		 86
+#define __NR_swapon		 87
+#define __NR_reboot		 88
+#define __NR_readdir		 89
+#define __NR_mmap		 90
+#define __NR_munmap		 91
+#define __NR_truncate		 92
+#define __NR_ftruncate		 93
+#define __NR_fchmod		 94
+#define __NR_fchown		 95
+#define __NR_getpriority	 96
+#define __NR_setpriority	 97
+#define __NR_profil		 98
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+#define __NR_ioperm		101
+#define __NR_socketcall		102
+#define __NR_syslog		103
+#define __NR_setitimer		104
+#define __NR_getitimer		105
+#define __NR_stat		106
+#define __NR_lstat		107
+#define __NR_fstat		108
+#define __NR_olduname		109
+#define __NR_iopl		/* 110 */ not supported
+#define __NR_vhangup		111
+#define __NR_idle		/* 112 */ Obsolete
+#define __NR_vm86		/* 113 */ not supported
+#define __NR_wait4		114
+#define __NR_swapoff		115
+#define __NR_sysinfo		116
+#define __NR_ipc		117
+#define __NR_fsync		118
+#define __NR_sigreturn		119
+#define __NR_clone		120
+#define __NR_setdomainname	121
+#define __NR_uname		122
+#define __NR_cacheflush		123
+#define __NR_adjtimex		124
+#define __NR_mprotect		125
+#define __NR_sigprocmask	126
+#define __NR_create_module	127
+#define __NR_init_module	128
+#define __NR_delete_module	129
+#define __NR_get_kernel_syms	130
+#define __NR_quotactl		131
+#define __NR_getpgid		132
+#define __NR_fchdir		133
+#define __NR_bdflush		134
+#define __NR_sysfs		135
+#define __NR_personality	136
+#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define __NR_setfsuid		138
+#define __NR_setfsgid		139
+#define __NR__llseek		140
+#define __NR_getdents		141
+#define __NR__newselect		142
+#define __NR_flock		143
+#define __NR_msync		144
+#define __NR_readv		145
+#define __NR_writev		146
+#define __NR_getsid		147
+#define __NR_fdatasync		148
+#define __NR__sysctl		149
+#define __NR_mlock		150
+#define __NR_munlock		151
+#define __NR_mlockall		152
+#define __NR_munlockall		153
+#define __NR_sched_setparam		154
+#define __NR_sched_getparam		155
+#define __NR_sched_setscheduler		156
+#define __NR_sched_getscheduler		157
+#define __NR_sched_yield		158
+#define __NR_sched_get_priority_max	159
+#define __NR_sched_get_priority_min	160
+#define __NR_sched_rr_get_interval	161
+#define __NR_nanosleep		162
+#define __NR_mremap		163
+#define __NR_setresuid		164
+#define __NR_getresuid		165
+#define __NR_getpagesize	166
+#define __NR_query_module	167
+#define __NR_poll		168
+#define __NR_nfsservctl		169
+#define __NR_setresgid		170
+#define __NR_getresgid		171
+#define __NR_prctl		172
+#define __NR_rt_sigreturn	173
+#define __NR_rt_sigaction	174
+#define __NR_rt_sigprocmask	175
+#define __NR_rt_sigpending	176
+#define __NR_rt_sigtimedwait	177
+#define __NR_rt_sigqueueinfo	178
+#define __NR_rt_sigsuspend	179
+#define __NR_pread64		180
+#define __NR_pwrite64		181
+#define __NR_lchown		182
+#define __NR_getcwd		183
+#define __NR_capget		184
+#define __NR_capset		185
+#define __NR_sigaltstack	186
+#define __NR_sendfile		187
+#define __NR_getpmsg		188	/* some people actually want streams */
+#define __NR_putpmsg		189	/* some people actually want streams */
+#define __NR_vfork		190
+#define __NR_ugetrlimit		191
+#define __NR_mmap2		192
+#define __NR_truncate64		193
+#define __NR_ftruncate64	194
+#define __NR_stat64		195
+#define __NR_lstat64		196
+#define __NR_fstat64		197
+#define __NR_chown32		198
+#define __NR_getuid32		199
+#define __NR_getgid32		200
+#define __NR_geteuid32		201
+#define __NR_getegid32		202
+#define __NR_setreuid32		203
+#define __NR_setregid32		204
+#define __NR_getgroups32	205
+#define __NR_setgroups32	206
+#define __NR_fchown32		207
+#define __NR_setresuid32	208
+#define __NR_getresuid32	209
+#define __NR_setresgid32	210
+#define __NR_getresgid32	211
+#define __NR_lchown32		212
+#define __NR_setuid32		213
+#define __NR_setgid32		214
+#define __NR_setfsuid32		215
+#define __NR_setfsgid32		216
+#define __NR_pivot_root		217
+#define __NR_getdents64		220
+#define __NR_gettid		221
+#define __NR_tkill		222
+#define __NR_setxattr		223
+#define __NR_lsetxattr		224
+#define __NR_fsetxattr		225
+#define __NR_getxattr		226
+#define __NR_lgetxattr		227
+#define __NR_fgetxattr		228
+#define __NR_listxattr		229
+#define __NR_llistxattr		230
+#define __NR_flistxattr		231
+#define __NR_removexattr	232
+#define __NR_lremovexattr	233
+#define __NR_fremovexattr	234
+#define __NR_futex		235
+#define __NR_sendfile64		236
+#define __NR_mincore		237
+#define __NR_madvise		238
+#define __NR_fcntl64		239
+#define __NR_readahead		240
+#define __NR_io_setup		241
+#define __NR_io_destroy		242
+#define __NR_io_getevents	243
+#define __NR_io_submit		244
+#define __NR_io_cancel		245
+#define __NR_fadvise64		246
+#define __NR_exit_group		247
+#define __NR_lookup_dcookie	248
+#define __NR_epoll_create	249
+#define __NR_epoll_ctl		250
+#define __NR_epoll_wait		251
+#define __NR_remap_file_pages	252
+#define __NR_set_tid_address	253
+#define __NR_timer_create	254
+#define __NR_timer_settime	255
+#define __NR_timer_gettime	256
+#define __NR_timer_getoverrun	257
+#define __NR_timer_delete	258
+#define __NR_clock_settime	259
+#define __NR_clock_gettime	260
+#define __NR_clock_getres	261
+#define __NR_clock_nanosleep	262
+#define __NR_statfs64		263
+#define __NR_fstatfs64		264
+#define __NR_tgkill		265
+#define __NR_utimes		266
+#define __NR_fadvise64_64	267
+#define __NR_mbind		268
+#define __NR_get_mempolicy	269
+#define __NR_set_mempolicy	270
+#define __NR_mq_open		271
+#define __NR_mq_unlink		272
+#define __NR_mq_timedsend	273
+#define __NR_mq_timedreceive	274
+#define __NR_mq_notify		275
+#define __NR_mq_getsetattr	276
+#define __NR_waitid		277
+#define __NR_vserver		278
+#define __NR_add_key		279
+#define __NR_request_key	280
+#define __NR_keyctl		281
+#define __NR_ioprio_set		282
+#define __NR_ioprio_get		283
+#define __NR_inotify_init	284
+#define __NR_inotify_add_watch	285
+#define __NR_inotify_rm_watch	286
+#define __NR_migrate_pages	287
+#define __NR_openat		288
+#define __NR_mkdirat		289
+#define __NR_mknodat		290
+#define __NR_fchownat		291
+#define __NR_futimesat		292
+#define __NR_fstatat64		293
+#define __NR_unlinkat		294
+#define __NR_renameat		295
+#define __NR_linkat		296
+#define __NR_symlinkat		297
+#define __NR_readlinkat		298
+#define __NR_fchmodat		299
+#define __NR_faccessat		300
+#define __NR_pselect6		301
+#define __NR_ppoll		302
+#define __NR_unshare		303
+#define __NR_set_robust_list	304
+#define __NR_get_robust_list	305
+#define __NR_splice		306
+#define __NR_sync_file_range	307
+#define __NR_tee		308
+#define __NR_vmsplice		309
+#define __NR_move_pages		310
+#define __NR_sched_setaffinity	311
+#define __NR_sched_getaffinity	312
+#define __NR_kexec_load		313
+#define __NR_getcpu		314
+#define __NR_epoll_pwait	315
+#define __NR_utimensat		316
+#define __NR_signalfd		317
+#define __NR_timerfd_create	318
+#define __NR_eventfd		319
+#define __NR_fallocate		320
+#define __NR_timerfd_settime	321
+#define __NR_timerfd_gettime	322
+#define __NR_signalfd4		323
+#define __NR_eventfd2		324
+#define __NR_epoll_create1	325
+#define __NR_dup3		326
+#define __NR_pipe2		327
+#define __NR_inotify_init1	328
+
+#ifdef __KERNEL__
+
+#define NR_syscalls		329
+
+#define __ARCH_WANT_IPC_PARSE_VERSION
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_OLD_STAT
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SGETMASK
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGACTION
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_M68K_UNISTD_H_ */
diff --git a/arch/m68k/include/asm/unistd_mm.h b/arch/m68k/include/asm/unistd_mm.h
deleted file mode 100644
index 3c19027..0000000
--- a/arch/m68k/include/asm/unistd_mm.h
+++ /dev/null
@@ -1,372 +0,0 @@
-#ifndef _ASM_M68K_UNISTD_H_
-#define _ASM_M68K_UNISTD_H_
-
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall	  0
-#define __NR_exit		  1
-#define __NR_fork		  2
-#define __NR_read		  3
-#define __NR_write		  4
-#define __NR_open		  5
-#define __NR_close		  6
-#define __NR_waitpid		  7
-#define __NR_creat		  8
-#define __NR_link		  9
-#define __NR_unlink		 10
-#define __NR_execve		 11
-#define __NR_chdir		 12
-#define __NR_time		 13
-#define __NR_mknod		 14
-#define __NR_chmod		 15
-#define __NR_chown		 16
-#define __NR_break		 17
-#define __NR_oldstat		 18
-#define __NR_lseek		 19
-#define __NR_getpid		 20
-#define __NR_mount		 21
-#define __NR_umount		 22
-#define __NR_setuid		 23
-#define __NR_getuid		 24
-#define __NR_stime		 25
-#define __NR_ptrace		 26
-#define __NR_alarm		 27
-#define __NR_oldfstat		 28
-#define __NR_pause		 29
-#define __NR_utime		 30
-#define __NR_stty		 31
-#define __NR_gtty		 32
-#define __NR_access		 33
-#define __NR_nice		 34
-#define __NR_ftime		 35
-#define __NR_sync		 36
-#define __NR_kill		 37
-#define __NR_rename		 38
-#define __NR_mkdir		 39
-#define __NR_rmdir		 40
-#define __NR_dup		 41
-#define __NR_pipe		 42
-#define __NR_times		 43
-#define __NR_prof		 44
-#define __NR_brk		 45
-#define __NR_setgid		 46
-#define __NR_getgid		 47
-#define __NR_signal		 48
-#define __NR_geteuid		 49
-#define __NR_getegid		 50
-#define __NR_acct		 51
-#define __NR_umount2		 52
-#define __NR_lock		 53
-#define __NR_ioctl		 54
-#define __NR_fcntl		 55
-#define __NR_mpx		 56
-#define __NR_setpgid		 57
-#define __NR_ulimit		 58
-#define __NR_oldolduname	 59
-#define __NR_umask		 60
-#define __NR_chroot		 61
-#define __NR_ustat		 62
-#define __NR_dup2		 63
-#define __NR_getppid		 64
-#define __NR_getpgrp		 65
-#define __NR_setsid		 66
-#define __NR_sigaction		 67
-#define __NR_sgetmask		 68
-#define __NR_ssetmask		 69
-#define __NR_setreuid		 70
-#define __NR_setregid		 71
-#define __NR_sigsuspend		 72
-#define __NR_sigpending		 73
-#define __NR_sethostname	 74
-#define __NR_setrlimit		 75
-#define __NR_getrlimit		 76
-#define __NR_getrusage		 77
-#define __NR_gettimeofday	 78
-#define __NR_settimeofday	 79
-#define __NR_getgroups		 80
-#define __NR_setgroups		 81
-#define __NR_select		 82
-#define __NR_symlink		 83
-#define __NR_oldlstat		 84
-#define __NR_readlink		 85
-#define __NR_uselib		 86
-#define __NR_swapon		 87
-#define __NR_reboot		 88
-#define __NR_readdir		 89
-#define __NR_mmap		 90
-#define __NR_munmap		 91
-#define __NR_truncate		 92
-#define __NR_ftruncate		 93
-#define __NR_fchmod		 94
-#define __NR_fchown		 95
-#define __NR_getpriority	 96
-#define __NR_setpriority	 97
-#define __NR_profil		 98
-#define __NR_statfs		 99
-#define __NR_fstatfs		100
-#define __NR_ioperm		101
-#define __NR_socketcall		102
-#define __NR_syslog		103
-#define __NR_setitimer		104
-#define __NR_getitimer		105
-#define __NR_stat		106
-#define __NR_lstat		107
-#define __NR_fstat		108
-#define __NR_olduname		109
-#define __NR_iopl		/* 110 */ not supported
-#define __NR_vhangup		111
-#define __NR_idle		/* 112 */ Obsolete
-#define __NR_vm86		/* 113 */ not supported
-#define __NR_wait4		114
-#define __NR_swapoff		115
-#define __NR_sysinfo		116
-#define __NR_ipc		117
-#define __NR_fsync		118
-#define __NR_sigreturn		119
-#define __NR_clone		120
-#define __NR_setdomainname	121
-#define __NR_uname		122
-#define __NR_cacheflush		123
-#define __NR_adjtimex		124
-#define __NR_mprotect		125
-#define __NR_sigprocmask	126
-#define __NR_create_module	127
-#define __NR_init_module	128
-#define __NR_delete_module	129
-#define __NR_get_kernel_syms	130
-#define __NR_quotactl		131
-#define __NR_getpgid		132
-#define __NR_fchdir		133
-#define __NR_bdflush		134
-#define __NR_sysfs		135
-#define __NR_personality	136
-#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
-#define __NR_setfsuid		138
-#define __NR_setfsgid		139
-#define __NR__llseek		140
-#define __NR_getdents		141
-#define __NR__newselect		142
-#define __NR_flock		143
-#define __NR_msync		144
-#define __NR_readv		145
-#define __NR_writev		146
-#define __NR_getsid		147
-#define __NR_fdatasync		148
-#define __NR__sysctl		149
-#define __NR_mlock		150
-#define __NR_munlock		151
-#define __NR_mlockall		152
-#define __NR_munlockall		153
-#define __NR_sched_setparam		154
-#define __NR_sched_getparam		155
-#define __NR_sched_setscheduler		156
-#define __NR_sched_getscheduler		157
-#define __NR_sched_yield		158
-#define __NR_sched_get_priority_max	159
-#define __NR_sched_get_priority_min	160
-#define __NR_sched_rr_get_interval	161
-#define __NR_nanosleep		162
-#define __NR_mremap		163
-#define __NR_setresuid		164
-#define __NR_getresuid		165
-#define __NR_getpagesize	166
-#define __NR_query_module	167
-#define __NR_poll		168
-#define __NR_nfsservctl		169
-#define __NR_setresgid		170
-#define __NR_getresgid		171
-#define __NR_prctl		172
-#define __NR_rt_sigreturn	173
-#define __NR_rt_sigaction	174
-#define __NR_rt_sigprocmask	175
-#define __NR_rt_sigpending	176
-#define __NR_rt_sigtimedwait	177
-#define __NR_rt_sigqueueinfo	178
-#define __NR_rt_sigsuspend	179
-#define __NR_pread64		180
-#define __NR_pwrite64		181
-#define __NR_lchown		182
-#define __NR_getcwd		183
-#define __NR_capget		184
-#define __NR_capset		185
-#define __NR_sigaltstack	186
-#define __NR_sendfile		187
-#define __NR_getpmsg		188	/* some people actually want streams */
-#define __NR_putpmsg		189	/* some people actually want streams */
-#define __NR_vfork		190
-#define __NR_ugetrlimit		191
-#define __NR_mmap2		192
-#define __NR_truncate64		193
-#define __NR_ftruncate64	194
-#define __NR_stat64		195
-#define __NR_lstat64		196
-#define __NR_fstat64		197
-#define __NR_chown32		198
-#define __NR_getuid32		199
-#define __NR_getgid32		200
-#define __NR_geteuid32		201
-#define __NR_getegid32		202
-#define __NR_setreuid32		203
-#define __NR_setregid32		204
-#define __NR_getgroups32	205
-#define __NR_setgroups32	206
-#define __NR_fchown32		207
-#define __NR_setresuid32	208
-#define __NR_getresuid32	209
-#define __NR_setresgid32	210
-#define __NR_getresgid32	211
-#define __NR_lchown32		212
-#define __NR_setuid32		213
-#define __NR_setgid32		214
-#define __NR_setfsuid32		215
-#define __NR_setfsgid32		216
-#define __NR_pivot_root		217
-#define __NR_getdents64		220
-#define __NR_gettid		221
-#define __NR_tkill		222
-#define __NR_setxattr		223
-#define __NR_lsetxattr		224
-#define __NR_fsetxattr		225
-#define __NR_getxattr		226
-#define __NR_lgetxattr		227
-#define __NR_fgetxattr		228
-#define __NR_listxattr		229
-#define __NR_llistxattr		230
-#define __NR_flistxattr		231
-#define __NR_removexattr	232
-#define __NR_lremovexattr	233
-#define __NR_fremovexattr	234
-#define __NR_futex		235
-#define __NR_sendfile64		236
-#define __NR_mincore		237
-#define __NR_madvise		238
-#define __NR_fcntl64		239
-#define __NR_readahead		240
-#define __NR_io_setup		241
-#define __NR_io_destroy		242
-#define __NR_io_getevents	243
-#define __NR_io_submit		244
-#define __NR_io_cancel		245
-#define __NR_fadvise64		246
-#define __NR_exit_group		247
-#define __NR_lookup_dcookie	248
-#define __NR_epoll_create	249
-#define __NR_epoll_ctl		250
-#define __NR_epoll_wait		251
-#define __NR_remap_file_pages	252
-#define __NR_set_tid_address	253
-#define __NR_timer_create	254
-#define __NR_timer_settime	255
-#define __NR_timer_gettime	256
-#define __NR_timer_getoverrun	257
-#define __NR_timer_delete	258
-#define __NR_clock_settime	259
-#define __NR_clock_gettime	260
-#define __NR_clock_getres	261
-#define __NR_clock_nanosleep	262
-#define __NR_statfs64		263
-#define __NR_fstatfs64		264
-#define __NR_tgkill		265
-#define __NR_utimes		266
-#define __NR_fadvise64_64	267
-#define __NR_mbind		268
-#define __NR_get_mempolicy	269
-#define __NR_set_mempolicy	270
-#define __NR_mq_open		271
-#define __NR_mq_unlink		272
-#define __NR_mq_timedsend	273
-#define __NR_mq_timedreceive	274
-#define __NR_mq_notify		275
-#define __NR_mq_getsetattr	276
-#define __NR_waitid		277
-#define __NR_vserver		278
-#define __NR_add_key		279
-#define __NR_request_key	280
-#define __NR_keyctl		281
-#define __NR_ioprio_set		282
-#define __NR_ioprio_get		283
-#define __NR_inotify_init	284
-#define __NR_inotify_add_watch	285
-#define __NR_inotify_rm_watch	286
-#define __NR_migrate_pages	287
-#define __NR_openat		288
-#define __NR_mkdirat		289
-#define __NR_mknodat		290
-#define __NR_fchownat		291
-#define __NR_futimesat		292
-#define __NR_fstatat64		293
-#define __NR_unlinkat		294
-#define __NR_renameat		295
-#define __NR_linkat		296
-#define __NR_symlinkat		297
-#define __NR_readlinkat		298
-#define __NR_fchmodat		299
-#define __NR_faccessat		300
-#define __NR_pselect6		301
-#define __NR_ppoll		302
-#define __NR_unshare		303
-#define __NR_set_robust_list	304
-#define __NR_get_robust_list	305
-#define __NR_splice		306
-#define __NR_sync_file_range	307
-#define __NR_tee		308
-#define __NR_vmsplice		309
-#define __NR_move_pages		310
-#define __NR_sched_setaffinity	311
-#define __NR_sched_getaffinity	312
-#define __NR_kexec_load		313
-#define __NR_getcpu		314
-#define __NR_epoll_pwait	315
-#define __NR_utimensat		316
-#define __NR_signalfd		317
-#define __NR_timerfd_create	318
-#define __NR_eventfd		319
-#define __NR_fallocate		320
-#define __NR_timerfd_settime	321
-#define __NR_timerfd_gettime	322
-#define __NR_signalfd4		323
-#define __NR_eventfd2		324
-#define __NR_epoll_create1	325
-#define __NR_dup3		326
-#define __NR_pipe2		327
-#define __NR_inotify_init1	328
-
-#ifdef __KERNEL__
-
-#define NR_syscalls		329
-
-#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_OLD_STAT
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_RT_SIGACTION
-
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_M68K_UNISTD_H_ */
diff --git a/arch/m68k/include/asm/unistd_no.h b/arch/m68k/include/asm/unistd_no.h
deleted file mode 100644
index b034a2f..0000000
--- a/arch/m68k/include/asm/unistd_no.h
+++ /dev/null
@@ -1,372 +0,0 @@
-#ifndef _ASM_M68K_UNISTD_H_
-#define _ASM_M68K_UNISTD_H_
-
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall      0
-#define __NR_exit		  1
-#define __NR_fork		  2
-#define __NR_read		  3
-#define __NR_write		  4
-#define __NR_open		  5
-#define __NR_close		  6
-#define __NR_waitpid		  7
-#define __NR_creat		  8
-#define __NR_link		  9
-#define __NR_unlink		 10
-#define __NR_execve		 11
-#define __NR_chdir		 12
-#define __NR_time		 13
-#define __NR_mknod		 14
-#define __NR_chmod		 15
-#define __NR_chown		 16
-#define __NR_break		 17
-#define __NR_oldstat		 18
-#define __NR_lseek		 19
-#define __NR_getpid		 20
-#define __NR_mount		 21
-#define __NR_umount		 22
-#define __NR_setuid		 23
-#define __NR_getuid		 24
-#define __NR_stime		 25
-#define __NR_ptrace		 26
-#define __NR_alarm		 27
-#define __NR_oldfstat		 28
-#define __NR_pause		 29
-#define __NR_utime		 30
-#define __NR_stty		 31
-#define __NR_gtty		 32
-#define __NR_access		 33
-#define __NR_nice		 34
-#define __NR_ftime		 35
-#define __NR_sync		 36
-#define __NR_kill		 37
-#define __NR_rename		 38
-#define __NR_mkdir		 39
-#define __NR_rmdir		 40
-#define __NR_dup		 41
-#define __NR_pipe		 42
-#define __NR_times		 43
-#define __NR_prof		 44
-#define __NR_brk		 45
-#define __NR_setgid		 46
-#define __NR_getgid		 47
-#define __NR_signal		 48
-#define __NR_geteuid		 49
-#define __NR_getegid		 50
-#define __NR_acct		 51
-#define __NR_umount2		 52
-#define __NR_lock		 53
-#define __NR_ioctl		 54
-#define __NR_fcntl		 55
-#define __NR_mpx		 56
-#define __NR_setpgid		 57
-#define __NR_ulimit		 58
-#define __NR_oldolduname	 59
-#define __NR_umask		 60
-#define __NR_chroot		 61
-#define __NR_ustat		 62
-#define __NR_dup2		 63
-#define __NR_getppid		 64
-#define __NR_getpgrp		 65
-#define __NR_setsid		 66
-#define __NR_sigaction		 67
-#define __NR_sgetmask		 68
-#define __NR_ssetmask		 69
-#define __NR_setreuid		 70
-#define __NR_setregid		 71
-#define __NR_sigsuspend		 72
-#define __NR_sigpending		 73
-#define __NR_sethostname	 74
-#define __NR_setrlimit		 75
-#define __NR_getrlimit		 76
-#define __NR_getrusage		 77
-#define __NR_gettimeofday	 78
-#define __NR_settimeofday	 79
-#define __NR_getgroups		 80
-#define __NR_setgroups		 81
-#define __NR_select		 82
-#define __NR_symlink		 83
-#define __NR_oldlstat		 84
-#define __NR_readlink		 85
-#define __NR_uselib		 86
-#define __NR_swapon		 87
-#define __NR_reboot		 88
-#define __NR_readdir		 89
-#define __NR_mmap		 90
-#define __NR_munmap		 91
-#define __NR_truncate		 92
-#define __NR_ftruncate		 93
-#define __NR_fchmod		 94
-#define __NR_fchown		 95
-#define __NR_getpriority	 96
-#define __NR_setpriority	 97
-#define __NR_profil		 98
-#define __NR_statfs		 99
-#define __NR_fstatfs		100
-#define __NR_ioperm		101
-#define __NR_socketcall		102
-#define __NR_syslog		103
-#define __NR_setitimer		104
-#define __NR_getitimer		105
-#define __NR_stat		106
-#define __NR_lstat		107
-#define __NR_fstat		108
-#define __NR_olduname		109
-#define __NR_iopl		/* 110 */ not supported
-#define __NR_vhangup		111
-#define __NR_idle		/* 112 */ Obsolete
-#define __NR_vm86		/* 113 */ not supported
-#define __NR_wait4		114
-#define __NR_swapoff		115
-#define __NR_sysinfo		116
-#define __NR_ipc		117
-#define __NR_fsync		118
-#define __NR_sigreturn		119
-#define __NR_clone		120
-#define __NR_setdomainname	121
-#define __NR_uname		122
-#define __NR_cacheflush		123
-#define __NR_adjtimex		124
-#define __NR_mprotect		125
-#define __NR_sigprocmask	126
-#define __NR_create_module	127
-#define __NR_init_module	128
-#define __NR_delete_module	129
-#define __NR_get_kernel_syms	130
-#define __NR_quotactl		131
-#define __NR_getpgid		132
-#define __NR_fchdir		133
-#define __NR_bdflush		134
-#define __NR_sysfs		135
-#define __NR_personality	136
-#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
-#define __NR_setfsuid		138
-#define __NR_setfsgid		139
-#define __NR__llseek		140
-#define __NR_getdents		141
-#define __NR__newselect		142
-#define __NR_flock		143
-#define __NR_msync		144
-#define __NR_readv		145
-#define __NR_writev		146
-#define __NR_getsid		147
-#define __NR_fdatasync		148
-#define __NR__sysctl		149
-#define __NR_mlock		150
-#define __NR_munlock		151
-#define __NR_mlockall		152
-#define __NR_munlockall		153
-#define __NR_sched_setparam		154
-#define __NR_sched_getparam		155
-#define __NR_sched_setscheduler		156
-#define __NR_sched_getscheduler		157
-#define __NR_sched_yield		158
-#define __NR_sched_get_priority_max	159
-#define __NR_sched_get_priority_min	160
-#define __NR_sched_rr_get_interval	161
-#define __NR_nanosleep		162
-#define __NR_mremap		163
-#define __NR_setresuid		164
-#define __NR_getresuid		165
-#define __NR_getpagesize	166
-#define __NR_query_module	167
-#define __NR_poll		168
-#define __NR_nfsservctl		169
-#define __NR_setresgid		170
-#define __NR_getresgid		171
-#define __NR_prctl		172
-#define __NR_rt_sigreturn	173
-#define __NR_rt_sigaction	174
-#define __NR_rt_sigprocmask	175
-#define __NR_rt_sigpending	176
-#define __NR_rt_sigtimedwait	177
-#define __NR_rt_sigqueueinfo	178
-#define __NR_rt_sigsuspend	179
-#define __NR_pread64		180
-#define __NR_pwrite64		181
-#define __NR_lchown		182
-#define __NR_getcwd		183
-#define __NR_capget		184
-#define __NR_capset		185
-#define __NR_sigaltstack	186
-#define __NR_sendfile		187
-#define __NR_getpmsg		188	/* some people actually want streams */
-#define __NR_putpmsg		189	/* some people actually want streams */
-#define __NR_vfork		190
-#define __NR_ugetrlimit		191
-#define __NR_mmap2		192
-#define __NR_truncate64		193
-#define __NR_ftruncate64	194
-#define __NR_stat64		195
-#define __NR_lstat64		196
-#define __NR_fstat64		197
-#define __NR_chown32		198
-#define __NR_getuid32		199
-#define __NR_getgid32		200
-#define __NR_geteuid32		201
-#define __NR_getegid32		202
-#define __NR_setreuid32		203
-#define __NR_setregid32		204
-#define __NR_getgroups32	205
-#define __NR_setgroups32	206
-#define __NR_fchown32		207
-#define __NR_setresuid32	208
-#define __NR_getresuid32	209
-#define __NR_setresgid32	210
-#define __NR_getresgid32	211
-#define __NR_lchown32		212
-#define __NR_setuid32		213
-#define __NR_setgid32		214
-#define __NR_setfsuid32		215
-#define __NR_setfsgid32		216
-#define __NR_pivot_root		217
-#define __NR_getdents64		220
-#define __NR_gettid		221
-#define __NR_tkill		222
-#define __NR_setxattr		223
-#define __NR_lsetxattr		224
-#define __NR_fsetxattr		225
-#define __NR_getxattr		226
-#define __NR_lgetxattr		227
-#define __NR_fgetxattr		228
-#define __NR_listxattr		229
-#define __NR_llistxattr		230
-#define __NR_flistxattr		231
-#define __NR_removexattr	232
-#define __NR_lremovexattr	233
-#define __NR_fremovexattr	234
-#define __NR_futex		235
-#define __NR_sendfile64		236
-#define __NR_mincore		237
-#define __NR_madvise		238
-#define __NR_fcntl64		239
-#define __NR_readahead		240
-#define __NR_io_setup		241
-#define __NR_io_destroy		242
-#define __NR_io_getevents	243
-#define __NR_io_submit		244
-#define __NR_io_cancel		245
-#define __NR_fadvise64		246
-#define __NR_exit_group		247
-#define __NR_lookup_dcookie	248
-#define __NR_epoll_create	249
-#define __NR_epoll_ctl		250
-#define __NR_epoll_wait		251
-#define __NR_remap_file_pages	252
-#define __NR_set_tid_address	253
-#define __NR_timer_create	254
-#define __NR_timer_settime	255
-#define __NR_timer_gettime	256
-#define __NR_timer_getoverrun	257
-#define __NR_timer_delete	258
-#define __NR_clock_settime	259
-#define __NR_clock_gettime	260
-#define __NR_clock_getres	261
-#define __NR_clock_nanosleep	262
-#define __NR_statfs64		263
-#define __NR_fstatfs64		264
-#define __NR_tgkill		265
-#define __NR_utimes		266
-#define __NR_fadvise64_64	267
-#define __NR_mbind		268
-#define __NR_get_mempolicy	269
-#define __NR_set_mempolicy	270
-#define __NR_mq_open		271
-#define __NR_mq_unlink		272
-#define __NR_mq_timedsend	273
-#define __NR_mq_timedreceive	274
-#define __NR_mq_notify		275
-#define __NR_mq_getsetattr	276
-#define __NR_waitid		277
-#define __NR_vserver		278
-#define __NR_add_key		279
-#define __NR_request_key	280
-#define __NR_keyctl		281
-#define __NR_ioprio_set		282
-#define __NR_ioprio_get		283
-#define __NR_inotify_init	284
-#define __NR_inotify_add_watch	285
-#define __NR_inotify_rm_watch	286
-#define __NR_migrate_pages	287
-#define __NR_openat		288
-#define __NR_mkdirat		289
-#define __NR_mknodat		290
-#define __NR_fchownat		291
-#define __NR_futimesat		292
-#define __NR_fstatat64		293
-#define __NR_unlinkat		294
-#define __NR_renameat		295
-#define __NR_linkat		296
-#define __NR_symlinkat		297
-#define __NR_readlinkat		298
-#define __NR_fchmodat		299
-#define __NR_faccessat		300
-#define __NR_pselect6		301
-#define __NR_ppoll		302
-#define __NR_unshare		303
-#define __NR_set_robust_list	304
-#define __NR_get_robust_list	305
-#define __NR_splice		306
-#define __NR_sync_file_range	307
-#define __NR_tee		308
-#define __NR_vmsplice		309
-#define __NR_move_pages		310
-#define __NR_sched_setaffinity	311
-#define __NR_sched_getaffinity	312
-#define __NR_kexec_load		313
-#define __NR_getcpu		314
-#define __NR_epoll_pwait	315
-#define __NR_utimensat		316
-#define __NR_signalfd		317
-#define __NR_timerfd_create	318
-#define __NR_eventfd		319
-#define __NR_fallocate		320
-#define __NR_timerfd_settime	321
-#define __NR_timerfd_gettime	322
-#define __NR_signalfd4		323
-#define __NR_eventfd2		324
-#define __NR_epoll_create1	325
-#define __NR_dup3		326
-#define __NR_pipe2		327
-#define __NR_inotify_init1	328
-
-#ifdef __KERNEL__
-
-#define NR_syscalls		329
-
-#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_OLD_STAT
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_RT_SIGACTION
-
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_M68K_UNISTD_H_ */
diff --git a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c
index d01a5d2..db90254 100644
--- a/arch/m68knommu/platform/5206e/config.c
+++ b/arch/m68knommu/platform/5206e/config.c
@@ -17,6 +17,7 @@
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfdma.h>
+#include <asm/mcfuart.h>
 
 /***************************************************************************/
 
diff --git a/arch/m68knommu/platform/528x/config.c b/arch/m68knommu/platform/528x/config.c
index 2ffb549..bee526f 100644
--- a/arch/m68knommu/platform/528x/config.c
+++ b/arch/m68knommu/platform/528x/config.c
@@ -24,7 +24,6 @@
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
-#include <asm/mcfqspi.h>
 
 #ifdef CONFIG_MTD_PARTITIONS
 #include <linux/mtd/partitions.h>
@@ -33,233 +32,6 @@
 /***************************************************************************/
 
 void coldfire_reset(void);
-static void coldfire_qspi_cs_control(u8 cs, u8 command);
-
-/***************************************************************************/
-
-#if defined(CONFIG_SPI)
-
-#if defined(CONFIG_WILDFIRE)
-#define SPI_NUM_CHIPSELECTS 	0x02
-#define SPI_PAR_VAL		0x07  /* Enable DIN, DOUT, CLK */
-#define SPI_CS_MASK		0x18
-
-#define FLASH_BLOCKSIZE		(1024*64)
-#define FLASH_NUMBLOCKS		16
-#define FLASH_TYPE		"m25p80"
-
-#define M25P80_CS		0
-#define MMC_CS			1
-
-#ifdef CONFIG_MTD_PARTITIONS
-static struct mtd_partition stm25p_partitions[] = {
-	/* sflash */
-	[0] = {
-		.name = "stm25p80",
-		.offset = 0x00000000,
-		.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS,
-		.mask_flags = 0
-	}
-};
-
-#endif
-
-#elif defined(CONFIG_WILDFIREMOD)
-
-#define SPI_NUM_CHIPSELECTS	0x08
-#define SPI_PAR_VAL		0x07  /* Enable DIN, DOUT, CLK */
-#define SPI_CS_MASK		0x78
-
-#define FLASH_BLOCKSIZE		(1024*64)
-#define FLASH_NUMBLOCKS		64
-#define FLASH_TYPE		"m25p32"
-/* Reserve 1M for the kernel parition */
-#define FLASH_KERNEL_SIZE   (1024 * 1024)
-
-#define M25P80_CS		5
-#define MMC_CS			6
-
-#ifdef CONFIG_MTD_PARTITIONS
-static struct mtd_partition stm25p_partitions[] = {
-	/* sflash */
-	[0] = {
-		.name = "kernel",
-		.offset = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS - FLASH_KERNEL_SIZE,
-		.size = FLASH_KERNEL_SIZE,
-		.mask_flags = 0
-	},
-	[1] = {
-		.name = "image",
-		.offset = 0x00000000,
-		.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS - FLASH_KERNEL_SIZE,
-		.mask_flags = 0
-	},
-	[2] = {
-		.name = "all",
-		.offset = 0x00000000,
-		.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS,
-		.mask_flags = 0
-	}
-};
-#endif
-
-#else
-#define SPI_NUM_CHIPSELECTS 	0x04
-#define SPI_PAR_VAL		0x7F  /* Enable DIN, DOUT, CLK, CS0 - CS4 */
-#endif
-
-#ifdef MMC_CS
-static struct coldfire_spi_chip flash_chip_info = {
-	.mode = SPI_MODE_0,
-	.bits_per_word = 16,
-	.del_cs_to_clk = 17,
-	.del_after_trans = 1,
-	.void_write_data = 0
-};
-
-static struct coldfire_spi_chip mmc_chip_info = {
-	.mode = SPI_MODE_0,
-	.bits_per_word = 16,
-	.del_cs_to_clk = 17,
-	.del_after_trans = 1,
-	.void_write_data = 0xFFFF
-};
-#endif
-
-#ifdef M25P80_CS
-static struct flash_platform_data stm25p80_platform_data = {
-	.name = "ST M25P80 SPI Flash chip",
-#ifdef CONFIG_MTD_PARTITIONS
-	.parts = stm25p_partitions,
-	.nr_parts = sizeof(stm25p_partitions) / sizeof(*stm25p_partitions),
-#endif
-	.type = FLASH_TYPE
-};
-#endif
-
-static struct spi_board_info spi_board_info[] __initdata = {
-#ifdef M25P80_CS
-	{
-		.modalias = "m25p80",
-		.max_speed_hz = 16000000,
-		.bus_num = 1,
-		.chip_select = M25P80_CS,
-		.platform_data = &stm25p80_platform_data,
-		.controller_data = &flash_chip_info
-	},
-#endif
-#ifdef MMC_CS
-	{
-		.modalias = "mmc_spi",
-		.max_speed_hz = 16000000,
-		.bus_num = 1,
-		.chip_select = MMC_CS,
-		.controller_data = &mmc_chip_info
-	}
-#endif
-};
-
-static struct coldfire_spi_master coldfire_master_info = {
-	.bus_num = 1,
-	.num_chipselect = SPI_NUM_CHIPSELECTS,
-	.irq_source = MCF5282_QSPI_IRQ_SOURCE,
-	.irq_vector = MCF5282_QSPI_IRQ_VECTOR,
-	.irq_mask = ((0x01 << MCF5282_QSPI_IRQ_SOURCE) | 0x01),
-	.irq_lp = 0x2B,  /* Level 5 and Priority 3 */
-	.par_val = SPI_PAR_VAL,
-	.cs_control = coldfire_qspi_cs_control,
-};
-
-static struct resource coldfire_spi_resources[] = {
-	[0] = {
-		.name = "qspi-par",
-		.start = MCF5282_QSPI_PAR,
-		.end = MCF5282_QSPI_PAR,
-		.flags = IORESOURCE_MEM
-	},
-
-	[1] = {
-		.name = "qspi-module",
-		.start = MCF5282_QSPI_QMR,
-		.end = MCF5282_QSPI_QMR + 0x18,
-		.flags = IORESOURCE_MEM
-	},
-
-	[2] = {
-		.name = "qspi-int-level",
-		.start = MCF5282_INTC0 + MCFINTC_ICR0 + MCF5282_QSPI_IRQ_SOURCE,
-		.end = MCF5282_INTC0 + MCFINTC_ICR0 + MCF5282_QSPI_IRQ_SOURCE,
-		.flags = IORESOURCE_MEM
-	},
-
-	[3] = {
-		.name = "qspi-int-mask",
-		.start = MCF5282_INTC0 + MCFINTC_IMRL,
-		.end = MCF5282_INTC0 + MCFINTC_IMRL,
-		.flags = IORESOURCE_MEM
-	}
-};
-
-static struct platform_device coldfire_spi = {
-	.name = "spi_coldfire",
-	.id = -1,
-	.resource = coldfire_spi_resources,
-	.num_resources = ARRAY_SIZE(coldfire_spi_resources),
-	.dev = {
-		.platform_data = &coldfire_master_info,
-	}
-};
-
-static void coldfire_qspi_cs_control(u8 cs, u8 command)
-{
-	u8 cs_bit = ((0x01 << cs) << 3) & SPI_CS_MASK;
-
-#if defined(CONFIG_WILDFIRE)
-	u8 cs_mask = ~(((0x01 << cs) << 3) & SPI_CS_MASK);
-#endif
-#if defined(CONFIG_WILDFIREMOD)
-	u8 cs_mask = (cs << 3) & SPI_CS_MASK;
-#endif
-
-	/*
-	 * Don't do anything if the chip select is not
-	 * one of the port qs pins.
-	 */
-	if (command & QSPI_CS_INIT) {
-#if defined(CONFIG_WILDFIRE)
-		MCF5282_GPIO_DDRQS  |= cs_bit;
-		MCF5282_GPIO_PQSPAR &= ~cs_bit;
-#endif
-
-#if defined(CONFIG_WILDFIREMOD)
-		MCF5282_GPIO_DDRQS  |= SPI_CS_MASK;
-		MCF5282_GPIO_PQSPAR &= ~SPI_CS_MASK;
-#endif
-	}
-
-	if (command & QSPI_CS_ASSERT) {
-		MCF5282_GPIO_PORTQS &= ~SPI_CS_MASK;
-		MCF5282_GPIO_PORTQS |= cs_mask;
-	} else if (command & QSPI_CS_DROP) {
-		MCF5282_GPIO_PORTQS |= SPI_CS_MASK;
-	}
-}
-
-static int __init spi_dev_init(void)
-{
-	int retval;
-
-	retval = platform_device_register(&coldfire_spi);
-	if (retval < 0)
-		return retval;
-
-	if (ARRAY_SIZE(spi_board_info))
-		retval = spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
-
-	return retval;
-}
-
-#endif /* CONFIG_SPI */
 
 /***************************************************************************/
 
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e61465a..206cb79 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -238,8 +238,12 @@
 	  This option enables support for MIPS Technologies MIPSsim software
 	  emulator.
 
-config MACH_EMMA
-	bool "NEC EMMA series based machines"
+config NEC_MARKEINS
+	bool "NEC EMMA2RH Mark-eins board"
+	select SOC_EMMA2RH
+	select HW_HAS_PCI
+	help
+	  This enables support for the NEC Electronics Mark-eins boards.
 
 config MACH_VR41XX
 	bool "NEC VR4100 series based machines"
@@ -637,7 +641,6 @@
 
 source "arch/mips/alchemy/Kconfig"
 source "arch/mips/basler/excite/Kconfig"
-source "arch/mips/emma/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/lasat/Kconfig"
 source "arch/mips/pmc-sierra/Kconfig"
@@ -895,6 +898,18 @@
 	bool
 	select SERIAL_RM9000
 
+config SOC_EMMA2RH
+	bool
+	select CEVT_R4K
+	select CSRC_R4K
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_R5500
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+
 config SOC_PNX833X
 	bool
 	select CEVT_R4K
@@ -930,11 +945,6 @@
 config SWAP_IO_SPACE
 	bool
 
-config EMMA2RH
-	bool
-	depends on MARKEINS
-	default y
-
 config SERIAL_RM9000
 	bool
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 21b00e9..22dab2e 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -416,7 +416,7 @@
 #
 # Common NEC EMMAXXX
 #
-core-$(CONFIG_SOC_EMMA)		+= arch/mips/emma/common/
+core-$(CONFIG_SOC_EMMA2RH)	+= arch/mips/emma/common/
 cflags-$(CONFIG_SOC_EMMA2RH)	+= -I$(srctree)/arch/mips/include/asm/mach-emma2rh
 
 #
diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c
index a1e3526..dfbfd7e 100644
--- a/arch/mips/basler/excite/excite_iodev.c
+++ b/arch/mips/basler/excite/excite_iodev.c
@@ -33,8 +33,8 @@
 
 
 static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int);
-static int __init iodev_probe(struct device *);
-static int __exit iodev_remove(struct device *);
+static int __init iodev_probe(struct platform_device *);
+static int __exit iodev_remove(struct platform_device *);
 static int iodev_open(struct inode *, struct file *);
 static int iodev_release(struct inode *, struct file *);
 static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *);
@@ -65,13 +65,13 @@
 	.fops		= &fops
 };
 
-static struct device_driver iodev_driver =
-{
-	.name		= (char *) iodev_name,
-	.bus		= &platform_bus_type,
-	.owner		= THIS_MODULE,
+static struct platform_driver iodev_driver = {
+	.driver = {
+		.name		= iodev_name,
+		.owner		= THIS_MODULE,
+	},
 	.probe		= iodev_probe,
-	.remove		= __exit_p(iodev_remove)
+	.remove		= __devexit_p(iodev_remove),
 };
 
 
@@ -89,11 +89,10 @@
 
 
 /* No hotplugging on the platform bus - use __init */
-static int __init iodev_probe(struct device *dev)
+static int __init iodev_probe(struct platform_device *dev)
 {
-	struct platform_device * const pdv = to_platform_device(dev);
 	const struct resource * const ri =
-		iodev_get_resource(pdv, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ);
+		iodev_get_resource(dev, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ);
 
 	if (unlikely(!ri))
 		return -ENXIO;
@@ -104,7 +103,7 @@
 
 
 
-static int __exit iodev_remove(struct device *dev)
+static int __exit iodev_remove(struct platform_device *dev)
 {
 	return misc_deregister(&miscdev);
 }
@@ -160,14 +159,14 @@
 
 static int __init iodev_init_module(void)
 {
-	return driver_register(&iodev_driver);
+	return platform_driver_register(&iodev_driver);
 }
 
 
 
 static void __exit iodev_cleanup_module(void)
 {
-	driver_unregister(&iodev_driver);
+	platform_driver_unregister(&iodev_driver);
 }
 
 module_init(iodev_init_module);
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index f2baea3..0208723 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -512,7 +512,7 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
-CONFIG_MD_RAID456=m
+CONFIG_MD_RAID456=y
 CONFIG_MD_RAID5_RESHAPE=y
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 9d5bd2a..5380f1f 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc9
-# Fri Jul 11 23:01:36 2008
+# Linux kernel version: 2.6.29-rc7
+# Wed Mar  4 23:07:16 2009
 #
 CONFIG_MIPS=y
 
@@ -18,8 +18,10 @@
 # CONFIG_LEMOTE_FULONG is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SIM is not set
-# CONFIG_MARKEINS is not set
+# CONFIG_MACH_EMMA is not set
 # CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
 # CONFIG_PMC_MSP is not set
@@ -39,7 +41,11 @@
 # CONFIG_SNI_RM is not set
 CONFIG_MACH_TX39XX=y
 # CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
 # CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+CONFIG_MACH_TXX9=y
 CONFIG_TOSHIBA_JMR3927=y
 CONFIG_SOC_TX3927=y
 # CONFIG_TOSHIBA_FPCIB0 is not set
@@ -54,12 +60,14 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CMOS_UPDATE=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_CEVT_TXX9=y
 CONFIG_GPIO_TXX9=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
 # CONFIG_HOTPLUG_CPU is not set
 # CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_GPIO=y
@@ -87,6 +95,7 @@
 # CONFIG_CPU_TX49XX is not set
 # CONFIG_CPU_R5000 is not set
 # CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
 # CONFIG_CPU_R6000 is not set
 # CONFIG_CPU_NEVADA is not set
 # CONFIG_CPU_R8000 is not set
@@ -94,6 +103,7 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
 CONFIG_SYS_HAS_CPU_TX39XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
@@ -117,14 +127,12 @@
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-# CONFIG_TICK_ONESHOT is not set
+CONFIG_UNEVICTABLE_LRU=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -159,6 +167,15 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
@@ -171,7 +188,6 @@
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -188,26 +204,23 @@
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=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_HAVE_DMA_ATTRS is not set
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 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_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -221,7 +234,7 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
@@ -231,12 +244,15 @@
 CONFIG_PCI_DOMAINS=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_STUB is not set
 CONFIG_MMU=y
 
 #
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
 
@@ -245,15 +261,12 @@
 #
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PM is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -293,6 +306,7 @@
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -302,14 +316,9 @@
 # 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_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
 #
@@ -323,7 +332,89 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # 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=y
+# CONFIG_MTD_AR7_PARTS 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=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=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_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
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR 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
@@ -336,6 +427,7 @@
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
 # CONFIG_MISC_DEVICES is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
@@ -361,7 +453,6 @@
 # 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_EQUALIZER is not set
@@ -383,6 +474,9 @@
 # CONFIG_BROADCOM_PHY is not set
 # CONFIG_ICPLUS_PHY is not set
 # CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
 # CONFIG_FIXED_PHY is not set
 # CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
@@ -392,6 +486,7 @@
 # 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
@@ -399,6 +494,9 @@
 # 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
@@ -406,7 +504,6 @@
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
 CONFIG_TC35815=y
-# CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
@@ -415,9 +512,11 @@
 # CONFIG_R6040 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_ATL2 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
@@ -428,6 +527,10 @@
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 # CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_PPP is not set
@@ -440,27 +543,7 @@
 #
 # 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
+# CONFIG_INPUT is not set
 
 #
 # Hardware I/O ports
@@ -517,10 +600,11 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
-CONFIG_HAVE_GPIO_LIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
 
 #
-# GPIO Support
+# Memory mapped GPIO expanders:
 #
 
 #
@@ -528,6 +612,11 @@
 #
 
 #
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
 # SPI GPIO expanders:
 #
 # CONFIG_W1 is not set
@@ -542,6 +631,7 @@
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
 CONFIG_TXX9_WDT=y
 
 #
@@ -549,18 +639,21 @@
 #
 # CONFIG_PCIPCWATCHDOG is not set
 # CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -591,16 +684,26 @@
 # 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_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_GPIO=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
 CONFIG_RTC_LIB=y
@@ -626,27 +729,34 @@
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
 # CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
 CONFIG_RTC_DRV_DS1742=y
 # CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
 # on-CPU RTC drivers
 #
+# CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 CONFIG_DNOTIFY=y
@@ -676,28 +786,17 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_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_MISC_FILESYSTEMS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
-# CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
 CONFIG_LOCKD=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
@@ -726,7 +825,16 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_CMDLINE=""
 
 #
@@ -734,15 +842,18 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/markeins_defconfig
similarity index 99%
rename from arch/mips/configs/emma2rh_defconfig
rename to arch/mips/configs/markeins_defconfig
index fea9bc9..bad8901 100644
--- a/arch/mips/configs/emma2rh_defconfig
+++ b/arch/mips/configs/markeins_defconfig
@@ -35,7 +35,7 @@
 # CONFIG_PNX8550_STB810 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
-CONFIG_MARKEINS=y
+CONFIG_NEC_MARKEINS=y
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SGI_IP27 is not set
 # CONFIG_SGI_IP32 is not set
@@ -68,7 +68,7 @@
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_SWAP_IO_SPACE=y
-CONFIG_EMMA2RH=y
+CONFIG_SOC_EMMA2RH=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
@@ -574,9 +574,9 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x1e000000
-CONFIG_MTD_PHYSMAP_LEN=0x02000000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
 # CONFIG_MTD_PLATRAM is not set
 
 #
diff --git a/arch/mips/configs/rbtx49xx_defconfig b/arch/mips/configs/rbtx49xx_defconfig
index 83d5c58..1efe977 100644
--- a/arch/mips/configs/rbtx49xx_defconfig
+++ b/arch/mips/configs/rbtx49xx_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc9
-# Fri Jul 11 23:03:21 2008
+# Linux kernel version: 2.6.29-rc7
+# Wed Mar  4 23:08:06 2009
 #
 CONFIG_MIPS=y
 
@@ -18,8 +18,10 @@
 # CONFIG_LEMOTE_FULONG is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SIM is not set
-# CONFIG_MARKEINS is not set
+# CONFIG_MACH_EMMA is not set
 # CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
 # CONFIG_PMC_MSP is not set
@@ -39,20 +41,28 @@
 # CONFIG_SNI_RM is not set
 # CONFIG_MACH_TX39XX is not set
 CONFIG_MACH_TX49XX=y
+# CONFIG_MIKROTIK_RB532 is not set
 # CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+CONFIG_MACH_TXX9=y
 CONFIG_TOSHIBA_RBTX4927=y
 CONFIG_TOSHIBA_RBTX4938=y
+CONFIG_TOSHIBA_RBTX4939=y
 CONFIG_SOC_TX4927=y
 CONFIG_SOC_TX4938=y
+CONFIG_SOC_TX4939=y
+CONFIG_TXX9_7SEGLED=y
 # CONFIG_TOSHIBA_FPCIB0 is not set
 CONFIG_PICMG_PCI_BACKPLANE_DEFAULT=y
 
 #
 # Multiplex Pin Select
 #
-CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61=y
+# CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61 is not set
 # CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND is not set
 # CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA is not set
+CONFIG_TOSHIBA_RBTX4938_MPLEX_KEEP=y
 CONFIG_PCI_TX4927=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -64,14 +74,18 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CMOS_UPDATE=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K_LIB=y
 CONFIG_CEVT_R4K=y
 CONFIG_CEVT_TXX9=y
+CONFIG_CSRC_R4K_LIB=y
 CONFIG_CSRC_R4K=y
 CONFIG_GPIO_TXX9=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
 # CONFIG_HOTPLUG_CPU is not set
 # CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_GPIO=y
@@ -100,6 +114,7 @@
 CONFIG_CPU_TX49XX=y
 # CONFIG_CPU_R5000 is not set
 # CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
 # CONFIG_CPU_R6000 is not set
 # CONFIG_CPU_NEVADA is not set
 # CONFIG_CPU_R8000 is not set
@@ -107,6 +122,7 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
 CONFIG_SYS_HAS_CPU_TX49XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
@@ -134,13 +150,12 @@
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -176,6 +191,15 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -190,7 +214,6 @@
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -207,30 +230,26 @@
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=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_HAVE_DMA_ATTRS is not set
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
-# CONFIG_MODULE_UNLOAD is not set
+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
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -244,7 +263,8 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_PROBE_INITRD_HEADER is not set
+# CONFIG_FREEZER is not set
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
@@ -254,12 +274,15 @@
 CONFIG_PCI_DOMAINS=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
 CONFIG_MMU=y
 
 #
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
 
@@ -268,15 +291,12 @@
 #
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PM is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -318,6 +338,7 @@
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -327,14 +348,9 @@
 # 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_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
 #
@@ -348,7 +364,90 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # 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_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS 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=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=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_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
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR 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
@@ -365,9 +464,60 @@
 # CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
 # CONFIG_MISC_DEVICES is not set
 CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_TIMINGS=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+# CONFIG_BLK_DEV_GENERIC 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_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 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_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_IDE_TX4938=y
+CONFIG_BLK_DEV_IDE_TX4939=y
+CONFIG_BLK_DEV_IDEDMA=y
 
 #
 # SCSI device support
@@ -390,7 +540,6 @@
 # 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_EQUALIZER is not set
@@ -412,15 +561,19 @@
 # CONFIG_BROADCOM_PHY is not set
 # CONFIG_ICPLUS_PHY is not set
 # CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_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_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=y
 # CONFIG_DM9000 is not set
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
@@ -429,6 +582,9 @@
 # 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
@@ -436,7 +592,6 @@
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
 CONFIG_TC35815=y
-# CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
@@ -445,9 +600,11 @@
 # CONFIG_R6040 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_ATL2 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
@@ -458,6 +615,10 @@
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 # CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_PPP is not set
@@ -502,6 +663,7 @@
 CONFIG_SERIAL_TXX9_STDSERIAL=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_IPMI_HANDLER is not set
@@ -517,17 +679,19 @@
 #
 # SPI Master Controller Drivers
 #
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
 CONFIG_SPI_TXX9=y
 
 #
 # SPI Protocol Masters
 #
-CONFIG_EEPROM_AT25=y
 # CONFIG_SPI_TLE62X0 is not set
-CONFIG_HAVE_GPIO_LIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
 
 #
-# GPIO Support
+# Memory mapped GPIO expanders:
 #
 
 #
@@ -535,8 +699,14 @@
 #
 
 #
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
 # SPI GPIO expanders:
 #
+# CONFIG_GPIO_MAX7301 is not set
 # CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
@@ -550,6 +720,7 @@
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
 CONFIG_TXX9_WDT=m
 
 #
@@ -557,18 +728,21 @@
 #
 # CONFIG_PCIPCWATCHDOG is not set
 # CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -599,15 +773,27 @@
 # 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_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_GPIO=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
 CONFIG_RTC_LIB=y
@@ -628,35 +814,47 @@
 #
 # SPI RTC drivers
 #
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
 # CONFIG_RTC_DRV_R9701 is not set
 CONFIG_RTC_DRV_RS5C348=y
+# CONFIG_RTC_DRV_DS3234 is not set
 
 #
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
 # CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
 CONFIG_RTC_DRV_DS1742=y
 # CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
 # on-CPU RTC drivers
 #
+CONFIG_RTC_DRV_TX4939=y
+# CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_DNOTIFY is not set
@@ -687,30 +885,19 @@
 CONFIG_PROC_FS=y
 # CONFIG_PROC_KCORE is not set
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_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_MISC_FILESYSTEMS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
@@ -740,7 +927,16 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_CMDLINE=""
 
 #
@@ -748,15 +944,18 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
diff --git a/arch/mips/emma/Kconfig b/arch/mips/emma/Kconfig
deleted file mode 100644
index 9669c72..0000000
--- a/arch/mips/emma/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
-choice
-	prompt "Machine type"
-	depends on MACH_EMMA
-	default NEC_MARKEINS
-
-config NEC_MARKEINS
-	bool "NEC EMMA2RH Mark-eins board"
-	select SOC_EMMA2RH
-	select HW_HAS_PCI
-	help
-	  This enables support for the NEC Electronics Mark-eins boards.
-
-endchoice
-
-config SOC_EMMA2RH
-	bool
-	select SOC_EMMA
-	select SYS_HAS_CPU_R5500
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-
-config SOC_EMMA
-	bool
-	select CEVT_R4K
-	select CSRC_R4K
-	select DMA_NONCOHERENT
-	select IRQ_CPU
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_BIG_ENDIAN
diff --git a/arch/mips/emma/markeins/platform.c b/arch/mips/emma/markeins/platform.c
index 88e87f6..d5f47e4 100644
--- a/arch/mips/emma/markeins/platform.c
+++ b/arch/mips/emma/markeins/platform.c
@@ -141,13 +141,6 @@
 	},
 };
 
-static struct platform_device *devices[] = {
-	&i2c_emma_devices[0],
-	&i2c_emma_devices[1],
-	&i2c_emma_devices[2],
-	&serial_emma,
-};
-
 static struct mtd_partition markeins_parts[] = {
 	[0] = {
 		.name = "RootFS",
@@ -181,11 +174,39 @@
 	},
 };
 
+static struct physmap_flash_data markeins_flash_data = {
+	.width		= 2,
+	.nr_parts	= ARRAY_SIZE(markeins_parts),
+	.parts		= markeins_parts
+};
+
+static struct resource markeins_flash_resource = {
+	.start		= 0x1e000000,
+	.end		= 0x02000000,
+	.flags		= IORESOURCE_MEM
+};
+
+static struct platform_device markeins_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+        	.platform_data  = &markeins_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &markeins_flash_resource,
+};
+
+static struct platform_device *devices[] = {
+	i2c_emma_devices,
+	i2c_emma_devices + 1,
+	i2c_emma_devices + 2,
+	&serial_emma,
+	&markeins_flash_device,
+};
+
 static int __init platform_devices_setup(void)
 {
-	physmap_set_partitions(markeins_parts, ARRAY_SIZE(markeins_parts));
 	return platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
 arch_initcall(platform_devices_setup);
-
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index ac5d541..6c5b409 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -3,6 +3,8 @@
 /*
  * Architecture specific compatibility types
  */
+#include <linux/seccomp.h>
+#include <linux/thread_info.h>
 #include <linux/types.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -218,4 +220,9 @@
 	compat_ulong_t	__unused2;
 };
 
+static inline int is_compat_task(void)
+{
+	return test_thread_flag(TIF_32BIT);
+}
+
 #endif /* _ASM_COMPAT_H */
diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h
index 43baed1..134e1fc 100644
--- a/arch/mips/include/asm/hazards.h
+++ b/arch/mips/include/asm/hazards.h
@@ -138,7 +138,8 @@
 		__instruction_hazard();					\
 } while (0)
 
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_CAVIUM_OCTEON)
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \
+      defined(CONFIG_CPU_R5500)
 
 /*
  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 0417516..526f327 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1391,11 +1391,11 @@
 static inline unsigned int					\
 set_c0_##name(unsigned int set)					\
 {								\
-	unsigned int res;					\
+	unsigned int res, new;					\
 								\
 	res = read_c0_##name();					\
-	res |= set;						\
-	write_c0_##name(res);					\
+	new = res | set;					\
+	write_c0_##name(new);					\
 								\
 	return res;						\
 }								\
@@ -1403,24 +1403,24 @@
 static inline unsigned int					\
 clear_c0_##name(unsigned int clear)				\
 {								\
-	unsigned int res;					\
+	unsigned int res, new;					\
 								\
 	res = read_c0_##name();					\
-	res &= ~clear;						\
-	write_c0_##name(res);					\
+	new = res & ~clear;					\
+	write_c0_##name(new);					\
 								\
 	return res;						\
 }								\
 								\
 static inline unsigned int					\
-change_c0_##name(unsigned int change, unsigned int new)		\
+change_c0_##name(unsigned int change, unsigned int val)		\
 {								\
-	unsigned int res;					\
+	unsigned int res, new;					\
 								\
 	res = read_c0_##name();					\
-	res &= ~change;						\
-	res |= (new & change);					\
-	write_c0_##name(res);					\
+	new = res & ~change;					\
+	new |= (val & change);					\
+	write_c0_##name(new);					\
 								\
 	return res;						\
 }
diff --git a/arch/mips/include/asm/prefetch.h b/arch/mips/include/asm/prefetch.h
index 1785083..a56594f 100644
--- a/arch/mips/include/asm/prefetch.h
+++ b/arch/mips/include/asm/prefetch.h
@@ -26,7 +26,7 @@
  * Pref_WriteBackInvalidate is a nop and Pref_PrepareForStore is broken in
  * current versions due to erratum G105.
  *
- * VR7701 only implements the Load prefetch.
+ * VR5500 (including VR5701 and VR7701) only implement load prefetch.
  *
  * Finally MIPS32 and MIPS64 implement all of the following hints.
  */
diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h
index a6772e9..ae6306e 100644
--- a/arch/mips/include/asm/seccomp.h
+++ b/arch/mips/include/asm/seccomp.h
@@ -15,8 +15,6 @@
  */
 #ifdef CONFIG_MIPS32_O32
 
-#define TIF_32BIT TIF_32BIT_REGS
-
 #define __NR_seccomp_read_32		4003
 #define __NR_seccomp_write_32		4004
 #define __NR_seccomp_exit_32		4001
@@ -24,8 +22,6 @@
 
 #elif defined(CONFIG_MIPS32_N32)
 
-#define TIF_32BIT _TIF_32BIT_ADDR
-
 #define __NR_seccomp_read_32		6000
 #define __NR_seccomp_write_32		6001
 #define __NR_seccomp_exit_32		6058
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 3f76de7..676aa2a 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -127,6 +127,12 @@
 #define TIF_LOAD_WATCH		25	/* If set, load watch registers */
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
+#ifdef CONFIG_MIPS32_O32
+#define TIF_32BIT TIF_32BIT_REGS
+#elif defined(CONFIG_MIPS32_N32)
+#define TIF_32BIT _TIF_32BIT_ADDR
+#endif /* CONFIG_MIPS32_O32 */
+
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index a7162a4..1bdbcad 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -149,6 +149,7 @@
 	case CPU_R4650:
 	case CPU_R4700:
 	case CPU_R5000:
+	case CPU_R5500:
 	case CPU_NEVADA:
 	case CPU_4KC:
 	case CPU_4KEC:
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 2f8452b..49aac6e 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -32,7 +32,6 @@
 #include <linux/module.h>
 #include <linux/binfmts.h>
 #include <linux/security.h>
-#include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <linux/vfs.h>
 #include <linux/ipc.h>
@@ -235,7 +234,7 @@
 #else
 
 SYSCALL_DEFINE6(32_ipc, u32, call, int, first, int, second, int, third,
-	u32, ptr, u32 fifth)
+	u32, ptr, u32, fifth)
 {
 	return -ENOSYS;
 }
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index b2d7041..29fadac 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1520,7 +1520,9 @@
 #endif /* CONFIG_MIPS_MT_SMTC */
 
 	if (cpu_has_veic || cpu_has_vint) {
+		unsigned long sr = set_c0_status(ST0_BEV);
 		write_c0_ebase(ebase);
+		write_c0_status(sr);
 		/* Setting vector spacing enables EI/VI mode  */
 		change_c0_intctl(0x3e0, VECTORSPACING);
 	}
@@ -1602,8 +1604,6 @@
 #ifdef CONFIG_64BIT
 	unsigned long uncached_ebase = TO_UNCAC(ebase);
 #endif
-	if (cpu_has_mips_r2)
-		uncached_ebase += (read_c0_ebase() & 0x3ffff000);
 
 	if (!addr)
 		panic(panic_null_cerr);
@@ -1635,9 +1635,11 @@
 		return;	/* Already done */
 #endif
 
-	if (cpu_has_veic || cpu_has_vint)
-		ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64);
-	else {
+	if (cpu_has_veic || cpu_has_vint) {
+		unsigned long size = 0x200 + VECTORSPACING*64;
+		ebase = (unsigned long)
+			__alloc_bootmem(size, 1 << fls(size), 0);
+	} else {
 		ebase = CAC_BASE;
 		if (cpu_has_mips_r2)
 			ebase += (read_c0_ebase() & 0x3ffff000);
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index c43f4b2..871e828 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -780,7 +780,7 @@
 		c->dcache.ways = 2;
 		c->dcache.waybit = 0;
 
-		c->options |= MIPS_CPU_CACHE_CDEX_P;
+		c->options |= MIPS_CPU_CACHE_CDEX_P | MIPS_CPU_PREFETCH;
 		break;
 
 	case CPU_TX49XX:
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 546e697..bed56f1 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -225,7 +225,7 @@
 	if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) {
 		unsigned long addr;
 
-		addr = plat_dma_addr_to_phys(dma_address);
+		addr = dma_addr_to_virt(dma_address);
 		dma_cache_wback_inv(addr, size);
 	}
 
diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index 1417c64..48060c6 100644
--- a/arch/mips/mm/page.c
+++ b/arch/mips/mm/page.c
@@ -172,8 +172,9 @@
 		 */
 		cache_line_size = cpu_dcache_line_size();
 		switch (current_cpu_type()) {
+		case CPU_R5500:
 		case CPU_TX49XX:
-			/* TX49 supports only Pref_Load */
+			/* These processors only support the Pref_Load. */
 			pref_bias_copy_load = 256;
 			break;
 
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 4294203..f335cf6 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -318,6 +318,7 @@
 	case CPU_BCM4710:
 	case CPU_LOONGSON2:
 	case CPU_CAVIUM_OCTEON:
+	case CPU_R5500:
 		if (m4kc_tlbp_war())
 			uasm_i_nop(p);
 		tlbw(p);
diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig
index 9fc96e7..bf34a28 100644
--- a/arch/parisc/configs/712_defconfig
+++ b/arch/parisc/configs/712_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23
-# Fri Oct 12 21:00:07 2007
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 01:32:55 2009
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -33,17 +33,35 @@
 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
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS 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_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
@@ -55,29 +73,38 @@
 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_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT 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_FORCE_LOAD is not set
 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_INIT_ALL_POSSIBLE=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
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -91,6 +118,7 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
 
 #
 # Processor type and features
@@ -114,17 +142,19 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK 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_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 # CONFIG_HPUX is not set
 
 #
@@ -138,10 +168,6 @@
 # CONFIG_EISA is not set
 # CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
 # CONFIG_PCCARD is not set
 
 #
@@ -156,16 +182,15 @@
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -173,6 +198,7 @@
 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
@@ -203,25 +229,25 @@
 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 is not set
-# CONFIG_NF_CONNTRACK_ENABLED is not set
+# 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
+# CONFIG_IP_VS is not set
 
 #
 # IP: Netfilter Configuration
 #
+# CONFIG_NF_DEFRAG_IPV4 is not set
 CONFIG_IP_NF_QUEUE=m
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -230,6 +256,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 CONFIG_LLC=m
@@ -240,28 +267,26 @@
 # 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_DCB 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_PHONET is not set
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
 # CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -276,6 +301,8 @@
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -298,11 +325,19 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=6144
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 CONFIG_ATA_OVER_ETH=m
+# CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
 # CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
@@ -342,14 +377,17 @@
 # CONFIG_SCSI_FC_ATTRS is not set
 CONFIG_SCSI_ISCSI_ATTRS=m
 # 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_LIBFC is not set
 # CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_IMM is not set
 CONFIG_SCSI_LASI700=y
 CONFIG_53C700_LE_ON_BE=y
 # CONFIG_SCSI_ZALON is not set
 CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
@@ -362,7 +400,6 @@
 # CONFIG_MD_FAULTY is not set
 # CONFIG_BLK_DEV_DM is not set
 CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -377,6 +414,9 @@
 # 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
 # CONFIG_NET_POCKET is not set
 CONFIG_NETDEV_1000=y
@@ -387,6 +427,11 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_PLIP is not set
 CONFIG_PPP=m
@@ -401,7 +446,6 @@
 # CONFIG_PPPOL2TP is not set
 # CONFIG_SLIP is not set
 CONFIG_SLHC=m
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -423,7 +467,6 @@
 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
 
@@ -446,8 +489,8 @@
 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_ELANTECH is not set
 # CONFIG_MOUSE_PS2_TOUCHKIT is not set
 CONFIG_MOUSE_SERIAL=m
 # CONFIG_MOUSE_VSXXXAA is not set
@@ -474,9 +517,11 @@
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -501,72 +546,76 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=64
 CONFIG_PRINTER=m
 # CONFIG_LP_CONSOLE is not set
 CONFIG_PPDEV=m
-# CONFIG_TIPAR is not set
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
 # CONFIG_R3964 is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
 # 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 is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # 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=m
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
 # CONFIG_FB_SYS_FILLRECT is not set
 # CONFIG_FB_SYS_COPYAREA is not set
 # CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
 # CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -579,6 +628,14 @@
 CONFIG_FB_STI=y
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
 # Console display driver support
@@ -606,15 +663,8 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_PARISC_CLUT224=y
-
-#
-# Sound
-#
 CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
 CONFIG_SND=y
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
@@ -630,10 +680,7 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_VIRMIDI is not set
 # CONFIG_SND_MTPAV is not set
@@ -641,63 +688,82 @@
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
 # CONFIG_SND_PORTMAN2X4 is not set
-
-#
-# GSC devices
-#
+CONFIG_SND_GSC=y
 CONFIG_SND_HARMONY=y
-
-#
-# System on Chip audio support
-#
 # CONFIG_SND_SOC is not set
-
-#
-# SoC Audio support for SuperH
-#
-
-#
-# Open Sound System
-#
 # CONFIG_SOUND_PRIME is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
 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'
+# Enable Host or Gadget support to see Inventra options
 #
 
 #
-# USB Gadget Support
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
 # CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
-# CONFIG_RTC_CLASS is not set
+# CONFIG_ACCESSIBILITY 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
 
 #
-# DMA Engine support
+# RTC interfaces
 #
-# CONFIG_DMA_ENGINE 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
 
 #
-# DMA Clients
+# SPI RTC drivers
 #
 
 #
-# DMA Devices
+# Platform RTC drivers
 #
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_PARISC=y
+# CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
-
-#
-# Userspace I/O
-#
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -707,7 +773,7 @@
 # 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_EXT4_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
@@ -717,19 +783,18 @@
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
-# CONFIG_GFS2_FS is not set
+# CONFIG_XFS_DEBUG is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_BTRFS_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=y
 # CONFIG_FUSE_FS is not set
@@ -759,16 +824,13 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_ECRYPT_FS is not set
@@ -778,35 +840,34 @@
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_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=m
 # CONFIG_UFS_FS_WRITE is not set
 # CONFIG_UFS_DEBUG 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
 CONFIG_NFS_V4=y
-CONFIG_NFS_DIRECTIO=y
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
 # CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
-CONFIG_NFSD_TCP=y
-CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 CONFIG_RPCSEC_GSS_SPKM3=m
 CONFIG_SMB_FS=m
@@ -815,6 +876,7 @@
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
 # CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
 # CONFIG_CIFS_XATTR is not set
 # CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
@@ -827,10 +889,6 @@
 #
 # 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=m
@@ -871,33 +929,28 @@
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
 CONFIG_NLS_UTF8=m
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
 
 #
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-
-#
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS 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_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -909,10 +962,32 @@
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_LIST is not set
-CONFIG_FORCED_INLINING=y
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_NOP_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
 CONFIG_DEBUG_RODATA=y
 
 #
@@ -921,57 +996,113 @@
 CONFIG_KEYS=y
 CONFIG_KEYS_DEBUG_PROC_KEYS=y
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
 CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
 CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
 CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+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 is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_XCBC is not set
-CONFIG_CRYPTO_NULL=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
-# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_ECB=m
-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=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 is not set
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
+# CONFIG_CRYPTO_SALSA20 is not set
 # CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
 CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_CAMELLIA is not set
-CONFIG_CRYPTO_TEST=m
-# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
-# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
 CONFIG_LIBCRC32C=m
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index ddacc72..f12e4b8 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23
-# Fri Oct 12 21:12:44 2007
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 01:32:56 2009
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -34,18 +34,30 @@
 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
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
-# CONFIG_CPUSETS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS 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_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
@@ -57,28 +69,40 @@
 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_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT 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_FORCE_LOAD is not set
 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_INIT_ALL_POSSIBLE=y
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 CONFIG_BLOCK_COMPAT=y
 
 #
@@ -93,6 +117,7 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
 
 #
 # Processor type and features
@@ -118,12 +143,12 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
-CONFIG_PREEMPT_BKL=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_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 CONFIG_DISCONTIGMEM_MANUAL=y
@@ -131,11 +156,12 @@
 CONFIG_DISCONTIGMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 CONFIG_COMPAT=y
 CONFIG_NR_CPUS=8
 
@@ -145,14 +171,13 @@
 # CONFIG_GSC is not set
 CONFIG_PCI=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
 # CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
 CONFIG_PCI_LBA=y
 CONFIG_IOSAPIC=y
 CONFIG_IOMMU_SBA=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+CONFIG_IOMMU_HELPER=y
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
@@ -187,16 +212,15 @@
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -204,6 +228,8 @@
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
 CONFIG_NET_KEY=m
 # CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
@@ -234,7 +260,6 @@
 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
@@ -250,66 +275,72 @@
 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=y
 # CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
 
 #
 # Core Netfilter Configuration
 #
-# CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NF_CONNTRACK_ENABLED is not set
+# 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_NFQUEUE 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_HASHLIMIT 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_POLICY is not set
 # CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY 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_RECENT 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
+# CONFIG_IP_VS is not set
 
 #
 # IP: Netfilter Configuration
 #
+# CONFIG_NF_DEFRAG_IPV4 is not set
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_TOS=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_OWNER=m
 # CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=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_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
 # CONFIG_IP_NF_TARGET_TTL is not set
 CONFIG_IP_NF_RAW=m
@@ -318,33 +349,30 @@
 CONFIG_IP_NF_ARP_MANGLE=m
 
 #
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
+# IPv6: Netfilter Configuration
 #
 # CONFIG_IP6_NF_QUEUE is not set
 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_OWNER is not set
-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 is not set
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+# CONFIG_IP6_NF_MATCH_MH is not set
+CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 # CONFIG_IP6_NF_TARGET_HL is not set
 CONFIG_IP6_NF_RAW=m
 CONFIG_IP_DCCP=m
 CONFIG_INET_DCCP_DIAG=m
-CONFIG_IP_DCCP_ACKVEC=y
 
 #
 # DCCP CCIDs Configuration (EXPERIMENTAL)
 #
-CONFIG_IP_DCCP_CCID2=m
 # CONFIG_IP_DCCP_CCID2_DEBUG is not set
 # CONFIG_IP_DCCP_CCID3 is not set
 
@@ -356,6 +384,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 CONFIG_LLC=m
@@ -366,28 +395,26 @@
 # 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_DCB 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_PHONET is not set
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
 # CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -402,6 +429,8 @@
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -421,14 +450,23 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=6144
-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_BLK_DEV_HD 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_HP_ILO is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
@@ -468,8 +506,10 @@
 CONFIG_SCSI_FC_ATTRS=m
 CONFIG_SCSI_ISCSI_ATTRS=m
 # 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_CXGB3_ISCSI 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
@@ -478,16 +518,21 @@
 # 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_LIBFC is not set
+# CONFIG_FCOE 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_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
@@ -503,9 +548,11 @@
 CONFIG_SCSI_DEBUG=m
 # CONFIG_SCSI_SRP is not set
 # CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
@@ -514,10 +561,6 @@
 # CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
 # CONFIG_BLK_DEV_DM is not set
-
-#
-# Fusion MPT device support
-#
 CONFIG_FUSION=y
 CONFIG_FUSION_SPI=m
 CONFIG_FUSION_FC=m
@@ -529,20 +572,40 @@
 #
 # IEEE 1394 (FireWire) support
 #
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
 # 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=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
 # CONFIG_VETH is not set
-# CONFIG_IP1000 is not set
 # CONFIG_ARCNET is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=m
+
+#
+# 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_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
 # CONFIG_HAPPYMEAL is not set
@@ -567,33 +630,38 @@
 # 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=m
-# CONFIG_PCNET32_NAPI 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=m
 # 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_SMSC9420 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_ATL2 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
 # CONFIG_DL2K is not set
 CONFIG_E1000=m
-CONFIG_E1000_NAPI=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_E1000E 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
@@ -601,23 +669,31 @@
 # 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 is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
 # CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC 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_EN is not set
 # CONFIG_MLX4_CORE is not set
 # CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
 # CONFIG_TR is not set
 
 #
@@ -625,6 +701,11 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 CONFIG_NET_PCMCIA=y
 CONFIG_PCMCIA_3C589=m
 CONFIG_PCMCIA_3C574=m
@@ -650,7 +731,6 @@
 # CONFIG_SLIP is not set
 CONFIG_SLHC=m
 # 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
@@ -669,7 +749,6 @@
 #
 # 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
 
@@ -693,10 +772,13 @@
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
 
 #
 # Serial drivers
@@ -721,17 +803,12 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-CONFIG_AGP=y
-CONFIG_AGP_PARISC=y
-# CONFIG_DRM is not set
 
 #
 # PCMCIA character devices
@@ -739,51 +816,66 @@
 # 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=y
 CONFIG_MAX_RAW_DEVS=256
 # 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_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
 # Graphics support
 #
+CONFIG_AGP=y
+CONFIG_AGP_PARISC=y
+# 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
-# CONFIG_VGASTATE is not set
-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
 
 #
 # Console display driver support
@@ -792,50 +884,83 @@
 CONFIG_DUMMY_CONSOLE_COLUMNS=160
 CONFIG_DUMMY_CONSOLE_ROWS=64
 # CONFIG_STI_CONSOLE 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_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
 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
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# Enable Host or Gadget support to see Inventra options
 #
 
 #
-# USB Gadget Support
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
 # CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
-# CONFIG_RTC_CLASS 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
 
 #
-# DMA Engine support
+# RTC interfaces
 #
-# CONFIG_DMA_ENGINE 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
 
 #
-# DMA Clients
+# SPI RTC drivers
 #
 
 #
-# DMA Devices
+# Platform RTC drivers
 #
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
 
 #
-# Userspace I/O
+# on-CPU RTC drivers
 #
+CONFIG_RTC_DRV_PARISC=y
+# CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -845,7 +970,7 @@
 # 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_EXT4_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
@@ -855,19 +980,19 @@
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_BTRFS_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=y
 # CONFIG_FUSE_FS is not set
@@ -897,16 +1022,13 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_ECRYPT_FS is not set
@@ -916,34 +1038,33 @@
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_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=m
 # CONFIG_UFS_FS_WRITE is not set
 # CONFIG_UFS_DEBUG is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
-CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
 # CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
-CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_RPCSEC_GSS_SPKM3=m
 CONFIG_SMB_FS=m
@@ -952,6 +1073,7 @@
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
 # CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
 # CONFIG_CIFS_XATTR is not set
 # CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
@@ -964,10 +1086,6 @@
 #
 # 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=m
@@ -1008,33 +1126,28 @@
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=m
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
 
 #
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-
-#
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -1046,10 +1159,33 @@
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
-CONFIG_FORCED_INLINING=y
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_NOP_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_BUILD_DOCSRC is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
 # CONFIG_DEBUG_RODATA is not set
 
 #
@@ -1058,56 +1194,112 @@
 CONFIG_KEYS=y
 CONFIG_KEYS_DEBUG_PROC_KEYS=y
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
 CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
 CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
 CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+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=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_XCBC is not set
-CONFIG_CRYPTO_NULL=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 CONFIG_CRYPTO_SHA1=m
 # CONFIG_CRYPTO_SHA256 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=m
-# 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=m
-# CONFIG_CRYPTO_FCRYPT is not set
-CONFIG_CRYPTO_BLOWFISH=m
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
 # CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_CAMELLIA is not set
 CONFIG_CRYPTO_CAST5=m
 # CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SALSA20 is not set
 # CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
 CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_CAMELLIA is not set
-CONFIG_CRYPTO_TEST=m
-# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
-# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
 CONFIG_LIBCRC32C=m
diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig
index 1bf22c9..98bb05e 100644
--- a/arch/parisc/configs/b180_defconfig
+++ b/arch/parisc/configs/b180_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23
-# Fri Oct 12 21:16:46 2007
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 01:32:57 2009
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -33,13 +33,29 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_CGROUPS 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_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
@@ -51,27 +67,34 @@
 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_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT 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_FORCE_LOAD is not set
 # CONFIG_MODULE_UNLOAD is not set
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_INIT_ALL_POSSIBLE=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_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -85,6 +108,7 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
 
 #
 # Processor type and features
@@ -108,13 +132,15 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 # CONFIG_HPUX is not set
 
 #
@@ -130,14 +156,14 @@
 CONFIG_ISA=y
 CONFIG_PCI=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
 # CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
 CONFIG_GSC_DINO=y
 # CONFIG_PCI_LBA is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+CONFIG_IOMMU_HELPER=y
 # CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
 
 #
 # PA-RISC specific drivers
@@ -151,16 +177,15 @@
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -205,36 +230,37 @@
 CONFIG_INET6_XFRM_MODE_TUNNEL=y
 CONFIG_INET6_XFRM_MODE_BEET=y
 CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETLABEL 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
-
-#
-# QoS and/or fair queueing
-#
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB 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_PHONET is not set
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
 #
@@ -247,7 +273,9 @@
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -275,10 +303,18 @@
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 CONFIG_ATA_OVER_ETH=y
+# CONFIG_BLK_DEV_HD 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_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
@@ -317,8 +353,10 @@
 # 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_CXGB3_ISCSI 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
@@ -330,12 +368,15 @@
 # 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_IN2000 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_LIBFC is not set
+# CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -346,6 +387,7 @@
 # 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_NCR53C406A is not set
 CONFIG_SCSI_LASI700=y
 CONFIG_53C700_LE_ON_BE=y
@@ -360,7 +402,6 @@
 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
 CONFIG_SCSI_NCR53C8XX_SYNC=40
 # CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
@@ -373,9 +414,11 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
@@ -383,26 +426,18 @@
 # CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
 # CONFIG_BLK_DEV_DM 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
 #
 
 #
-# An alternative FireWire stack is available with EXPERIMENTAL=y
+# A new alternative FireWire stack is available with EXPERIMENTAL=y
 #
 # 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_EQUALIZER is not set
@@ -434,36 +469,49 @@
 # 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_CS89x0 is not set
 # CONFIG_NET_POCKET is not set
+# CONFIG_ATL2 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_IGB is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI 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_JME is not set
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
 # CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC 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_EN is not set
 # CONFIG_MLX4_CORE is not set
 # CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
 # CONFIG_TR is not set
 
 #
@@ -471,6 +519,11 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_PLIP is not set
@@ -503,7 +556,6 @@
 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=y
 # CONFIG_INPUT_EVBUG is not set
 
@@ -526,11 +578,12 @@
 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_ELANTECH is not set
 # CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_INPORT is not set
 # CONFIG_MOUSE_LOGIBM is not set
 # CONFIG_MOUSE_PC110PAD is not set
@@ -564,9 +617,11 @@
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -598,75 +653,79 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 CONFIG_PRINTER=y
 # CONFIG_LP_CONSOLE is not set
 # CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM 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
 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_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=m
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
 # CONFIG_FB_SYS_FILLRECT is not set
 # CONFIG_FB_SYS_COPYAREA is not set
 # CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
 # CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -691,6 +750,7 @@
 # CONFIG_FB_ATY is not set
 # CONFIG_FB_S3 is not set
 # CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
@@ -698,7 +758,16 @@
 # CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_ARK is not set
+# CONFIG_FB_CARMINE is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
 # Console display driver support
@@ -718,15 +787,8 @@
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
 CONFIG_LOGO_PARISC_CLUT224=y
-
-#
-# Sound
-#
 CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
 CONFIG_SND=y
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
@@ -742,10 +804,7 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_VIRMIDI is not set
 # CONFIG_SND_MTPAV is not set
@@ -753,10 +812,7 @@
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
 # CONFIG_SND_PORTMAN2X4 is not set
-
-#
-# PCI devices
-#
+CONFIG_SND_PCI=y
 # CONFIG_SND_AD1889 is not set
 # CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALI5451 is not set
@@ -765,9 +821,11 @@
 # CONFIG_SND_AU8810 is not set
 # CONFIG_SND_AU8820 is not set
 # CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 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_DARLA20 is not set
@@ -792,6 +850,7 @@
 # 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 is not set
@@ -809,30 +868,23 @@
 # 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
-
-#
-# GSC devices
-#
+CONFIG_SND_GSC=y
 CONFIG_SND_HARMONY=y
-
-#
-# System on Chip audio support
-#
 # CONFIG_SND_SOC is not set
-
-#
-# SoC Audio support for SuperH
-#
-
-#
-# Open Sound System
-#
 # CONFIG_SOUND_PRIME is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -840,36 +892,63 @@
 # CONFIG_USB is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# Enable Host or Gadget support to see Inventra options
 #
 
 #
-# USB Gadget Support
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
 # CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
-# CONFIG_RTC_CLASS 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
 
 #
-# DMA Engine support
+# RTC interfaces
 #
-# CONFIG_DMA_ENGINE 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
 
 #
-# DMA Clients
+# SPI RTC drivers
 #
 
 #
-# DMA Devices
+# Platform RTC drivers
 #
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_PARISC=y
+# CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
-
-#
-# Userspace I/O
-#
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -879,19 +958,18 @@
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 # 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_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=y
 # CONFIG_FUSE_FS is not set
@@ -917,35 +995,32 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_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
-# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
 # CONFIG_NFSD_V3_ACL is not set
-CONFIG_NFSD_TCP=y
-CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
@@ -962,10 +1037,6 @@
 #
 # 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=m
@@ -1011,7 +1082,9 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
@@ -1019,9 +1092,12 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -1033,10 +1109,29 @@
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_LIST is not set
-CONFIG_FORCED_INLINING=y
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_BUILD_DOCSRC is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
 # CONFIG_DEBUG_RODATA is not set
 
 #
@@ -1044,52 +1139,108 @@
 #
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
 CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
 CONFIG_CRYPTO_MANAGER=y
-# CONFIG_CRYPTO_HMAC is not set
+CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_PCBC is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_MD4 is not set
 # CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 # CONFIG_CRYPTO_SHA1 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_ECB is not set
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_PCBC 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_WP512 is not set
+
+#
+# Ciphers
+#
 # CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA 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_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
 # CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
 # 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
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig
index c6def3c..0aa8014 100644
--- a/arch/parisc/configs/c3000_defconfig
+++ b/arch/parisc/configs/c3000_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23
-# Fri Oct 12 21:24:00 2007
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 01:32:58 2009
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -33,16 +33,29 @@
 # 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_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS 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_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
@@ -54,29 +67,39 @@
 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_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT 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_FORCE_LOAD is not set
 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_INIT_ALL_POSSIBLE=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
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -90,6 +113,7 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
 
 #
 # Processor type and features
@@ -115,17 +139,19 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK 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_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 # CONFIG_HPUX is not set
 
 #
@@ -134,14 +160,13 @@
 # CONFIG_GSC is not set
 CONFIG_PCI=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
 # CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
 CONFIG_PCI_LBA=y
 CONFIG_IOSAPIC=y
 CONFIG_IOMMU_SBA=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+CONFIG_IOMMU_HELPER=y
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
 
@@ -158,16 +183,15 @@
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -175,6 +199,8 @@
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
 CONFIG_NET_KEY=m
 # CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
@@ -204,7 +230,6 @@
 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
@@ -220,29 +245,34 @@
 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=y
 CONFIG_NETFILTER_DEBUG=y
+CONFIG_NETFILTER_ADVANCED=y
 
 #
 # Core Netfilter Configuration
 #
-# CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NF_CONNTRACK_ENABLED is not set
+# 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
+# CONFIG_IP_VS is not set
 
 #
 # IP: Netfilter Configuration
 #
+# CONFIG_NF_DEFRAG_IPV4 is not set
 CONFIG_IP_NF_QUEUE=m
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
 
 #
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
+# IPv6: Netfilter Configuration
 #
 # CONFIG_IP6_NF_QUEUE is not set
 # CONFIG_IP6_NF_IPTABLES is not set
@@ -251,6 +281,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -260,28 +291,26 @@
 # 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_DCB 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_PHONET is not set
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
 # CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -296,6 +325,8 @@
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -316,59 +347,62 @@
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD 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=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
+# EEPROM support
 #
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_ATAPI=y
 # CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=m
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
 CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
 # CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-CONFIG_BLK_DEV_IDESCSI=y
 # 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_SHARE_IRQ=y
 CONFIG_IDEPCI_PCIBUS_ORDER=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_BLK_DEV_GENERIC is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_ONLYDISK=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_IT8172 is not set
 # CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 CONFIG_BLK_DEV_NS87415=y
@@ -380,10 +414,7 @@
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_BLK_DEV_TC86C001 is not set
-# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
@@ -422,8 +453,10 @@
 # CONFIG_SCSI_FC_ATTRS is not set
 CONFIG_SCSI_ISCSI_ATTRS=m
 # 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_CXGB3_ISCSI 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
@@ -433,16 +466,20 @@
 # 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_LIBFC is not set
+# CONFIG_FCOE 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_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
@@ -458,9 +495,11 @@
 # CONFIG_SCSI_NSP32 is not set
 CONFIG_SCSI_DEBUG=m
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
@@ -475,13 +514,8 @@
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
-# CONFIG_DM_MULTIPATH_EMC is not set
-# CONFIG_DM_MULTIPATH_RDAC is not set
 # CONFIG_DM_DELAY is not set
-
-#
-# Fusion MPT device support
-#
+# CONFIG_DM_UEVENT is not set
 CONFIG_FUSION=y
 CONFIG_FUSION_SPI=m
 # CONFIG_FUSION_FC is not set
@@ -493,20 +527,40 @@
 #
 # IEEE 1394 (FireWire) support
 #
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
 # 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=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
 # CONFIG_VETH is not set
-# CONFIG_IP1000 is not set
 # CONFIG_ARCNET is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=m
+
+#
+# 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_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
 # CONFIG_HAPPYMEAL is not set
@@ -528,33 +582,38 @@
 # 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR 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=m
 # 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_SMSC9420 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_ATL2 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_ACENIC=m
 # CONFIG_ACENIC_OMIT_TIGON_I is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=m
-# CONFIG_E1000_NAPI is not set
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_E1000E 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
@@ -562,23 +621,31 @@
 # 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 is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
 # CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC 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_EN is not set
 # CONFIG_MLX4_CORE is not set
 # CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
 # CONFIG_TR is not set
 
 #
@@ -586,6 +653,11 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 
 #
 # USB Network Adapters
@@ -594,7 +666,6 @@
 # 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_FDDI is not set
@@ -612,7 +683,6 @@
 # CONFIG_SLIP is not set
 CONFIG_SLHC=m
 # 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
@@ -634,7 +704,6 @@
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1600
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1200
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
@@ -652,6 +721,7 @@
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
@@ -672,10 +742,13 @@
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
 
 #
 # Serial drivers
@@ -699,72 +772,77 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
 # 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_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=m
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
 # CONFIG_FB_SYS_FILLRECT is not set
 # CONFIG_FB_SYS_COPYAREA is not set
 # CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
 # CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -790,6 +868,7 @@
 # CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
@@ -798,7 +877,16 @@
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_ARK is not set
 # CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
 # Console display driver support
@@ -818,15 +906,8 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_PARISC_CLUT224=y
-
-#
-# Sound
-#
 CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
 CONFIG_SND=y
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
@@ -842,20 +923,16 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_VMASTER=y
 CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_DRIVERS=y
 # 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
-
-#
-# PCI devices
-#
+# CONFIG_SND_AC97_POWER_SAVE is not set
+CONFIG_SND_PCI=y
 CONFIG_SND_AD1889=y
 # CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALI5451 is not set
@@ -864,10 +941,12 @@
 # CONFIG_SND_AU8810 is not set
 # CONFIG_SND_AU8820 is not set
 # CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 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_DARLA20 is not set
@@ -892,6 +971,7 @@
 # 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 is not set
@@ -909,47 +989,59 @@
 # 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
-
-#
-# USB devices
-#
+CONFIG_SND_USB=y
 # CONFIG_SND_USB_AUDIO 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
-#
-
-#
-# 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_HID_PID is not set
 CONFIG_USB_HIDDEV=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF 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=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
 
 #
 # Miscellaneous USB options
@@ -958,12 +1050,20 @@
 CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
 # CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_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
@@ -971,32 +1071,37 @@
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_ACM is not set
 CONFIG_USB_PRINTER=m
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=m
 # 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=y
 CONFIG_USB_STORAGE_USBAT=y
 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_ONETOUCH is not set
 # CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -1004,15 +1109,10 @@
 #
 CONFIG_USB_MDC800=m
 CONFIG_USB_MICROTEK=m
-# CONFIG_USB_MON is not set
 
 #
 # USB port drivers
 #
-
-#
-# USB Serial Converter support
-#
 # CONFIG_USB_SERIAL is not set
 
 #
@@ -1021,7 +1121,7 @@
 # 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_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 CONFIG_USB_LEGOTOWER=m
 # CONFIG_USB_LCD is not set
@@ -1037,37 +1137,59 @@
 # 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_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
 # CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
-# CONFIG_RTC_CLASS 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
 
 #
-# DMA Engine support
+# RTC interfaces
 #
-# CONFIG_DMA_ENGINE 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
 
 #
-# DMA Clients
+# SPI RTC drivers
 #
 
 #
-# DMA Devices
+# Platform RTC drivers
 #
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
 
 #
-# Userspace I/O
+# on-CPU RTC drivers
 #
+CONFIG_RTC_DRV_PARISC=y
+# CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -1077,25 +1199,24 @@
 # 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_EXT4_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
-# CONFIG_GFS2_FS is not set
+# CONFIG_XFS_DEBUG is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_BTRFS_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=y
 # CONFIG_FUSE_FS is not set
@@ -1124,16 +1245,13 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1142,32 +1260,31 @@
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_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
 # CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
 # CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1181,10 +1298,6 @@
 #
 # 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=m
@@ -1225,33 +1338,28 @@
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=m
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
 
 #
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-
-#
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -1263,10 +1371,33 @@
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
-CONFIG_FORCED_INLINING=y
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_NOP_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_BUILD_DOCSRC is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
 CONFIG_DEBUG_RODATA=y
 
 #
@@ -1274,54 +1405,110 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
 CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
 CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+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=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
-CONFIG_CRYPTO_NULL=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 # CONFIG_CRYPTO_SHA1 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=m
-# 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=m
-# CONFIG_CRYPTO_FCRYPT is not set
-CONFIG_CRYPTO_BLOWFISH=m
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
 # CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_CAMELLIA 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_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SALSA20 is not set
 # CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
 CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_CAMELLIA is not set
-CONFIG_CRYPTO_TEST=m
-# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
diff --git a/arch/parisc/configs/default_defconfig b/arch/parisc/configs/default_defconfig
index 448a757..283a96c 100644
--- a/arch/parisc/configs/default_defconfig
+++ b/arch/parisc/configs/default_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23
-# Fri Oct 12 20:54:57 2007
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 01:32:59 2009
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -33,17 +33,35 @@
 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
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS 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_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
@@ -55,29 +73,39 @@
 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_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT 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_FORCE_LOAD is not set
 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_INIT_ALL_POSSIBLE=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
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -91,6 +119,7 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
 
 #
 # Processor type and features
@@ -114,17 +143,19 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK 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_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 # CONFIG_HPUX is not set
 
 #
@@ -140,15 +171,14 @@
 # CONFIG_ISA is not set
 CONFIG_PCI=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
 # CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
 CONFIG_GSC_DINO=y
 CONFIG_PCI_LBA=y
 CONFIG_IOSAPIC=y
 CONFIG_IOMMU_SBA=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+CONFIG_IOMMU_HELPER=y
 CONFIG_PCCARD=y
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=y
@@ -183,16 +213,15 @@
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -200,6 +229,8 @@
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=y
 CONFIG_NET_KEY=m
 # CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
@@ -245,8 +276,10 @@
 CONFIG_INET6_XFRM_MODE_BEET=y
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
 # CONFIG_IPV6_TUNNEL is not set
 # 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
@@ -254,6 +287,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 CONFIG_LLC=m
@@ -264,28 +298,26 @@
 # 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_DCB 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_PHONET is not set
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
 # CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -300,6 +332,8 @@
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -330,63 +364,68 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=6144
-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_BLK_DEV_HD 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=y
-CONFIG_BLK_DEV_IDE=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
+# EEPROM support
 #
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_ATAPI=y
 # CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
 CONFIG_BLK_DEV_IDECS=y
 # CONFIG_BLK_DEV_DELKIN is not set
 CONFIG_BLK_DEV_IDECD=y
+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=y
 # 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_SHARE_IRQ=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_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_ONLYDISK=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_IT8172 is not set
 # CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 CONFIG_BLK_DEV_NS87415=y
@@ -398,10 +437,7 @@
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_BLK_DEV_TC86C001 is not set
-# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
@@ -440,8 +476,10 @@
 # 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_CXGB3_ISCSI 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
@@ -452,11 +490,14 @@
 # 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_LIBFC is not set
+# CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
@@ -464,6 +505,7 @@
 # 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_LASI700=y
 CONFIG_53C700_LE_ON_BE=y
 # CONFIG_SCSI_STEX is not set
@@ -487,9 +529,11 @@
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
 # CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
@@ -505,32 +549,47 @@
 # CONFIG_DM_ZERO is not set
 # CONFIG_DM_MULTIPATH is not set
 # CONFIG_DM_DELAY is not set
-
-#
-# Fusion MPT device support
-#
+# CONFIG_DM_UEVENT is not set
 # 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
 #
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
 # 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=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
 # CONFIG_VETH is not set
-# CONFIG_IP1000 is not set
 # CONFIG_ARCNET is not set
-# CONFIG_PHYLIB 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_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
 CONFIG_LASI_82596=y
@@ -550,13 +609,15 @@
 # CONFIG_DM9102 is not set
 # CONFIG_ULI526X is not set
 # CONFIG_PCMCIA_XIRCOM is not set
-# CONFIG_PCMCIA_XIRTULIP is not set
 # CONFIG_DEPCA 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
@@ -564,7 +625,7 @@
 # CONFIG_AC3200 is not set
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
+# CONFIG_CS89x0 is not set
 # CONFIG_E100 is not set
 # CONFIG_LNE390 is not set
 # CONFIG_FEALNX is not set
@@ -574,19 +635,24 @@
 # CONFIG_ES3210 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_SMSC9420 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_NET_POCKET is not set
+# CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_ACENIC=y
 # CONFIG_ACENIC_OMIT_TIGON_I is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
 # CONFIG_E1000E 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
@@ -594,23 +660,31 @@
 # 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=y
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
 # CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC 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_EN is not set
 # CONFIG_MLX4_CORE is not set
 # CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
 # CONFIG_TR is not set
 
 #
@@ -618,6 +692,11 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 
 #
 # USB Network Adapters
@@ -626,7 +705,6 @@
 # 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=y
 # CONFIG_PCMCIA_3C589 is not set
@@ -654,7 +732,6 @@
 # CONFIG_SLIP is not set
 CONFIG_SLHC=m
 # 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
@@ -676,7 +753,6 @@
 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
 
@@ -699,11 +775,12 @@
 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_ELANTECH is not set
 # CONFIG_MOUSE_PS2_TOUCHKIT is not set
 CONFIG_MOUSE_SERIAL=y
 # CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 CONFIG_MOUSE_HIL=y
 # CONFIG_INPUT_JOYSTICK is not set
@@ -729,10 +806,13 @@
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
 
 #
 # Serial drivers
@@ -759,21 +839,16 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=64
 CONFIG_PRINTER=m
 # CONFIG_LP_CONSOLE is not set
 CONFIG_PPDEV=m
-# CONFIG_TIPAR is not set
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
 
 #
 # PCMCIA character devices
@@ -781,60 +856,70 @@
 # 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_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_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=m
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
 # CONFIG_FB_SYS_FILLRECT is not set
 # CONFIG_FB_SYS_COPYAREA is not set
 # CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
 # CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -860,6 +945,7 @@
 # CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
@@ -868,7 +954,16 @@
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_ARK is not set
 # CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
 # Console display driver support
@@ -896,15 +991,8 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_PARISC_CLUT224=y
-
-#
-# Sound
-#
 CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
 CONFIG_SND=y
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
@@ -920,11 +1008,9 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_VMASTER=y
 CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_VIRMIDI is not set
 # CONFIG_SND_MTPAV is not set
@@ -932,10 +1018,8 @@
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
 # CONFIG_SND_PORTMAN2X4 is not set
-
-#
-# PCI devices
-#
+# CONFIG_SND_AC97_POWER_SAVE is not set
+CONFIG_SND_PCI=y
 CONFIG_SND_AD1889=y
 # CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALI5451 is not set
@@ -944,10 +1028,12 @@
 # CONFIG_SND_AU8810 is not set
 # CONFIG_SND_AU8820 is not set
 # CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 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_DARLA20 is not set
@@ -972,6 +1058,7 @@
 # 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 is not set
@@ -989,58 +1076,67 @@
 # 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
-
-#
-# USB devices
-#
+CONFIG_SND_USB=y
 # CONFIG_SND_USB_AUDIO is not set
 # CONFIG_SND_USB_CAIAQ is not set
-
-#
-# PCMCIA devices
-#
+CONFIG_SND_PCMCIA=y
 # CONFIG_SND_VXPOCKET is not set
 # CONFIG_SND_PDAUDIOCF is not set
-
-#
-# GSC devices
-#
+CONFIG_SND_GSC=y
 CONFIG_SND_HARMONY=y
-
-#
-# System on Chip audio support
-#
 # CONFIG_SND_SOC is not set
-
-#
-# SoC Audio support for SuperH
-#
-
-#
-# Open Sound System
-#
 # CONFIG_SOUND_PRIME is not set
 CONFIG_AC97_BUS=y
 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_HID_FF is not set
+# CONFIG_HID_PID is not set
 # CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF 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
@@ -1049,12 +1145,18 @@
 CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
 # CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_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
@@ -1062,19 +1164,23 @@
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
 # CONFIG_USB_STORAGE is not set
 # CONFIG_USB_LIBUSUAL is not set
@@ -1084,16 +1190,11 @@
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-CONFIG_USB_MON=y
 
 #
 # USB port drivers
 #
 # CONFIG_USB_USS720 is not set
-
-#
-# USB Serial Converter support
-#
 # CONFIG_USB_SERIAL is not set
 
 #
@@ -1102,7 +1203,7 @@
 # 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_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
@@ -1118,38 +1219,60 @@
 # 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_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
 # CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
-# CONFIG_RTC_CLASS 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
 
 #
-# DMA Engine support
+# RTC interfaces
 #
-# CONFIG_DMA_ENGINE 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
 
 #
-# DMA Clients
+# SPI RTC drivers
 #
 
 #
-# DMA Devices
+# Platform RTC drivers
 #
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_PARISC=y
+# CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
-
-#
-# Userspace I/O
-#
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -1159,21 +1282,20 @@
 # 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_EXT4_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=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_BTRFS_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=y
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -1202,16 +1324,13 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_ECRYPT_FS is not set
@@ -1221,33 +1340,32 @@
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_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
 # CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
 # CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
-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_SUNRPC_REGISTER_V4 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 CONFIG_RPCSEC_GSS_SPKM3=m
 CONFIG_SMB_FS=m
@@ -1256,6 +1374,7 @@
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
 # CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
 # CONFIG_CIFS_XATTR is not set
 # CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
@@ -1268,10 +1387,6 @@
 #
 # 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
@@ -1312,33 +1427,28 @@
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
 CONFIG_NLS_UTF8=y
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
 
 #
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-
-#
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -1350,10 +1460,33 @@
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_LIST is not set
-CONFIG_FORCED_INLINING=y
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_NOP_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_BUILD_DOCSRC is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
 # CONFIG_DEBUG_RODATA is not set
 
 #
@@ -1362,56 +1495,112 @@
 CONFIG_KEYS=y
 CONFIG_KEYS_DEBUG_PROC_KEYS=y
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
 CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
 CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
 CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+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 is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_XCBC is not set
-CONFIG_CRYPTO_NULL=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
-# 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=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 is not set
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
+# CONFIG_CRYPTO_SALSA20 is not set
 # CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
 CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_CAMELLIA is not set
-CONFIG_CRYPTO_TEST=m
-# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
index bd9a4db3..5cbe9f9 100644
--- a/arch/parisc/hpux/fs.c
+++ b/arch/parisc/hpux/fs.c
@@ -137,7 +137,6 @@
 			error = count - buf.count;
 	}
 
-out_putf:
 	fput(file);
 out:
 	return error;
diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h
index ffb2088..89fb400 100644
--- a/arch/parisc/include/asm/assembly.h
+++ b/arch/parisc/include/asm/assembly.h
@@ -79,6 +79,7 @@
 
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
+#include <asm/types.h>
 
 #include <asm/asmregs.h>
 
@@ -129,27 +130,27 @@
 
 	/* Shift Left - note the r and t can NOT be the same! */
 	.macro shl r, sa, t
-	dep,z	\r, 31-\sa, 32-\sa, \t
+	dep,z	\r, 31-(\sa), 32-(\sa), \t
 	.endm
 
 	/* The PA 2.0 shift left */
 	.macro shlw r, sa, t
-	depw,z	\r, 31-\sa, 32-\sa, \t
+	depw,z	\r, 31-(\sa), 32-(\sa), \t
 	.endm
 
 	/* And the PA 2.0W shift left */
 	.macro shld r, sa, t
-	depd,z	\r, 63-\sa, 64-\sa, \t
+	depd,z	\r, 63-(\sa), 64-(\sa), \t
 	.endm
 
 	/* Shift Right - note the r and t can NOT be the same! */
 	.macro shr r, sa, t
-	extru \r, 31-\sa, 32-\sa, \t
+	extru \r, 31-(\sa), 32-(\sa), \t
 	.endm
 
 	/* pa20w version of shift right */
 	.macro shrd r, sa, t
-	extrd,u \r, 63-\sa, 64-\sa, \t
+	extrd,u \r, 63-(\sa), 64-(\sa), \t
 	.endm
 
 	/* load 32-bit 'value' into 'reg' compensating for the ldil
diff --git a/arch/parisc/include/asm/io.h b/arch/parisc/include/asm/io.h
index d3031d1..1f6d2ae 100644
--- a/arch/parisc/include/asm/io.h
+++ b/arch/parisc/include/asm/io.h
@@ -174,15 +174,48 @@
 	*(volatile unsigned long long __force *) addr = b;
 }
 
-/* readb can never be const, so use __fswab instead of le*_to_cpu */
-#define readb(addr) __raw_readb(addr)
-#define readw(addr) le16_to_cpu(__raw_readw(addr))
-#define readl(addr) le32_to_cpu(__raw_readl(addr))
-#define readq(addr) le64_to_cpu(__raw_readq(addr))
-#define writeb(b, addr) __raw_writeb(b, addr)
-#define writew(b, addr) __raw_writew(cpu_to_le16(b), addr)
-#define writel(b, addr) __raw_writel(cpu_to_le32(b), addr)
-#define writeq(b, addr) __raw_writeq(cpu_to_le64(b), addr)
+static inline unsigned char readb(const volatile void __iomem *addr)
+{
+	return __raw_readb(addr);
+}
+static inline unsigned short readw(const volatile void __iomem *addr)
+{
+	return le16_to_cpu(__raw_readw(addr));
+}
+static inline unsigned int readl(const volatile void __iomem *addr)
+{
+	return le32_to_cpu(__raw_readl(addr));
+}
+static inline unsigned long long readq(const volatile void __iomem *addr)
+{
+	return le64_to_cpu(__raw_readq(addr));
+}
+
+static inline void writeb(unsigned char b, volatile void __iomem *addr)
+{
+	__raw_writeb(b, addr);
+}
+static inline void writew(unsigned short w, volatile void __iomem *addr)
+{
+	__raw_writew(cpu_to_le16(w), addr);
+}
+static inline void writel(unsigned int l, volatile void __iomem *addr)
+{
+	__raw_writel(cpu_to_le32(l), addr);
+}
+static inline void writeq(unsigned long long q, volatile void __iomem *addr)
+{
+	__raw_writeq(cpu_to_le64(q), addr);
+}
+
+#define	readb	readb
+#define	readw	readw
+#define	readl	readl
+#define readq	readq
+#define writeb	writeb
+#define writew	writew
+#define writel	writel
+#define writeq	writeq
 
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
diff --git a/arch/parisc/include/asm/irq.h b/arch/parisc/include/asm/irq.h
index 399c819..dfa26b6 100644
--- a/arch/parisc/include/asm/irq.h
+++ b/arch/parisc/include/asm/irq.h
@@ -49,7 +49,7 @@
 extern unsigned long txn_affinity_addr(unsigned int irq, int cpu);
 
 extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *);
-extern int cpu_check_affinity(unsigned int irq, cpumask_t *dest);
+extern int cpu_check_affinity(unsigned int irq, const struct cpumask *dest);
 
 /* soft power switch support (power.c) */
 extern struct tasklet_struct power_tasklet;
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index 1c6dbb6..cd4c0b2 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -241,6 +241,7 @@
 #define __copy_to_user_inatomic __copy_to_user
 #define __copy_from_user_inatomic __copy_from_user
 
+struct pt_regs;
 int fixup_exception(struct pt_regs *regs);
 
 #endif /* __PARISC_UACCESS_H */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 5259d8c..837530e 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -551,10 +551,7 @@
 {
 	int sr3;
 
-	if (!vma->vm_mm->context) {
-		BUG();
-		return;
-	}
+	BUG_ON(!vma->vm_mm->context);
 
 	sr3 = mfsp(3);
 	if (vma->vm_mm->context == sr3) {
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index d1fa4ed..0db9fdc 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -368,7 +368,7 @@
 	 * abstractions for the macros */
 	.macro		EXTR	reg1,start,length,reg2
 #ifdef CONFIG_64BIT
-	extrd,u		\reg1,32+\start,\length,\reg2
+	extrd,u		\reg1,32+(\start),\length,\reg2
 #else
 	extrw,u		\reg1,\start,\length,\reg2
 #endif
@@ -376,7 +376,7 @@
 
 	.macro		DEP	reg1,start,length,reg2
 #ifdef CONFIG_64BIT
-	depd		\reg1,32+\start,\length,\reg2
+	depd		\reg1,32+(\start),\length,\reg2
 #else
 	depw		\reg1,\start,\length,\reg2
 #endif
@@ -384,7 +384,7 @@
 
 	.macro		DEPI	val,start,length,reg
 #ifdef CONFIG_64BIT
-	depdi		\val,32+\start,\length,\reg
+	depdi		\val,32+(\start),\length,\reg
 #else
 	depwi		\val,\start,\length,\reg
 #endif
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 03f26bd..f6d2412 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -151,7 +151,7 @@
 }
 
 #ifdef CONFIG_64BIT
-void __init set_firmware_width_unlocked(void)
+void __cpuinit set_firmware_width_unlocked(void)
 {
 	int ret;
 
@@ -168,7 +168,7 @@
  * This function must be called before any pdc_* function that uses the
  * convert_to_wide function.
  */
-void __init set_firmware_width(void)
+void __cpuinit set_firmware_width(void)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&pdc_lock, flags);
@@ -176,11 +176,11 @@
 	spin_unlock_irqrestore(&pdc_lock, flags);
 }
 #else
-void __init set_firmware_width_unlocked(void) {
+void __cpuinit set_firmware_width_unlocked(void) {
 	return;
 }
 
-void __init set_firmware_width(void) {
+void __cpuinit set_firmware_width(void) {
 	return;
 }
 #endif /*CONFIG_64BIT*/
@@ -302,7 +302,7 @@
 	return retval;
 }
 
-int __init pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info)
+int __cpuinit pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info)
 {
 	int ret;
 
@@ -323,7 +323,7 @@
  * This PDC call returns the presence and status of all the coprocessors
  * attached to the processor.
  */
-int __init pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info)
+int __cpuinit pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info)
 {
 	int ret;
 	unsigned long flags;
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index ac2c822..29e70e1 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -112,7 +112,7 @@
 }
 
 #ifdef CONFIG_SMP
-int cpu_check_affinity(unsigned int irq, cpumask_t *dest)
+int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
 {
 	int cpu_dest;
 
@@ -120,23 +120,25 @@
 	if (CHECK_IRQ_PER_CPU(irq)) {
 		/* Bad linux design decision.  The mask has already
 		 * been set; we must reset it */
-		irq_desc[irq].affinity = CPU_MASK_ALL;
+		cpumask_setall(&irq_desc[irq].affinity);
 		return -EINVAL;
 	}
 
 	/* whatever mask they set, we just allow one CPU */
 	cpu_dest = first_cpu(*dest);
-	*dest = cpumask_of_cpu(cpu_dest);
 
-	return 0;
+	return cpu_dest;
 }
 
 static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
 {
-	if (cpu_check_affinity(irq, dest))
+	int cpu_dest;
+
+	cpu_dest = cpu_check_affinity(irq, dest);
+	if (cpu_dest < 0)
 		return;
 
-	irq_desc[irq].affinity = *dest;
+	cpumask_copy(&irq_desc[irq].affinity, &cpumask_of_cpu(cpu_dest));
 }
 #endif
 
@@ -295,7 +297,7 @@
 unsigned long txn_affinity_addr(unsigned int irq, int cpu)
 {
 #ifdef CONFIG_SMP
-	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+	cpumask_copy(&irq_desc[irq].affinity, cpumask_of(cpu));
 #endif
 
 	return per_cpu(cpu_data, cpu).txn_addr;
@@ -352,7 +354,7 @@
 	irq = eirr_to_irq(eirr_val);
 
 #ifdef CONFIG_SMP
-	dest = irq_desc[irq].affinity;
+	cpumask_copy(&dest, &irq_desc[irq].affinity);
 	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) &&
 	    !cpu_isset(smp_processor_id(), dest)) {
 		int cpu = first_cpu(dest);
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index df47895..7d927ea 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -447,10 +447,7 @@
 
 static dma_addr_t pa11_dma_map_single(struct device *dev, void *addr, size_t size, enum dma_data_direction direction)
 {
-	if (direction == DMA_NONE) {
-		printk(KERN_ERR "pa11_dma_map_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
-		BUG();
-	}
+	BUG_ON(direction == DMA_NONE);
 
 	flush_kernel_dcache_range((unsigned long) addr, size);
 	return virt_to_phys(addr);
@@ -458,10 +455,7 @@
 
 static void pa11_dma_unmap_single(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
 {
-	if (direction == DMA_NONE) {
-		printk(KERN_ERR "pa11_dma_unmap_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
-		BUG();
-	}
+	BUG_ON(direction == DMA_NONE);
 
 	if (direction == DMA_TO_DEVICE)
 	    return;
@@ -480,8 +474,7 @@
 {
 	int i;
 
-	if (direction == DMA_NONE)
-	    BUG();
+	BUG_ON(direction == DMA_NONE);
 
 	for (i = 0; i < nents; i++, sglist++ ) {
 		unsigned long vaddr = sg_virt_addr(sglist);
@@ -496,8 +489,7 @@
 {
 	int i;
 
-	if (direction == DMA_NONE)
-	    BUG();
+	BUG_ON(direction == DMA_NONE);
 
 	if (direction == DMA_TO_DEVICE)
 	    return;
@@ -511,16 +503,14 @@
 
 static void pa11_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction)
 {
-	if (direction == DMA_NONE)
-	    BUG();
+	BUG_ON(direction == DMA_NONE);
 
 	flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size);
 }
 
 static void pa11_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction)
 {
-	if (direction == DMA_NONE)
-	    BUG();
+	BUG_ON(direction == DMA_NONE);
 
 	flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size);
 }
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 7c155c2..9d704d9 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -304,10 +304,8 @@
 	 */
 	max_low_pfn = max_pfn;
 
-	if ((bootmap_pfn - bootmap_start_pfn) != bootmap_pages) {
-		printk(KERN_WARNING "WARNING! bootmap sizing is messed up!\n");
-		BUG();
-	}
+	/* bootmap sizing messed up? */
+	BUG_ON((bootmap_pfn - bootmap_start_pfn) != bootmap_pages);
 
 	/* reserve PAGE0 pdc memory, kernel text/data/bss & bootmap */
 
diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
index 8b5ba82..4447def 100644
--- a/arch/powerpc/boot/dts/canyonlands.dts
+++ b/arch/powerpc/boot/dts/canyonlands.dts
@@ -127,6 +127,13 @@
 			dcr-reg = <0x010 0x002>;
 		};
 
+		CRYPTO: crypto@180000 {
+			compatible = "amcc,ppc460ex-crypto", "amcc,ppc4xx-crypto";
+			reg = <4 0x00180000 0x80400>;
+			interrupt-parent = <&UIC0>;
+			interrupts = <0x1d 0x4>;
+		};
+
 		MAL0: mcmal {
 			compatible = "ibm,mcmal-460ex", "ibm,mcmal2";
 			dcr-reg = <0x180 0x062>;
diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts
index 2804444..5e6b08f 100644
--- a/arch/powerpc/boot/dts/kilauea.dts
+++ b/arch/powerpc/boot/dts/kilauea.dts
@@ -97,6 +97,13 @@
 				      0x6 0x4>;	/* ECC SEC Error */ 
 		};
 
+		CRYPTO: crypto@ef700000 {
+			compatible = "amcc,ppc405ex-crypto", "amcc,ppc4xx-crypto";
+			reg = <0xef700000 0x80400>;
+			interrupt-parent = <&UIC0>;
+			interrupts = <0x17 0x2>;
+		};
+
 		MAL0: mcmal {
 			compatible = "ibm,mcmal-405ex", "ibm,mcmal2";
 			dcr-reg = <0x180 0x062>;
diff --git a/arch/powerpc/configs/40x/virtex_defconfig b/arch/powerpc/configs/40x/virtex_defconfig
index b6888384..f5698f9 100644
--- a/arch/powerpc/configs/40x/virtex_defconfig
+++ b/arch/powerpc/configs/40x/virtex_defconfig
@@ -686,7 +686,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
-# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
diff --git a/arch/powerpc/configs/44x/virtex5_defconfig b/arch/powerpc/configs/44x/virtex5_defconfig
index 15aab1c..1bf0a63 100644
--- a/arch/powerpc/configs/44x/virtex5_defconfig
+++ b/arch/powerpc/configs/44x/virtex5_defconfig
@@ -691,7 +691,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
-# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index aa5855a..15900dc 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 15:35:29 2009
+# Linux kernel version: 2.6.29-rc6
+# Fri Mar  6 00:07:38 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -71,6 +71,15 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -88,6 +97,7 @@
 # CONFIG_IPC_NS is not set
 # CONFIG_USER_NS is not set
 # CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -153,11 +163,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -294,7 +299,6 @@
 #
 # Networking options
 #
-# CONFIG_NET_NS is not set
 CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
@@ -508,8 +512,8 @@
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_OF_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
 # CONFIG_MTD_AR7_PARTS is not set
 
 #
@@ -587,7 +591,6 @@
 # LPDDR flash memory drivers
 #
 # CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
 
 #
 # UBI - Unsorted block images
@@ -617,13 +620,19 @@
 # CONFIG_BLK_DEV_HD 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_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_HP_ILO is not set
 # CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=m
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -839,6 +848,7 @@
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
 # CONFIG_JME is not set
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
@@ -1037,8 +1047,6 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-CONFIG_EEPROM_LEGACY=m
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index b6eee7c..ac14f52 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc3
-# Wed Aug 20 08:16:53 2008
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 09:28:45 2009
 #
 CONFIG_PPC64=y
 
@@ -16,13 +16,14 @@
 CONFIG_ALTIVEC=y
 # CONFIG_VSX is not set
 CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_64=y
 CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_64BIT=y
 CONFIG_WORD_SIZE=64
-CONFIG_PPC_MERGE=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
 CONFIG_MMU=y
 CONFIG_GENERIC_CMOS_UPDATE=y
 CONFIG_GENERIC_TIME=y
@@ -46,7 +47,7 @@
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_PPC_OF=y
 CONFIG_OF=y
@@ -74,10 +75,19 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
@@ -86,11 +96,13 @@
 # CONFIG_IPC_NS is not set
 # CONFIG_USER_NS is not set
 # CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
-# CONFIG_EMBEDDED is not set
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
@@ -99,37 +111,36 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-# CONFIG_COMPAT_BRK is not set
 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_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
-# CONFIG_MARKERS is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=m
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_SYSCALL_WRAPPERS=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT 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_FORCE_LOAD is not set
@@ -137,7 +148,6 @@
 # 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_BLK_DEV_IO_TRACE is not set
@@ -157,7 +167,7 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
 
 #
 # Platform support
@@ -183,18 +193,20 @@
 CONFIG_PS3_DISK=y
 CONFIG_PS3_ROM=y
 CONFIG_PS3_FLASH=y
-CONFIG_OPROFILE_PS3=y
+CONFIG_PS3_VRAM=m
 CONFIG_PS3_LPM=m
 CONFIG_PPC_CELL=y
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
 # CONFIG_PPC_CELLEB is not set
+# CONFIG_PPC_CELL_QPACE is not set
 
 #
 # Cell Broadband Engine options
 #
 CONFIG_SPU_FS=y
 CONFIG_SPU_FS_64K_LS=y
+# CONFIG_SPU_TRACE is not set
 CONFIG_SPU_BASE=y
 # CONFIG_PQ2ADS is not set
 # CONFIG_IPIC is not set
@@ -210,6 +222,7 @@
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
 
 #
 # Kernel options
@@ -229,6 +242,8 @@
 # CONFIG_PREEMPT is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
 # CONFIG_IOMMU_VMERGE is not set
@@ -251,7 +266,6 @@
 CONFIG_SPARSEMEM_MANUAL=y
 CONFIG_SPARSEMEM=y
 CONFIG_HAVE_MEMORY_PRESENT=y
-# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPARSEMEM_EXTREME=y
 CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
 # CONFIG_SPARSEMEM_VMEMMAP is not set
@@ -261,11 +275,14 @@
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
+CONFIG_UNEVICTABLE_LRU=y
 CONFIG_ARCH_MEMORY_PROBE=y
 CONFIG_PPC_HAS_HASH_64K=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_SCHED_SMT=y
@@ -299,6 +316,7 @@
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -361,6 +379,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -371,6 +390,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -392,39 +412,37 @@
 #
 # Bluetooth device drivers
 #
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIBTUSB=m
 # CONFIG_BT_HCIUART is not set
 # CONFIG_BT_HCIBCM203X is not set
 # CONFIG_BT_HCIBPA10X is not set
 # CONFIG_BT_HCIBFUSB is not set
 # CONFIG_BT_HCIVHCI is not set
 # CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
 CONFIG_CFG80211=m
+# CONFIG_CFG80211_REG_DEBUG is not set
 CONFIG_NL80211=y
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
 CONFIG_WIRELESS_EXT=y
 # CONFIG_WIRELESS_EXT_SYSFS is not set
+# CONFIG_LIB80211 is not set
 CONFIG_MAC80211=m
 
 #
 # Rate control algorithm selection
 #
 CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
 CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
 CONFIG_MAC80211_RC_DEFAULT="pid"
 # CONFIG_MAC80211_MESH is not set
 # CONFIG_MAC80211_LEDS is not set
 # CONFIG_MAC80211_DEBUGFS is not set
 # CONFIG_MAC80211_DEBUG_MENU 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_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -450,6 +468,7 @@
 CONFIG_MTD_DEBUG_VERBOSE=0
 # CONFIG_MTD_CONCAT is not set
 # CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_TESTS is not set
 
 #
 # User Modules And Translation Layers
@@ -494,7 +513,6 @@
 #
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
-CONFIG_MTD_PS3VRAM=y
 # CONFIG_MTD_MTDRAM is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
@@ -508,6 +526,11 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -528,8 +551,13 @@
 # CONFIG_ATA_OVER_ETH is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -575,7 +603,17 @@
 # CONFIG_SCSI_LOWLEVEL is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
-# CONFIG_MD is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
@@ -591,6 +629,9 @@
 # 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_GELIC_NET=y
@@ -604,6 +645,7 @@
 # CONFIG_WLAN_PRE80211 is not set
 CONFIG_WLAN_80211=y
 # CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
 # CONFIG_USB_ZD1201 is not set
 # CONFIG_USB_NET_RNDIS_WLAN is not set
 # CONFIG_RTL8187 is not set
@@ -615,13 +657,11 @@
 # CONFIG_B43LEGACY is not set
 CONFIG_ZD1211RW=m
 # CONFIG_ZD1211RW_DEBUG is not set
-CONFIG_RT2X00=m
-CONFIG_RT2X00_LIB=m
-CONFIG_RT2X00_LIB_USB=m
-CONFIG_RT2X00_LIB_FIRMWARE=y
-# CONFIG_RT2500USB is not set
-CONFIG_RT73USB=m
-# CONFIG_RT2X00_DEBUG is not set
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 
 #
 # USB Network Adapters
@@ -634,6 +674,7 @@
 CONFIG_USB_NET_AX8817X=m
 # CONFIG_USB_NET_CDCETHER is not set
 # CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SMSC95XX is not set
 # CONFIG_USB_NET_GL620A is not set
 # CONFIG_USB_NET_NET1080 is not set
 # CONFIG_USB_NET_PLUSB is not set
@@ -664,7 +705,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_POLLDEV is not set
 
 #
@@ -735,8 +776,10 @@
 # Non-8250 serial port support
 #
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_HVC_UDBG is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_R3964 is not set
@@ -753,11 +796,11 @@
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
@@ -767,6 +810,7 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -792,6 +836,7 @@
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
@@ -817,6 +862,8 @@
 CONFIG_FB_PS3=y
 CONFIG_FB_PS3_DEFAULT_SIZE_M=9
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -841,6 +888,7 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 CONFIG_LOGO_LINUX_CLUT224=y
 CONFIG_SOUND=m
+# CONFIG_SOUND_OSS_CORE is not set
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
@@ -849,6 +897,7 @@
 # CONFIG_SND_SEQUENCER is not set
 # CONFIG_SND_MIXER_OSS is not set
 # CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
 # CONFIG_SND_DYNAMIC_MINORS is not set
 CONFIG_SND_SUPPORT_OLD_API=y
 CONFIG_SND_VERBOSE_PROCFS=y
@@ -873,15 +922,40 @@
 # USB Input Devices
 #
 CONFIG_USB_HID=m
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
 
 #
 # USB HID Boot Protocol drivers
 #
 # CONFIG_USB_KBD is not set
 # CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_COMPAT is not set
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -898,7 +972,11 @@
 # CONFIG_USB_DYNAMIC_MINORS is not set
 CONFIG_USB_SUSPEND=y
 # CONFIG_USB_OTG is not set
-CONFIG_USB_MON=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
@@ -909,6 +987,7 @@
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
 CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
 # CONFIG_USB_EHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=m
@@ -918,6 +997,7 @@
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
 
 #
 # Enable Host or Gadget support to see Inventra options
@@ -929,20 +1009,20 @@
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 # CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=m
 # 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
@@ -950,7 +1030,6 @@
 # CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_STORAGE_ONETOUCH is not set
 # CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_SIERRA is not set
 # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_LIBUSUAL is not set
 
@@ -971,6 +1050,7 @@
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
 # CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
@@ -988,7 +1068,12 @@
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
@@ -1014,12 +1099,15 @@
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
 # CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
@@ -1028,6 +1116,7 @@
 CONFIG_RTC_DRV_PPC=m
 # CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -1035,26 +1124,35 @@
 CONFIG_EXT2_FS=m
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS=m
 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_EXT4_FS=y
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=m
 # CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_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_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 CONFIG_QUOTA=y
 # CONFIG_QUOTA_NETLINK_INTERFACE is not set
 CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
 # CONFIG_QFMT_V1 is not set
 CONFIG_QFMT_V2=y
 CONFIG_QUOTACTL=y
@@ -1087,16 +1185,14 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1106,6 +1202,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -1126,6 +1223,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1190,9 +1288,9 @@
 # Library routines
 #
 CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
 CONFIG_CRC_T10DIF=y
 CONFIG_CRC_ITU_T=m
 CONFIG_CRC32=y
@@ -1250,27 +1348,44 @@
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DEBUG_LIST=y
 # CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_NOTIFIERS is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
 # CONFIG_XMON is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_VIRQ_DEBUG is not set
@@ -1282,16 +1397,26 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
 
 #
 # Crypto core or helper
 #
+# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
 CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
 CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
 CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
 CONFIG_CRYPTO_GF128MUL=m
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
@@ -1363,6 +1488,11 @@
 #
 # CONFIG_CRYPTO_DEFLATE is not set
 CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_PPC_CLOCK is not set
 # CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/storcenter_defconfig b/arch/powerpc/configs/storcenter_defconfig
index 86512c8..9490346 100644
--- a/arch/powerpc/configs/storcenter_defconfig
+++ b/arch/powerpc/configs/storcenter_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 15:35:46 2009
+# Linux kernel version: 2.6.29-rc6
+# Fri Mar  6 00:09:08 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -71,6 +71,15 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
@@ -144,11 +153,6 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -377,8 +381,8 @@
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_OF_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
 # CONFIG_MTD_AR7_PARTS is not set
 
 #
@@ -452,7 +456,6 @@
 # LPDDR flash memory drivers
 #
 # CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
 
 #
 # UBI - Unsorted block images
@@ -478,13 +481,19 @@
 # CONFIG_BLK_DEV_HD 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_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_HP_ILO is not set
 # CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -677,6 +686,7 @@
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
 # CONFIG_JME is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
@@ -818,8 +828,6 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
@@ -1159,6 +1167,7 @@
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_EXPORTFS=m
 
 #
 # Partition Types
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 4911104..21172ba 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -241,9 +241,11 @@
 /* We need to mark all pages as being coherent if we're SMP or we have a
  * 74[45]x and an MPC107 host bridge. Also 83xx and PowerQUICC II
  * require it for PCI "streaming/prefetch" to work properly.
+ * This is also required by 52xx family.
  */
 #if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) \
-	|| defined(CONFIG_PPC_83xx) || defined(CONFIG_8260)
+	|| defined(CONFIG_PPC_83xx) || defined(CONFIG_8260) \
+	|| defined(CONFIG_PPC_MPC52xx)
 #define CPU_FTR_COMMON                  CPU_FTR_NEED_COHERENT
 #else
 #define CPU_FTR_COMMON                  0
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index a1c4cfd..d794a63 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -511,8 +511,11 @@
 	and	r1,r1,r2		/* writable if _RW and _DIRTY */
 	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
 	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
-	ori	r1,r1,0xe14		/* clear out reserved bits and M */
+	ori	r1,r1,0xe04		/* clear out reserved bits */
 	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
+BEGIN_FTR_SECTION
+	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
+END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
 	mtspr	SPRN_RPA,r1
 	mfspr	r3,SPRN_IMISS
 	tlbli	r3
@@ -585,8 +588,11 @@
 	and	r1,r1,r2		/* writable if _RW and _DIRTY */
 	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
 	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
-	ori	r1,r1,0xe14		/* clear out reserved bits and M */
+	ori	r1,r1,0xe04		/* clear out reserved bits */
 	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
+BEGIN_FTR_SECTION
+	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
+END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
 	mtspr	SPRN_RPA,r1
 	mfspr	r3,SPRN_DMISS
 	tlbld	r3
@@ -653,8 +659,11 @@
 	stw	r3,0(r2)		/* update PTE (accessed/dirty bits) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
 	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
-	li	r1,0xe15		/* clear out reserved bits and M */
+	li	r1,0xe05		/* clear out reserved bits & PP lsb */
 	andc	r1,r3,r1		/* PP = user? 2: 0 */
+BEGIN_FTR_SECTION
+	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
+END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
 	mtspr	SPRN_RPA,r1
 	mfspr	r3,SPRN_DMISS
 	tlbld	r3
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index 2ca7be6..244f997 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -12,7 +12,6 @@
 
 #include <linux/kernel.h>
 #include <linux/initrd.h>
-#include <linux/mtd/physmap.h>
 #include <linux/of_platform.h>
 
 #include <asm/time.h>
@@ -22,39 +21,6 @@
 
 #include "mpc10x.h"
 
-static struct mtd_partition linkstation_physmap_partitions[] = {
-	{
-		.name   = "mtd_firmimg",
-		.offset = 0x000000,
-		.size   = 0x300000,
-	},
-	{
-		.name   = "mtd_bootcode",
-		.offset = 0x300000,
-		.size   = 0x070000,
-	},
-	{
-		.name   = "mtd_status",
-		.offset = 0x370000,
-		.size   = 0x010000,
-	},
-	{
-		.name   = "mtd_conf",
-		.offset = 0x380000,
-		.size   = 0x080000,
-	},
-	{
-		.name   = "mtd_allflash",
-		.offset = 0x000000,
-		.size   = 0x400000,
-	},
-	{
-		.name   = "mtd_data",
-		.offset = 0x310000,
-		.size   = 0x0f0000,
-	},
-};
-
 static __initdata struct of_device_id of_bus_ids[] = {
 	{ .type = "soc", },
 	{ .compatible = "simple-bus", },
@@ -99,10 +65,6 @@
 static void __init linkstation_setup_arch(void)
 {
 	struct device_node *np;
-#ifdef CONFIG_MTD_PHYSMAP
-	physmap_set_partitions(linkstation_physmap_partitions,
-			       ARRAY_SIZE(linkstation_physmap_partitions));
-#endif
 
 	/* Lookup PCI host bridges */
 	for_each_compatible_node(np, "pci", "mpc10x-pci")
diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c
index 8864e48..613070e 100644
--- a/arch/powerpc/platforms/embedded6xx/storcenter.c
+++ b/arch/powerpc/platforms/embedded6xx/storcenter.c
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/initrd.h>
-#include <linux/mtd/physmap.h>
 #include <linux/of_platform.h>
 
 #include <asm/system.h>
@@ -26,32 +25,6 @@
 #include "mpc10x.h"
 
 
-#ifdef CONFIG_MTD_PHYSMAP
-static struct mtd_partition storcenter_physmap_partitions[] = {
-	{
-		.name   = "kernel",
-		.offset = 0x000000,
-		.size   = 0x170000,
-	},
-	{
-		.name   = "rootfs",
-		.offset = 0x170000,
-		.size   = 0x590000,
-	},
-	{
-		.name   = "uboot",
-		.offset = 0x700000,
-		.size   = 0x040000,
-	},
-	{
-		.name   = "config",
-		.offset = 0x740000,
-		.size   = 0x0c0000,
-	},
-};
-#endif
-
-
 static __initdata struct of_device_id storcenter_of_bus[] = {
 	{ .name = "soc", },
 	{},
@@ -96,11 +69,6 @@
 {
 	struct device_node *np;
 
-#ifdef CONFIG_MTD_PHYSMAP
-	physmap_set_partitions(storcenter_physmap_partitions,
-			       ARRAY_SIZE(storcenter_physmap_partitions));
-#endif
-
 	/* Lookup PCI host bridges */
 	for_each_compatible_node(np, "pci", "mpc10x-pci")
 		storcenter_add_bridge(np);
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 920cf7a..740ef56 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -128,6 +128,13 @@
 	  be disabled on the kernel command line using "ps3flash=off", to
 	  not allocate this fixed buffer.
 
+config PS3_VRAM
+	tristate "PS3 Video RAM Storage Driver"
+	depends on FB_PS3=y && BLOCK && m
+	help
+	  This driver allows you to use excess PS3 video RAM as volatile
+	  storage or system swap.
+
 config PS3_LPM
 	tristate "PS3 Logical Performance Monitor support"
 	depends on PPC_PS3
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 58311a8..a705fff 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -376,7 +376,7 @@
 	struct ps3_system_bus_driver *drv;
 
 	BUG_ON(!dev);
-	pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
+	dev_dbg(_dev, "%s:%d\n", __func__, __LINE__);
 
 	drv = ps3_system_bus_dev_to_system_bus_drv(dev);
 	BUG_ON(!drv);
@@ -398,7 +398,7 @@
 	struct ps3_system_bus_driver *drv;
 
 	BUG_ON(!dev);
-	pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
+	dev_dbg(_dev, "%s:%d\n", __func__, __LINE__);
 
 	drv = ps3_system_bus_dev_to_system_bus_drv(dev);
 	BUG_ON(!drv);
diff --git a/arch/s390/crypto/sha.h b/arch/s390/crypto/sha.h
index 1ceafa5..f4e9dc7 100644
--- a/arch/s390/crypto/sha.h
+++ b/arch/s390/crypto/sha.h
@@ -29,7 +29,9 @@
 	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);
+struct shash_desc;
+
+int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len);
+int s390_sha_final(struct shash_desc *desc, u8 *out);
 
 #endif
diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c
index b3cb5a8..e85ba34 100644
--- a/arch/s390/crypto/sha1_s390.c
+++ b/arch/s390/crypto/sha1_s390.c
@@ -23,17 +23,17 @@
  * any later version.
  *
  */
+#include <crypto/internal/hash.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/crypto.h>
 #include <crypto/sha.h>
 
 #include "crypt_s390.h"
 #include "sha.h"
 
-static void sha1_init(struct crypto_tfm *tfm)
+static int sha1_init(struct shash_desc *desc)
 {
-	struct s390_sha_ctx *sctx = crypto_tfm_ctx(tfm);
+	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
 
 	sctx->state[0] = SHA1_H0;
 	sctx->state[1] = SHA1_H1;
@@ -42,34 +42,36 @@
 	sctx->state[4] = SHA1_H4;
 	sctx->count = 0;
 	sctx->func = KIMD_SHA_1;
+
+	return 0;
 }
 
-static struct crypto_alg alg = {
-	.cra_name	=	"sha1",
-	.cra_driver_name=	"sha1-s390",
-	.cra_priority	=	CRYPT_S390_PRIORITY,
-	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
-	.cra_blocksize	=	SHA1_BLOCK_SIZE,
-	.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	=	s390_sha_update,
-	.dia_final	=	s390_sha_final } }
+static struct shash_alg alg = {
+	.digestsize	=	SHA1_DIGEST_SIZE,
+	.init		=	sha1_init,
+	.update		=	s390_sha_update,
+	.final		=	s390_sha_final,
+	.descsize	=	sizeof(struct s390_sha_ctx),
+	.base		=	{
+		.cra_name	=	"sha1",
+		.cra_driver_name=	"sha1-s390",
+		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA1_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
 };
 
 static int __init sha1_s390_init(void)
 {
 	if (!crypt_s390_func_available(KIMD_SHA_1))
 		return -EOPNOTSUPP;
-	return crypto_register_alg(&alg);
+	return crypto_register_shash(&alg);
 }
 
 static void __exit sha1_s390_fini(void)
 {
-	crypto_unregister_alg(&alg);
+	crypto_unregister_shash(&alg);
 }
 
 module_init(sha1_s390_init);
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
index 19c03fb..f9fefc5 100644
--- a/arch/s390/crypto/sha256_s390.c
+++ b/arch/s390/crypto/sha256_s390.c
@@ -16,17 +16,17 @@
  * any later version.
  *
  */
+#include <crypto/internal/hash.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/crypto.h>
 #include <crypto/sha.h>
 
 #include "crypt_s390.h"
 #include "sha.h"
 
-static void sha256_init(struct crypto_tfm *tfm)
+static int sha256_init(struct shash_desc *desc)
 {
-	struct s390_sha_ctx *sctx = crypto_tfm_ctx(tfm);
+	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
 
 	sctx->state[0] = SHA256_H0;
 	sctx->state[1] = SHA256_H1;
@@ -38,22 +38,24 @@
 	sctx->state[7] = SHA256_H7;
 	sctx->count = 0;
 	sctx->func = KIMD_SHA_256;
+
+	return 0;
 }
 
-static struct crypto_alg alg = {
-	.cra_name	=	"sha256",
-	.cra_driver_name =	"sha256-s390",
-	.cra_priority	=	CRYPT_S390_PRIORITY,
-	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
-	.cra_blocksize	=	SHA256_BLOCK_SIZE,
-	.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	=	s390_sha_update,
-	.dia_final	=	s390_sha_final } }
+static struct shash_alg alg = {
+	.digestsize	=	SHA256_DIGEST_SIZE,
+	.init		=	sha256_init,
+	.update		=	s390_sha_update,
+	.final		=	s390_sha_final,
+	.descsize	=	sizeof(struct s390_sha_ctx),
+	.base		=	{
+		.cra_name	=	"sha256",
+		.cra_driver_name=	"sha256-s390",
+		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA256_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
 };
 
 static int sha256_s390_init(void)
@@ -61,12 +63,12 @@
 	if (!crypt_s390_func_available(KIMD_SHA_256))
 		return -EOPNOTSUPP;
 
-	return crypto_register_alg(&alg);
+	return crypto_register_shash(&alg);
 }
 
 static void __exit sha256_s390_fini(void)
 {
-	crypto_unregister_alg(&alg);
+	crypto_unregister_shash(&alg);
 }
 
 module_init(sha256_s390_init);
diff --git a/arch/s390/crypto/sha512_s390.c b/arch/s390/crypto/sha512_s390.c
index 23c7861..83192bf 100644
--- a/arch/s390/crypto/sha512_s390.c
+++ b/arch/s390/crypto/sha512_s390.c
@@ -12,16 +12,16 @@
  * any later version.
  *
  */
+#include <crypto/internal/hash.h>
 #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)
+static int sha512_init(struct shash_desc *desc)
 {
-	struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
 
 	*(__u64 *)&ctx->state[0] = 0x6a09e667f3bcc908ULL;
 	*(__u64 *)&ctx->state[2] = 0xbb67ae8584caa73bULL;
@@ -33,29 +33,31 @@
 	*(__u64 *)&ctx->state[14] = 0x5be0cd19137e2179ULL;
 	ctx->count = 0;
 	ctx->func = KIMD_SHA_512;
+
+	return 0;
 }
 
-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 } }
+static struct shash_alg sha512_alg = {
+	.digestsize	=	SHA512_DIGEST_SIZE,
+	.init		=	sha512_init,
+	.update		=	s390_sha_update,
+	.final		=	s390_sha_final,
+	.descsize	=	sizeof(struct s390_sha_ctx),
+	.base		=	{
+		.cra_name	=	"sha512",
+		.cra_driver_name=	"sha512-s390",
+		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA512_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
 };
 
 MODULE_ALIAS("sha512");
 
-static void sha384_init(struct crypto_tfm *tfm)
+static int sha384_init(struct shash_desc *desc)
 {
-	struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
 
 	*(__u64 *)&ctx->state[0] = 0xcbbb9d5dc1059ed8ULL;
 	*(__u64 *)&ctx->state[2] = 0x629a292a367cd507ULL;
@@ -67,22 +69,25 @@
 	*(__u64 *)&ctx->state[14] = 0x47b5481dbefa4fa4ULL;
 	ctx->count = 0;
 	ctx->func = KIMD_SHA_512;
+
+	return 0;
 }
 
-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 } }
+static struct shash_alg sha384_alg = {
+	.digestsize	=	SHA384_DIGEST_SIZE,
+	.init		=	sha384_init,
+	.update		=	s390_sha_update,
+	.final		=	s390_sha_final,
+	.descsize	=	sizeof(struct s390_sha_ctx),
+	.base		=	{
+		.cra_name	=	"sha384",
+		.cra_driver_name=	"sha384-s390",
+		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA384_BLOCK_SIZE,
+		.cra_ctxsize	=	sizeof(struct s390_sha_ctx),
+		.cra_module	=	THIS_MODULE,
+	}
 };
 
 MODULE_ALIAS("sha384");
@@ -93,18 +98,18 @@
 
 	if (!crypt_s390_func_available(KIMD_SHA_512))
 		return -EOPNOTSUPP;
-	if ((ret = crypto_register_alg(&sha512_alg)) < 0)
+	if ((ret = crypto_register_shash(&sha512_alg)) < 0)
 		goto out;
-	if ((ret = crypto_register_alg(&sha384_alg)) < 0)
-		crypto_unregister_alg(&sha512_alg);
+	if ((ret = crypto_register_shash(&sha384_alg)) < 0)
+		crypto_unregister_shash(&sha512_alg);
 out:
 	return ret;
 }
 
 static void __exit fini(void)
 {
-	crypto_unregister_alg(&sha512_alg);
-	crypto_unregister_alg(&sha384_alg);
+	crypto_unregister_shash(&sha512_alg);
+	crypto_unregister_shash(&sha384_alg);
 }
 
 module_init(init);
diff --git a/arch/s390/crypto/sha_common.c b/arch/s390/crypto/sha_common.c
index 9d6eb8c..7903ec4 100644
--- a/arch/s390/crypto/sha_common.c
+++ b/arch/s390/crypto/sha_common.c
@@ -13,14 +13,14 @@
  *
  */
 
-#include <linux/crypto.h>
+#include <crypto/internal/hash.h>
 #include "sha.h"
 #include "crypt_s390.h"
 
-void s390_sha_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
+int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
 {
-	struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
-	unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
+	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
+	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
 	unsigned int index;
 	int ret;
 
@@ -51,13 +51,15 @@
 store:
 	if (len)
 		memcpy(ctx->buf + index , data, len);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(s390_sha_update);
 
-void s390_sha_final(struct crypto_tfm *tfm, u8 *out)
+int s390_sha_final(struct shash_desc *desc, u8 *out)
 {
-	struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
-	unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
+	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
+	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
 	u64 bits;
 	unsigned int index, end, plen;
 	int ret;
@@ -87,9 +89,11 @@
 	BUG_ON(ret != end);
 
 	/* copy digest to out */
-	memcpy(out, ctx->state, crypto_hash_digestsize(crypto_hash_cast(tfm)));
+	memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
 	/* wipe context */
 	memset(ctx, 0, sizeof *ctx);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(s390_sha_final);
 
diff --git a/arch/s390/include/asm/mman.h b/arch/s390/include/asm/mman.h
index 7839767..da01432 100644
--- a/arch/s390/include/asm/mman.h
+++ b/arch/s390/include/asm/mman.h
@@ -22,4 +22,9 @@
 #define MCL_CURRENT	1		/* lock all current mappings */
 #define MCL_FUTURE	2		/* lock all future mappings */
 
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__) && defined(CONFIG_64BIT)
+int s390_mmap_check(unsigned long addr, unsigned long len);
+#define arch_mmap_check(addr,len,flags)	s390_mmap_check(addr,len)
+#endif
+
 #endif /* __S390_MMAN_H__ */
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 066b995..db4523f 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -61,7 +61,7 @@
 extern int get_cpu_capability(unsigned int *);
 
 /*
- * User space process size: 2GB for 31 bit, 4TB for 64 bit.
+ * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
  */
 #ifndef __s390x__
 
@@ -70,8 +70,7 @@
 
 #else /* __s390x__ */
 
-#define TASK_SIZE_OF(tsk)	(test_tsk_thread_flag(tsk,TIF_31BIT) ? \
-					(1UL << 31) : (1UL << 53))
+#define TASK_SIZE_OF(tsk)	((tsk)->mm->context.asce_limit)
 #define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_31BIT) ? \
 					(1UL << 30) : (1UL << 41))
 #define TASK_SIZE		TASK_SIZE_OF(current)
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index c93eb50..c979c3b 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -30,6 +30,8 @@
 };
 #endif
 
+#define SD_MC_INIT SD_CPU_INIT
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_S390_TOPOLOGY_H */
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 397d131..8064122 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -5,6 +5,8 @@
  *
  */
 
+#include <asm/asm-offsets.h>
+
 #ifndef CONFIG_64BIT
 .globl _mcount
 _mcount:
@@ -14,7 +16,7 @@
 	ahi	%r15,-96
 	l	%r3,100(%r15)
 	la	%r2,0(%r14)
-	st	%r1,0(%r15)
+	st	%r1,__SF_BACKCHAIN(%r15)
 	la	%r3,0(%r3)
 	bras	%r14,0f
 	.long	ftrace_trace_function
@@ -38,7 +40,7 @@
 	stg	%r14,112(%r15)
 	lgr	%r1,%r15
 	aghi	%r15,-160
-	stg	%r1,0(%r15)
+	stg	%r1,__SF_BACKCHAIN(%r15)
 	lgr	%r2,%r14
 	lg	%r3,168(%r15)
 	larl	%r14,ftrace_trace_function
diff --git a/arch/s390/lib/div64.c b/arch/s390/lib/div64.c
index a5f8300..d9e62c0 100644
--- a/arch/s390/lib/div64.c
+++ b/arch/s390/lib/div64.c
@@ -61,7 +61,7 @@
 		"	clr	%0,%3\n"
 		"	jl	0f\n"
 		"	slr	%0,%3\n"
-		"	alr	%1,%2\n"
+		"	ahi	%1,1\n"
 		"0:\n"
 		: "+d" (reg2), "+d" (reg3), "=d" (tmp)
 		: "d" (base), "2" (1UL) : "cc" );
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index d66215b..b0b84c3 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -119,8 +119,6 @@
 			goto fault;
 
 		pfn = pte_pfn(*pte);
-		if (!pfn_valid(pfn))
-			goto out;
 
 		offset = uaddr & (PAGE_SIZE - 1);
 		size = min(n - done, PAGE_SIZE - offset);
@@ -135,7 +133,6 @@
 		done += size;
 		uaddr += size;
 	} while (done < n);
-out:
 	spin_unlock(&mm->page_table_lock);
 	return n - done;
 fault:
@@ -163,9 +160,6 @@
 		goto fault;
 
 	pfn = pte_pfn(*pte);
-	if (!pfn_valid(pfn))
-		goto out;
-
 	ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
 out:
 	return ret;
@@ -244,11 +238,6 @@
 			goto fault;
 
 		pfn = pte_pfn(*pte);
-		if (!pfn_valid(pfn)) {
-			done = -1;
-			goto out;
-		}
-
 		offset = uaddr & (PAGE_SIZE-1);
 		addr = (char *)(pfn << PAGE_SHIFT) + offset;
 		len = min(count - done, PAGE_SIZE - offset);
@@ -256,7 +245,6 @@
 		done += len_str;
 		uaddr += len_str;
 	} while ((len_str == len) && (done < count));
-out:
 	spin_unlock(&mm->page_table_lock);
 	return done + 1;
 fault:
@@ -325,12 +313,7 @@
 		}
 
 		pfn_from = pte_pfn(*pte_from);
-		if (!pfn_valid(pfn_from))
-			goto out;
 		pfn_to = pte_pfn(*pte_to);
-		if (!pfn_valid(pfn_to))
-			goto out;
-
 		offset_from = uaddr_from & (PAGE_SIZE-1);
 		offset_to = uaddr_from & (PAGE_SIZE-1);
 		offset_max = max(offset_from, offset_to);
@@ -342,7 +325,6 @@
 		uaddr_from += size;
 		uaddr_to += size;
 	} while (done < n);
-out:
 	spin_unlock(&mm->page_table_lock);
 	return n - done;
 fault:
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index 5932a82..e008d23 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -35,7 +35,7 @@
  * Leave an at least ~128 MB hole.
  */
 #define MIN_GAP (128*1024*1024)
-#define MAX_GAP (TASK_SIZE/6*5)
+#define MAX_GAP (STACK_TOP/6*5)
 
 static inline unsigned long mmap_base(void)
 {
@@ -46,7 +46,7 @@
 	else if (gap > MAX_GAP)
 		gap = MAX_GAP;
 
-	return TASK_SIZE - (gap & PAGE_MASK);
+	return STACK_TOP - (gap & PAGE_MASK);
 }
 
 static inline int mmap_is_legacy(void)
@@ -89,42 +89,58 @@
 
 #else
 
+int s390_mmap_check(unsigned long addr, unsigned long len)
+{
+	if (!test_thread_flag(TIF_31BIT) &&
+	    len >= TASK_SIZE && TASK_SIZE < (1UL << 53))
+		return crst_table_upgrade(current->mm, 1UL << 53);
+	return 0;
+}
+
 static unsigned long
 s390_get_unmapped_area(struct file *filp, unsigned long addr,
 		unsigned long len, unsigned long pgoff, unsigned long flags)
 {
 	struct mm_struct *mm = current->mm;
+	unsigned long area;
 	int rc;
 
-	addr = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
-	if (addr & ~PAGE_MASK)
-		return addr;
-	if (unlikely(mm->context.asce_limit < addr + len)) {
-		rc = crst_table_upgrade(mm, addr + len);
+	area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
+	if (!(area & ~PAGE_MASK))
+		return area;
+	if (area == -ENOMEM &&
+	    !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
+		/* Upgrade the page table to 4 levels and retry. */
+		rc = crst_table_upgrade(mm, 1UL << 53);
 		if (rc)
 			return (unsigned long) rc;
+		area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
 	}
-	return addr;
+	return area;
 }
 
 static unsigned long
-s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,
 			  const unsigned long len, const unsigned long pgoff,
 			  const unsigned long flags)
 {
 	struct mm_struct *mm = current->mm;
-	unsigned long addr = addr0;
+	unsigned long area;
 	int rc;
 
-	addr = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
-	if (addr & ~PAGE_MASK)
-		return addr;
-	if (unlikely(mm->context.asce_limit < addr + len)) {
-		rc = crst_table_upgrade(mm, addr + len);
+	area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
+	if (!(area & ~PAGE_MASK))
+		return area;
+	if (area == -ENOMEM &&
+	    !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
+		/* Upgrade the page table to 4 levels and retry. */
+		rc = crst_table_upgrade(mm, 1UL << 53);
 		if (rc)
 			return (unsigned long) rc;
+		area = arch_get_unmapped_area_topdown(filp, addr, len,
+						      pgoff, flags);
 	}
-	return addr;
+	return area;
 }
 /*
  * This function, called very early during the creation of a new
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 0767827..6b6ddc4 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -117,6 +117,7 @@
 		crst_table_init(table, entry);
 		pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
 		mm->pgd = (pgd_t *) table;
+		mm->task_size = mm->context.asce_limit;
 		table = NULL;
 	}
 	spin_unlock(&mm->page_table_lock);
@@ -154,6 +155,7 @@
 			BUG();
 		}
 		mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
+		mm->task_size = mm->context.asce_limit;
 		crst_table_free(mm, (unsigned long *) pgd);
 	}
 	update_mm(mm, current);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index ebabe51..8d50d52 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -107,6 +107,9 @@
 config SYS_SUPPORTS_PCI
 	bool
 
+config SYS_SUPPORTS_CMT
+	bool
+
 config STACKTRACE_SUPPORT
 	def_bool y
 
@@ -176,6 +179,10 @@
 config CPU_SHX3
 	bool
 
+config ARCH_SHMOBILE
+	bool
+	select ARCH_SUSPEND_POSSIBLE
+
 choice
 	prompt "Processor sub-type selection"
 
@@ -188,6 +195,7 @@
 config CPU_SUBTYPE_SH7619
 	bool "Support SH7619 processor"
 	select CPU_SH2
+	select SYS_SUPPORTS_CMT
 
 # SH-2A Processor Support
 
@@ -200,15 +208,18 @@
 	bool "Support SH7203 processor"
 	select CPU_SH2A
 	select CPU_HAS_FPU
+	select SYS_SUPPORTS_CMT
 
 config CPU_SUBTYPE_SH7206
 	bool "Support SH7206 processor"
 	select CPU_SH2A
+	select SYS_SUPPORTS_CMT
 
 config CPU_SUBTYPE_SH7263
 	bool "Support SH7263 processor"
 	select CPU_SH2A
 	select CPU_HAS_FPU
+	select SYS_SUPPORTS_CMT
 
 config CPU_SUBTYPE_MXG
 	bool "Support MX-G processor"
@@ -323,7 +334,9 @@
 	bool "Support SH7723 processor"
 	select CPU_SH4A
 	select CPU_SHX2
+	select ARCH_SHMOBILE
 	select ARCH_SPARSEMEM_ENABLE
+	select SYS_SUPPORTS_CMT
 	help
 	  Select SH7723 if you have an SH-MobileR2 CPU.
 
@@ -348,6 +361,14 @@
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_NUMA
 
+config CPU_SUBTYPE_SH7786
+	bool "Support SH7786 processor"
+	select CPU_SH4A
+	select CPU_SHX3
+	select CPU_HAS_PTEAEX
+	select ARCH_SPARSEMEM_ENABLE
+	select SYS_SUPPORTS_NUMA
+
 config CPU_SUBTYPE_SHX3
 	bool "Support SH-X3 processor"
 	select CPU_SH4A
@@ -362,20 +383,26 @@
 config CPU_SUBTYPE_SH7343
 	bool "Support SH7343 processor"
 	select CPU_SH4AL_DSP
+	select ARCH_SHMOBILE
+	select SYS_SUPPORTS_CMT
 
 config CPU_SUBTYPE_SH7722
 	bool "Support SH7722 processor"
 	select CPU_SH4AL_DSP
 	select CPU_SHX2
+	select ARCH_SHMOBILE
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_NUMA
+	select SYS_SUPPORTS_CMT
 
 config CPU_SUBTYPE_SH7366
 	bool "Support SH7366 processor"
 	select CPU_SH4AL_DSP
 	select CPU_SHX2
+	select ARCH_SHMOBILE
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_NUMA
+	select SYS_SUPPORTS_CMT
 
 # SH-5 Processor Support
 
@@ -398,25 +425,34 @@
 menu "Timer and clock configuration"
 
 config SH_TMU
-	def_bool y
-	prompt "TMU timer support"
+	bool "TMU timer support"
 	depends on CPU_SH3 || CPU_SH4
+	default y
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	help
 	  This enables the use of the TMU as the system timer.
 
 config SH_CMT
-	def_bool y
-	prompt "CMT timer support"
-	depends on CPU_SH2 && !CPU_SUBTYPE_MXG
+	bool "CMT timer support"
+	depends on SYS_SUPPORTS_CMT && CPU_SH2
+	default y
 	help
 	  This enables the use of the CMT as the system timer.
 
+#
+# Support for the new-style CMT driver. This will replace SH_CMT
+# once its other dependencies are merged.
+#
+config SH_TIMER_CMT
+	bool "CMT clockevents driver"
+	depends on SYS_SUPPORTS_CMT && !SH_CMT
+	select GENERIC_CLOCKEVENTS
+
 config SH_MTU2
-	def_bool n
-	prompt "MTU2 timer support"
+	bool "MTU2 timer support"
 	depends on CPU_SH2A
+	default y
 	help
 	  This enables the use of the MTU2 as the system timer.
 
@@ -426,7 +462,8 @@
 			CPU_SUBTYPE_SH7763
 	default "86" if CPU_SUBTYPE_SH7619
 	default "140" if CPU_SUBTYPE_SH7206
-	default "142" if CPU_SUBTYPE_SH7203
+	default "142" if CPU_SUBTYPE_SH7203 && SH_CMT
+	default "153" if CPU_SUBTYPE_SH7203 && SH_MTU2
 	default "238" if CPU_SUBTYPE_MXG
 	default "16"
 
@@ -438,7 +475,8 @@
 	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_MXG
+			      CPU_SUBTYPE_SH7263 || CPU_SUBTYPE_MXG    || \
+			      CPU_SUBTYPE_SH7786
 	default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
 	default "66000000" if CPU_SUBTYPE_SH4_202
 	default "50000000"
@@ -521,6 +559,13 @@
 
 	  For more details see Documentation/kdump/kdump.txt
 
+config KEXEC_JUMP
+	bool "kexec jump (EXPERIMENTAL)"
+	depends on SUPERH32 && KEXEC && HIBERNATION && EXPERIMENTAL
+	help
+	  Jump between original kernel and kexeced kernel and invoke
+	  code via KEXEC
+
 config SECCOMP
 	bool "Enable seccomp to safely compute untrusted bytecode"
 	depends on PROC_FS
diff --git a/arch/sh/Kconfig.cpu b/arch/sh/Kconfig.cpu
index 0e27fe3..c7d7043 100644
--- a/arch/sh/Kconfig.cpu
+++ b/arch/sh/Kconfig.cpu
@@ -104,6 +104,9 @@
 config CPU_HAS_PTEA
 	bool
 
+config CPU_HAS_PTEAEX
+	bool
+
 config CPU_HAS_DSP
 	bool
 
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 4067b0d..bece1f7 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -80,6 +80,7 @@
 defaultimage-$(CONFIG_SUPERH32)			:= zImage
 defaultimage-$(CONFIG_SH_SH7785LCR)		:= uImage
 defaultimage-$(CONFIG_SH_RSK)			:= uImage
+defaultimage-$(CONFIG_SH_URQUELL)		:= uImage
 defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE)	:= vmlinux
 defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE)	:= vmlinux
 
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index 8619147..dcc1af8 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -155,17 +155,22 @@
 
 config SH_SH7785LCR_29BIT_PHYSMAPS
 	bool "SH7785LCR 29bit physmaps"
-	depends on SH_SH7785LCR
+	depends on SH_SH7785LCR && 29BIT
 	default y
 	help
 	  This board has 2 physical memory maps. It can be changed with
 	  DIP switch(S2-5). If you set the DIP switch for S2-5 = ON,
 	  you can access all on-board device in 29bit address mode.
 
+config SH_URQUELL
+	bool "Urquell"
+	depends on CPU_SUBTYPE_SH7786
+	select ARCH_REQUIRE_GPIOLIB
+
 config SH_MIGOR
 	bool "Migo-R"
 	depends on CPU_SUBTYPE_SH7722
-	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 	help
 	  Select Migo-R if configuring for the SH7722 Migo-R platform
           by Renesas System Solutions Asia Pte. Ltd.
@@ -173,7 +178,7 @@
 config SH_AP325RXA
 	bool "AP-325RXA"
 	depends on CPU_SUBTYPE_SH7723
-	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 	help
 	  Renesas "AP-325RXA" support.
 	  Compatible with ALGO SYSTEM CO.,LTD. "AP-320A"
@@ -185,6 +190,13 @@
 	  Select SH7763RDP if configuring for a Renesas SH7763
 	  evaluation board.
 
+config SH_ESPT
+	bool "ESPT"
+	depends on CPU_SUBTYPE_SH7763
+	help
+	  Select ESPT if configuring for a Renesas SH7763
+	  with gigabit ether evaluation board.
+
 config SH_EDOSK7705
 	bool "EDOSK7705"
 	depends on CPU_SUBTYPE_SH7705
@@ -240,7 +252,7 @@
 config SH_MAGIC_PANEL_R2
 	bool "Magic Panel R2"
 	depends on CPU_SUBTYPE_SH7720
-	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 	help
 	  Select Magic Panel R2 if configuring for Magic Panel R2.
 
@@ -249,6 +261,13 @@
 	depends on CPU_SUBTYPE_SH5_101 || CPU_SUBTYPE_SH5_103
 	select SYS_SUPPORTS_PCI
 
+config SH_POLARIS
+	bool "SMSC Polaris"
+	select CPU_HAS_IPR_IRQ
+	depends on CPU_SUBTYPE_SH7709
+	help
+	  Select if configuring for an SMSC Polaris development board
+
 endmenu
 
 source "arch/sh/boards/mach-r2d/Kconfig"
diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile
index 269ae2b..7baa210 100644
--- a/arch/sh/boards/Makefile
+++ b/arch/sh/boards/Makefile
@@ -4,5 +4,8 @@
 obj-$(CONFIG_SH_AP325RXA)	+= board-ap325rxa.o
 obj-$(CONFIG_SH_MAGIC_PANEL_R2)	+= board-magicpanelr2.o
 obj-$(CONFIG_SH_SH7785LCR)	+= board-sh7785lcr.o
+obj-$(CONFIG_SH_URQUELL)	+= board-urquell.o
 obj-$(CONFIG_SH_SHMIN)		+= board-shmin.o
 obj-$(CONFIG_SH_EDOSK7760)	+= board-edosk7760.o
+obj-$(CONFIG_SH_ESPT)		+= board-espt.o
+obj-$(CONFIG_SH_POLARIS)	+= board-polaris.o
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
index 72da416..a64e388 100644
--- a/arch/sh/boards/board-ap325rxa.c
+++ b/arch/sh/boards/board-ap325rxa.c
@@ -22,6 +22,7 @@
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_gpio.h>
+#include <media/soc_camera.h>
 #include <media/soc_camera_platform.h>
 #include <media/sh_mobile_ceu.h>
 #include <video/sh_mobile_lcdc.h>
@@ -165,6 +166,16 @@
 	ctrl_outw(0x100, FPGA_BKLREG);
 }
 
+static void ap320_wvga_power_off(void *board_data)
+{
+	/* backlight */
+	ctrl_outw(0, FPGA_BKLREG);
+	gpio_set_value(GPIO_PTS3, 1);
+
+	/* ASD AP-320/325 LCD OFF */
+	ctrl_outw(0, FPGA_LCDREG);
+}
+
 static struct sh_mobile_lcdc_info lcdc_info = {
 	.clock_source = LCDC_CLK_EXTERNAL,
 	.ch[0] = {
@@ -190,6 +201,7 @@
 		},
 		.board_cfg = {
 			.display_on = ap320_wvga_power_on,
+			.display_off = ap320_wvga_power_off,
 		},
 	}
 };
diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c
new file mode 100644
index 0000000..d5ce5e1
--- /dev/null
+++ b/arch/sh/boards/board-espt.c
@@ -0,0 +1,102 @@
+/*
+ * Data Technology Inc. ESPT-GIGA board suport
+ *
+ * Copyright (C) 2008, 2009 Renesas Solutions Corp.
+ * Copyright (C) 2008, 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+#include <asm/machvec.h>
+#include <asm/sizes.h>
+#include <asm/sh_eth.h>
+
+/* NOR Flash */
+static struct mtd_partition espt_nor_flash_partitions[] = {
+	{
+		.name = "U-Boot",
+		.offset = 0,
+		.size = (2 * SZ_128K),
+		.mask_flags = MTD_WRITEABLE,	/* Read-only */
+	}, {
+		.name = "Linux-Kernel",
+		.offset = MTDPART_OFS_APPEND,
+		.size = (20 * SZ_128K),
+	}, {
+		.name = "Root Filesystem",
+		.offset = MTDPART_OFS_APPEND,
+		.size = MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data espt_nor_flash_data = {
+	.width = 2,
+	.parts = espt_nor_flash_partitions,
+	.nr_parts = ARRAY_SIZE(espt_nor_flash_partitions),
+};
+
+static struct resource espt_nor_flash_resources[] = {
+	[0] = {
+		.name = "NOR Flash",
+		.start = 0,
+		.end = SZ_8M - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device espt_nor_flash_device = {
+	.name = "physmap-flash",
+	.resource = espt_nor_flash_resources,
+	.num_resources = ARRAY_SIZE(espt_nor_flash_resources),
+	.dev = {
+		.platform_data = &espt_nor_flash_data,
+	},
+};
+
+/* SH-Ether */
+static struct resource sh_eth_resources[] = {
+	{
+		.start  = 0xFEE00800,   /* use eth1 */
+		.end    = 0xFEE00F7C - 1,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.start  = 57,   /* irq number */
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_eth_plat_data sh7763_eth_pdata = {
+	.phy = 0,
+	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+};
+
+static struct platform_device espt_eth_device = {
+	.name       = "sh-eth",
+	.resource   = sh_eth_resources,
+	.num_resources  = ARRAY_SIZE(sh_eth_resources),
+	.dev        = {
+		.platform_data = &sh7763_eth_pdata,
+	},
+};
+
+static struct platform_device *espt_devices[] __initdata = {
+	&espt_nor_flash_device,
+	&espt_eth_device,
+};
+
+static int __init espt_devices_setup(void)
+{
+	return platform_add_devices(espt_devices,
+				    ARRAY_SIZE(espt_devices));
+}
+device_initcall(espt_devices_setup);
+
+static struct sh_machine_vector mv_espt __initmv = {
+	.mv_name = "ESPT-GIGA",
+};
diff --git a/arch/sh/boards/board-polaris.c b/arch/sh/boards/board-polaris.c
new file mode 100644
index 0000000..62607eb
--- /dev/null
+++ b/arch/sh/boards/board-polaris.c
@@ -0,0 +1,149 @@
+/*
+ * June 2006 steve.glendinning@smsc.com
+ *
+ * Polaris-specific resource declaration
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/heartbeat.h>
+#include <cpu/gpio.h>
+#include <mach-se/mach/se.h>
+
+#define BCR2		(0xFFFFFF62)
+#define WCR2		(0xFFFFFF66)
+#define AREA5_WAIT_CTRL	(0x1C00)
+#define WAIT_STATES_10	(0x7)
+
+static struct resource smsc911x_resources[] = {
+	[0] = {
+		.name		= "smsc911x-memory",
+		.start		= PA_EXT5,
+		.end		= PA_EXT5 + 0x1fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name		= "smsc911x-irq",
+		.start		= IRQ0_IRQ,
+		.end		= IRQ0_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_32BIT,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+static struct platform_device smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev = {
+		.platform_data = &smsc911x_config,
+	},
+};
+
+static unsigned char heartbeat_bit_pos[] = { 0, 1, 2, 3 };
+
+static struct heartbeat_data heartbeat_data = {
+	.bit_pos	= heartbeat_bit_pos,
+	.nr_bits	= ARRAY_SIZE(heartbeat_bit_pos),
+	.regsize	= 8,
+};
+
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= PORT_PCDR,
+		.end	= PORT_PCDR,
+		.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 platform_device *polaris_devices[] __initdata = {
+	&smsc911x_device,
+	&heartbeat_device,
+};
+
+static int __init polaris_initialise(void)
+{
+	u16 wcr, bcr_mask;
+
+	printk(KERN_INFO "Configuring Polaris external bus\n");
+
+	/* Configure area 5 with 2 wait states */
+	wcr = ctrl_inw(WCR2);
+	wcr &= (~AREA5_WAIT_CTRL);
+	wcr |= (WAIT_STATES_10 << 10);
+	ctrl_outw(wcr, WCR2);
+
+	/* Configure area 5 for 32-bit access */
+	bcr_mask = ctrl_inw(BCR2);
+	bcr_mask |= 1 << 10;
+	ctrl_outw(bcr_mask, BCR2);
+
+	return platform_add_devices(polaris_devices,
+				    ARRAY_SIZE(polaris_devices));
+}
+arch_initcall(polaris_initialise);
+
+static struct ipr_data ipr_irq_table[] = {
+	/* External IRQs */
+	{ IRQ0_IRQ, 0,  0,  1, },	/* IRQ0 */
+	{ IRQ1_IRQ, 0,  4,  1, },	/* IRQ1 */
+};
+
+static unsigned long ipr_offsets[] = {
+	INTC_IPRC
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+	.chip = {
+		.name	= "sh7709-ext",
+	},
+};
+
+static void __init init_polaris_irq(void)
+{
+	/* Disable all interrupts */
+	ctrl_outw(0, BCR_ILCRA);
+	ctrl_outw(0, BCR_ILCRB);
+	ctrl_outw(0, BCR_ILCRC);
+	ctrl_outw(0, BCR_ILCRD);
+	ctrl_outw(0, BCR_ILCRE);
+	ctrl_outw(0, BCR_ILCRF);
+	ctrl_outw(0, BCR_ILCRG);
+
+	register_ipr_controller(&ipr_irq_desc);
+}
+
+static struct sh_machine_vector mv_polaris __initmv = {
+	.mv_name		= "Polaris",
+	.mv_nr_irqs		= 61,
+	.mv_init_irq		= init_polaris_irq,
+};
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index 38a6496..94c0296 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -275,7 +275,18 @@
 
 static void sh7785lcr_power_off(void)
 {
-	ctrl_outb(0x01, P2SEGADDR(PLD_POFCR));
+	unsigned char *p;
+
+	p = ioremap(PLD_POFCR, PLD_POFCR + 1);
+	if (!p) {
+		printk(KERN_ERR "%s: ioremap error.\n", __func__);
+		return;
+	}
+	*p = 0x01;
+	iounmap(p);
+	set_bl_bit();
+	while (1)
+		cpu_relax();
 }
 
 /* Initialize the board */
diff --git a/arch/sh/boards/board-urquell.c b/arch/sh/boards/board-urquell.c
new file mode 100644
index 0000000..17036ce
--- /dev/null
+++ b/arch/sh/boards/board-urquell.c
@@ -0,0 +1,162 @@
+/*
+ * Renesas Technology Corp. SH7786 Urquell Support.
+ *
+ * Copyright (C) 2008  Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Copyright (C) 2008  Yoshihiro Shimoda
+ *
+ * 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 <linux/fb.h>
+#include <linux/smc91x.h>
+#include <linux/mtd/physmap.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <mach/urquell.h>
+#include <cpu/sh7786.h>
+#include <asm/heartbeat.h>
+#include <asm/sizes.h>
+
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= BOARDREG(SLEDR),
+		.end	= BOARDREG(SLEDR),
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct heartbeat_data heartbeat_data = {
+	.regsize = 16,
+};
+
+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 smc91x_platdata smc91x_info = {
+	.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+};
+
+static struct resource smc91x_eth_resources[] = {
+	[0] = {
+		.name   = "SMC91C111" ,
+		.start  = 0x05800300,
+		.end    = 0x0580030f,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 11,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smc91x_eth_device = {
+	.name           = "smc91x",
+	.num_resources  = ARRAY_SIZE(smc91x_eth_resources),
+	.resource       = smc91x_eth_resources,
+	.dev	= {
+		.platform_data	= &smc91x_info,
+	},
+};
+
+static struct mtd_partition nor_flash_partitions[] = {
+	{
+		.name		= "loader",
+		.offset		= 0x00000000,
+		.size		= SZ_512K,
+		.mask_flags	= MTD_WRITEABLE,	/* Read-only */
+	},
+	{
+		.name		= "bootenv",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_512K,
+		.mask_flags	= MTD_WRITEABLE,	/* Read-only */
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_4M,
+	},
+	{
+		.name		= "data",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data nor_flash_data = {
+	.width		= 2,
+	.parts		= nor_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(nor_flash_partitions),
+};
+
+static struct resource nor_flash_resources[] = {
+	[0] = {
+		.start	= NOR_FLASH_ADDR,
+		.end	= NOR_FLASH_ADDR + NOR_FLASH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device nor_flash_device = {
+	.name		= "physmap-flash",
+	.dev		= {
+		.platform_data	= &nor_flash_data,
+	},
+	.num_resources	= ARRAY_SIZE(nor_flash_resources),
+	.resource	= nor_flash_resources,
+};
+
+static struct platform_device *urquell_devices[] __initdata = {
+	&heartbeat_device,
+	&smc91x_eth_device,
+	&nor_flash_device,
+};
+
+static int __init urquell_devices_setup(void)
+{
+	/* USB */
+	gpio_request(GPIO_FN_USB_OVC0,  NULL);
+	gpio_request(GPIO_FN_USB_PENC0, NULL);
+
+	return platform_add_devices(urquell_devices,
+				    ARRAY_SIZE(urquell_devices));
+}
+device_initcall(urquell_devices_setup);
+
+static void urquell_power_off(void)
+{
+	__raw_writew(0xa5a5, UBOARDREG(SRSTR));
+}
+
+static void __init urquell_init_irq(void)
+{
+	plat_irq_setup_pins(IRQ_MODE_IRL3210_MASK);
+}
+
+/* Initialize the board */
+static void __init urquell_setup(char **cmdline_p)
+{
+	printk(KERN_INFO "Renesas Technology Corp. Urquell support.\n");
+
+	pm_power_off = urquell_power_off;
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_urquell __initmv = {
+	.mv_name	= "Urquell",
+	.mv_setup	= urquell_setup,
+	.mv_init_irq	= urquell_init_irq,
+};
diff --git a/arch/sh/boards/mach-highlander/Kconfig b/arch/sh/boards/mach-highlander/Kconfig
index 08057f6..def49cc 100644
--- a/arch/sh/boards/mach-highlander/Kconfig
+++ b/arch/sh/boards/mach-highlander/Kconfig
@@ -18,7 +18,7 @@
 config SH_R7785RP
 	bool "R7785RP board support"
 	depends on CPU_SUBTYPE_SH7785
-	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 
 endchoice
 
diff --git a/arch/sh/boards/mach-hp6xx/pm_wakeup.S b/arch/sh/boards/mach-hp6xx/pm_wakeup.S
index 44b648c..4f18d44 100644
--- a/arch/sh/boards/mach-hp6xx/pm_wakeup.S
+++ b/arch/sh/boards/mach-hp6xx/pm_wakeup.S
@@ -10,47 +10,32 @@
 #include <linux/linkage.h>
 #include <cpu/mmu_context.h>
 
-#define k0	r0
-#define k1	r1
-#define k2	r2
-#define k3	r3
-#define k4	r4
-
 /*
  * Kernel mode register usage:
  *	k0	scratch
  *	k1	scratch
- *	k2	scratch (Exception code)
- *	k3	scratch (Return address)
- *	k4	scratch
- *	k5	reserved
- *	k6	Global Interrupt Mask (0--15 << 4)
- *	k7	CURRENT_THREAD_INFO (pointer to current thread info)
+ * For more details, please have a look at entry.S
  */
 
+#define k0	r0
+#define k1	r1
+
 ENTRY(wakeup_start)
 ! clear STBY bit
-	mov	#-126, k2
+	mov	#-126, k1
    	and	#127, k0
-	mov.b	k0, @k2
+	mov.b	k0, @k1
 ! enable refresh
 	mov.l	5f, k1
 	mov.w	6f, k0
   	mov.w	k0, @k1
 ! jump to handler
-	mov.l	2f, k2
-	mov.l	3f, k3
-	mov.l	@k2, k2
-
 	mov.l	4f, k1
 	jmp	@k1
-	nop
+	 nop
 
 	.align	2
-1:	.long	EXPEVT
-2:	.long	INTEVT
-3:	.long	ret_from_irq
-4:	.long	handle_exception
+4:	.long	handle_interrupt
 5:	.long	0xffffff68
 6:	.word	0x0524
 
diff --git a/arch/sh/boards/mach-hp6xx/setup.c b/arch/sh/boards/mach-hp6xx/setup.c
index 746742bd..8f305b3 100644
--- a/arch/sh/boards/mach-hp6xx/setup.c
+++ b/arch/sh/boards/mach-hp6xx/setup.c
@@ -115,7 +115,6 @@
 	.mv_setup = hp6xx_setup,
 	/* IRQ's : CPU(64) + CCHIP(16) + FREE_TO_USE(6) */
 	.mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM + 6,
-	.mv_irq_demux = hd64461_irq_demux,
 	/* Enable IRQ0 -> IRQ3 in IRQ_MODE */
 	.mv_init_irq = hp6xx_init_irq,
 };
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 28e56c5..bc35b4c 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -450,6 +450,14 @@
 
 static int __init migor_devices_setup(void)
 {
+
+#ifdef CONFIG_PM
+	/* Let D11 LED show STATUS0 */
+	gpio_request(GPIO_FN_STATUS0, NULL);
+
+	/* Lit D12 LED show PDSTATUS */
+	gpio_request(GPIO_FN_PDSTATUS, NULL);
+#else
 	/* Lit D11 LED */
 	gpio_request(GPIO_PTJ7, NULL);
 	gpio_direction_output(GPIO_PTJ7, 1);
@@ -459,6 +467,7 @@
 	gpio_request(GPIO_PTJ5, NULL);
 	gpio_direction_output(GPIO_PTJ5, 1);
 	gpio_export(GPIO_PTJ5, 0);
+#endif
 
 	/* SMC91C111 - Enable IRQ0, Setup CS4 for 16-bit fast access */
 	gpio_request(GPIO_FN_IRQ0, NULL);
diff --git a/arch/sh/boards/mach-rsk/Kconfig b/arch/sh/boards/mach-rsk/Kconfig
index bff095d..aeff3b0 100644
--- a/arch/sh/boards/mach-rsk/Kconfig
+++ b/arch/sh/boards/mach-rsk/Kconfig
@@ -10,7 +10,7 @@
 
 config SH_RSK7203
 	bool "RSK7203"
-	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 	depends on CPU_SUBTYPE_SH7203
 
 endchoice
diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c
index 6f926fd..390534a 100644
--- a/arch/sh/boards/mach-sh7763rdp/setup.c
+++ b/arch/sh/boards/mach-sh7763rdp/setup.c
@@ -63,15 +63,19 @@
 	},
 };
 
-/* SH-Ether */
+/*
+ * SH-Ether
+ *
+ * SH Ether of SH7763 has multi IRQ handling.
+ * (57,58,59 -> 57)
+ */
 static struct resource sh_eth_resources[] = {
 	{
 		.start  = 0xFEE00800,   /* use eth1 */
 		.end    = 0xFEE00F7C - 1,
 		.flags  = IORESOURCE_MEM,
 	}, {
-		.start  = 58,   /* irq number */
-		.end    = 58,
+		.start  = 57,   /* irq number */
 		.flags  = IORESOURCE_IRQ,
 	},
 };
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index c16ccd4..95483d1 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -33,20 +33,24 @@
 $(obj)/compressed/vmlinux: FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
-ifeq ($(CONFIG_32BIT),y)
-KERNEL_LOAD	:= $(shell /bin/bash -c 'printf "0x%08x" \
-		     $$[$(CONFIG_PAGE_OFFSET)  + \
-			$(CONFIG_ZERO_PAGE_OFFSET)]')
-else
-KERNEL_LOAD	:= $(shell /bin/bash -c 'printf "0x%08x" \
-		     $$[$(CONFIG_PAGE_OFFSET)  + \
-			$(CONFIG_MEMORY_START) + \
-			$(CONFIG_ZERO_PAGE_OFFSET)]')
+KERNEL_MEMORY := 0x00000000
+ifeq ($(CONFIG_PMB_FIXED),y)
+KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
+		     $$[$(CONFIG_MEMORY_START) & 0x1fffffff]')
 endif
+ifeq ($(CONFIG_29BIT),y)
+KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
+		     $$[$(CONFIG_MEMORY_START)]')
+endif
+
+KERNEL_LOAD	:= $(shell /bin/bash -c 'printf "0x%08x" \
+		     $$[$(CONFIG_PAGE_OFFSET)  + \
+			$(KERNEL_MEMORY) + \
+			$(CONFIG_ZERO_PAGE_OFFSET)]')
 
 KERNEL_ENTRY	:= $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_PAGE_OFFSET)  + \
-			$(CONFIG_MEMORY_START) + \
+			$(KERNEL_MEMORY) + \
 			$(CONFIG_ZERO_PAGE_OFFSET) + $(CONFIG_ENTRY_OFFSET)]')
 
 quiet_cmd_uimage = UIMAGE  $@
diff --git a/arch/sh/cchips/hd6446x/hd64461.c b/arch/sh/cchips/hd6446x/hd64461.c
index 27ceeb9..25ef910 100644
--- a/arch/sh/cchips/hd6446x/hd64461.c
+++ b/arch/sh/cchips/hd6446x/hd64461.c
@@ -53,21 +53,22 @@
 	.unmask		= hd64461_unmask_irq,
 };
 
-int hd64461_irq_demux(int irq)
+static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	if (irq == CONFIG_HD64461_IRQ) {
-		unsigned short bit;
-		unsigned short nirr = inw(HD64461_NIRR);
-		unsigned short nimr = inw(HD64461_NIMR);
-		int i;
+	unsigned short intv = ctrl_inw(HD64461_NIRR);
+	struct irq_desc *ext_desc;
+	unsigned int ext_irq = HD64461_IRQBASE;
 
-		nirr &= ~nimr;
-		for (bit = 1, i = 0; i < 16; bit <<= 1, i++)
-			if (nirr & bit)
-				break;
-		irq = HD64461_IRQBASE + i;
+	intv &= (1 << HD64461_IRQ_NUM) - 1;
+
+	while (intv) {
+		if (intv & 1) {
+			ext_desc = irq_desc + ext_irq;
+			handle_level_irq(ext_irq, ext_desc);
+		}
+		intv >>= 1;
+		ext_irq++;
 	}
-	return irq;
 }
 
 int __init setup_hd64461(void)
@@ -93,6 +94,9 @@
 		set_irq_chip_and_handler(i, &hd64461_irq_chip,
 					 handle_level_irq);
 
+	set_irq_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
+	set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
+
 #ifdef CONFIG_HD64461_ENABLER
 	printk(KERN_INFO "HD64461: enabling PCMCIA devices\n");
 	__raw_writeb(0x4c, HD64461_PCC1CSCIER);
diff --git a/arch/sh/configs/espt_defconfig b/arch/sh/configs/espt_defconfig
new file mode 100644
index 0000000..873ec42
--- /dev/null
+++ b/arch/sh/configs/espt_defconfig
@@ -0,0 +1,1190 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc7
+# Tue Mar 17 13:25:58 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_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_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
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+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_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS 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_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_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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_FREEZER is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 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 is not set
+# 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_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7763=y
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 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=0x04000000
+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_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_UNEVICTABLE_LRU=y
+
+#
+# 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=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_SH7763RDP is not set
+CONFIG_SH_ESPT=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_PCLK_FREQ=66666666
+# 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 is not set
+# 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_SECCOMP=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/nfs ip=bootp"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=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
+# 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=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_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_NET_DSA 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_DCB 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_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX 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_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# 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_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_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 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=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 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=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT 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
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR 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_BLK_DEV_HD 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=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_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# 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_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+CONFIG_SH_ETH=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR 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
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# 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 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_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# 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=3
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI 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_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# 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_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_BOTH_ENDIAN=y
+# CONFIG_FB_BIG_ENDIAN is not set
+# CONFIG_FB_LITTLE_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SH_MOBILE_LCDC is not set
+CONFIG_FB_SH7760=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_SUPERH_MONO=y
+CONFIG_LOGO_SUPERH_VGA16=y
+CONFIG_LOGO_SUPERH_CLUT224=y
+# 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
+# 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
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# 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
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD 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_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_STORAGE_CYPRESS_ATACB 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 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_SEVSEG 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_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING 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_EXT4_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_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# 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_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS 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_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# 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_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 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=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
+# CONFIG_DLM 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 is not set
+CONFIG_FRAME_WARN=1024
+# 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_STACKTRACE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# 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/sh/configs/polaris_defconfig b/arch/sh/configs/polaris_defconfig
new file mode 100644
index 0000000..320def2
--- /dev/null
+++ b/arch/sh/configs/polaris_defconfig
@@ -0,0 +1,969 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc4
+# Wed Feb 11 18:41:59 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_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_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 is not set
+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=y
+# CONFIG_AUDITSYSCALL is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+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_CGROUPS 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=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_AIO=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_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH3=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 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=y
+# 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 is not set
+# 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_SH7723 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=0x04000000
+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_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_ENTRY_OFFSET=0x00001000
+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_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_UNEVICTABLE_LRU=y
+
+#
+# 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=y
+CONFIG_SH_ADC=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Board support
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_HP6XX is not set
+CONFIG_SH_POLARIS=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=33000000
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA_API=y
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+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=ttySC1,115200 root=/dev/mtdblock2 rootfstype=jffs2 mem=63M mtdparts=physmap-flash.0:0x00100000(bootloader)ro,0x00500000(Kernel)ro,0x00A00000(Filesystem)"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+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 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=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_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_NET_DSA 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_DCB 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_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX 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_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# 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_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_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 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=y
+CONFIG_MTD_PHYSMAP_COMPAT=y
+CONFIG_MTD_PHYSMAP_START=0x00000000
+CONFIG_MTD_PHYSMAP_LEN=0x01000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# 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
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE 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_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 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=y
+# 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=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR 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
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# 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=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+CONFIG_SERIAL_NONSTANDARD=y
+# 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_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=3
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# 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
+# CONFIG_SPI 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_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# 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_DUMMY_CONSOLE=y
+# 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_ACCESSIBILITY 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_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_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_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_PROC_PAGE_MONITOR=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
+CONFIG_MISC_FILESYSTEMS=y
+# 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 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_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_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_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 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
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# 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=y
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_LOCKDEP=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_DEBUG_SG=y
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+CONFIG_EARLY_SCIF_CONSOLE_PORT=0x00000000
+CONFIG_EARLY_PRINTK=y
+# 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_DUMP_CODE=y
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF 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/sh/configs/sh7785lcr_32bit_defconfig b/arch/sh/configs/sh7785lcr_32bit_defconfig
new file mode 100644
index 0000000..54e1dee
--- /dev/null
+++ b/arch/sh/configs/sh7785lcr_32bit_defconfig
@@ -0,0 +1,1553 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc4
+# Fri Feb 20 18:25:29 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
+CONFIG_SYS_SUPPORTS_NUMA=y
+CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_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_IO_TRAPPED=y
+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=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+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_CGROUPS 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=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+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_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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_FREEZER is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 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 is not set
+# 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_SH7723 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=y
+# 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=0x40000000
+CONFIG_MEMORY_SIZE=0x20000000
+# CONFIG_29BIT is not set
+CONFIG_32BIT=y
+CONFIG_PMB_ENABLE=y
+# CONFIG_PMB is not set
+CONFIG_PMB_FIXED=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+# CONFIG_NUMA is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=2
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_UNEVICTABLE_LRU=y
+
+#
+# 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=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_HIGHLANDER is not set
+CONFIG_SH_SH7785LCR=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+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=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_GUSA=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=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
+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 is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE 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_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_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_NET_DSA 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_DCB 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_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX 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_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_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_COMPAT is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_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
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE 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_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=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD 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=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 is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_ATA_SFF=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=y
+# 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_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# 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_MII=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_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=y
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 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_ATL1E is not set
+# CONFIG_JME 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_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# 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=m
+# 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_EVDEV is not set
+# 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 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_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# 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_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# 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
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOPCA=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# 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_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SH_MOBILE is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_PCA_PLATFORM=y
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 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
+# CONFIG_SPI 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_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+CONFIG_MFD_SM501=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+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 is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+CONFIG_FB_SH_MOBILE_LCDC=m
+CONFIG_FB_SM501=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+# CONFIG_LOGO_SUPERH_CLUT224 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
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+CONFIG_THRUSTMASTER_FF=m
+CONFIG_ZEROPLUS_FF=m
+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
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# 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_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+CONFIG_USB_R8A66597_HCD=y
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD 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_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_STORAGE_CYPRESS_ATACB 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 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_SEVSEG 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=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# 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=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 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SH is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING 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_EXT4_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_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_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=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS 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_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_OMFS_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_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 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=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 is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# 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_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_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 is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB 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_DUMP_CODE is not set
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF 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
diff --git a/arch/sh/configs/urquell_defconfig b/arch/sh/configs/urquell_defconfig
new file mode 100644
index 0000000..be726c7
--- /dev/null
+++ b/arch/sh/configs/urquell_defconfig
@@ -0,0 +1,1332 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc4
+# Thu Mar  5 17:28:13 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
+CONFIG_SYS_SUPPORTS_NUMA=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_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_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=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+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_CGROUPS 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=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_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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_FREEZER is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX3=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 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 is not set
+# 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_SH7723 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_SH7786=y
+# 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=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+# CONFIG_NUMA is not set
+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_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_UNEVICTABLE_LRU=y
+
+#
+# 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=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+CONFIG_SH_URQUELL=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+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=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_GUSA=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1, 38400 earlyprintk=serial ip=on ignore_loglevel root=/dev/nfs ip=dhcp memchunk.vpu=4m"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=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
+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 is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE 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_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_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_NET_DSA 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_DCB 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_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX 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=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_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_COMPAT 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
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE 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_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD 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=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 is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_MV is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# 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_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+CONFIG_SMC91X=y
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR 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
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# 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=m
+# 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_EVDEV is not set
+# 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 is not set
+# CONFIG_KEYBOARD_SH_KEYSC 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_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# 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=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# 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
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOPCA=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SH_MOBILE is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_PCA_PLATFORM=y
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 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
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+CONFIG_MFD_SM501=y
+# CONFIG_MFD_SM501_GPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# 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_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+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 is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_SH_MOBILE_LCDC=m
+CONFIG_FB_SM501=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+# CONFIG_LOGO_SUPERH_CLUT224 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
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+CONFIG_THRUSTMASTER_FF=m
+CONFIG_ZEROPLUS_FF=m
+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
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# 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
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD 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_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_STORAGE_CYPRESS_ATACB 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 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_SEVSEG 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_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING 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_EXT4_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_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_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=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS 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_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_OMFS_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_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 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=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 is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# 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_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF 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
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 0193636..f13a052 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -9,13 +9,21 @@
 	select SH_DMA_API
 	default n
 
+config SH_DMA_IRQ_MULTI
+	bool
+	depends on SH_DMA
+	default y if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || \
+		CPU_SUBTYPE_SH7750S || CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R || \
+		CPU_SUBTYPE_SH7091 || CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7764 || \
+		CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
+
 config NR_ONCHIP_DMA_CHANNELS
 	int
 	depends on SH_DMA
-	default "6" if CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721
-	default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R
-	default "12" if CPU_SUBTYPE_SH7780
-	default "4"
+	default "4" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7750S
+	default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R || CPU_SUBTYPE_SH7760
+	default "12" if CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
+	default "6"
 	help
 	  This allows you to specify the number of channels that the on-chip
 	  DMAC supports. This will be 4 for SH7750/SH7751 and 8 for the
@@ -46,4 +54,28 @@
 	  of the SH7760.
 	  Say Y if you want to use Audio/USB DMA on your SH7760 board.
 
+config PVR2_DMA
+	tristate "PowerVR 2 DMAC support"
+	depends on SH_DREAMCAST && SH_DMA
+	help
+	  Selecting this will enable support for the PVR2 DMA controller.
+	  As this chains off of the on-chip DMAC, that must also be
+	  enabled by default.
+
+	  This is primarily used by the pvr2fb framebuffer driver for
+	  certain optimizations, but is not necessary for functionality.
+
+	  If in doubt, say N.
+
+config G2_DMA
+	tristate "G2 Bus DMA support"
+	depends on SH_DREAMCAST
+	select SH_DMA_API
+	help
+	  This enables support for the DMA controller for the Dreamcast's
+	  G2 bus. Drivers that want this will generally enable this on
+	  their own.
+
+	  If in doubt, say N.
+
 endmenu
diff --git a/arch/sh/drivers/dma/Makefile b/arch/sh/drivers/dma/Makefile
index ab956ad..c606813 100644
--- a/arch/sh/drivers/dma/Makefile
+++ b/arch/sh/drivers/dma/Makefile
@@ -4,5 +4,6 @@
 
 obj-$(CONFIG_SH_DMA_API)	+= dma-api.o dma-sysfs.o
 obj-$(CONFIG_SH_DMA)		+= dma-sh.o
-obj-$(CONFIG_SH_DREAMCAST)	+= dma-pvr2.o dma-g2.o
+obj-$(CONFIG_PVR2_DMA)		+= dma-pvr2.o
+obj-$(CONFIG_G2_DMA)		+= dma-g2.o
 obj-$(CONFIG_SH_DMABRG)		+= dmabrg.o
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index 50887a5..37fb5b8 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -17,28 +17,16 @@
 #include <mach-dreamcast/mach/dma.h>
 #include <asm/dma.h>
 #include <asm/io.h>
-#include "dma-sh.h"
+#include <asm/dma-sh.h>
 
-static int dmte_irq_map[] = {
-	DMTE0_IRQ,
-	DMTE1_IRQ,
-	DMTE2_IRQ,
-	DMTE3_IRQ,
-#if defined(CONFIG_CPU_SUBTYPE_SH7720)  ||	\
-    defined(CONFIG_CPU_SUBTYPE_SH7721)  ||	\
-    defined(CONFIG_CPU_SUBTYPE_SH7751R) ||	\
-    defined(CONFIG_CPU_SUBTYPE_SH7760)  ||	\
-    defined(CONFIG_CPU_SUBTYPE_SH7709)  ||	\
-    defined(CONFIG_CPU_SUBTYPE_SH7780)
-	DMTE4_IRQ,
-	DMTE5_IRQ,
+#if defined(DMAE1_IRQ)
+#define NR_DMAE		2
+#else
+#define NR_DMAE		1
 #endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7751R) ||	\
-    defined(CONFIG_CPU_SUBTYPE_SH7760)  ||	\
-    defined(CONFIG_CPU_SUBTYPE_SH7780)
-	DMTE6_IRQ,
-	DMTE7_IRQ,
-#endif
+
+static const char *dmae_name[] = {
+	"DMAC Address Error0", "DMAC Address Error1"
 };
 
 static inline unsigned int get_dmte_irq(unsigned int chan)
@@ -46,7 +34,14 @@
 	unsigned int irq = 0;
 	if (chan < ARRAY_SIZE(dmte_irq_map))
 		irq = dmte_irq_map[chan];
+
+#if defined(CONFIG_SH_DMA_IRQ_MULTI)
+	if (irq > DMTE6_IRQ)
+		return DMTE6_IRQ;
+	return DMTE0_IRQ;
+#else
 	return irq;
+#endif
 }
 
 /*
@@ -59,7 +54,7 @@
  */
 static inline unsigned int calc_xmit_shift(struct dma_channel *chan)
 {
-	u32 chcr = ctrl_inl(CHCR[chan->chan]);
+	u32 chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
 
 	return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT];
 }
@@ -75,13 +70,13 @@
 	struct dma_channel *chan = dev_id;
 	u32 chcr;
 
-	chcr = ctrl_inl(CHCR[chan->chan]);
+	chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
 
 	if (!(chcr & CHCR_TE))
 		return IRQ_NONE;
 
 	chcr &= ~(CHCR_IE | CHCR_DE);
-	ctrl_outl(chcr, CHCR[chan->chan]);
+	ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
 
 	wake_up(&chan->wait_queue);
 
@@ -94,7 +89,12 @@
 		return 0;
 
 	return request_irq(get_dmte_irq(chan->chan), dma_tei,
-			   IRQF_DISABLED, chan->dev_id, chan);
+#if defined(CONFIG_SH_DMA_IRQ_MULTI)
+				IRQF_SHARED,
+#else
+				IRQF_DISABLED,
+#endif
+				chan->dev_id, chan);
 }
 
 static void sh_dmac_free_dma(struct dma_channel *chan)
@@ -115,7 +115,7 @@
 		chan->flags &= ~DMA_TEI_CAPABLE;
 	}
 
-	ctrl_outl(chcr, CHCR[chan->chan]);
+	ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
 
 	chan->flags |= DMA_CONFIGURED;
 	return 0;
@@ -126,13 +126,13 @@
 	int irq;
 	u32 chcr;
 
-	chcr = ctrl_inl(CHCR[chan->chan]);
+	chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
 	chcr |= CHCR_DE;
 
 	if (chan->flags & DMA_TEI_CAPABLE)
 		chcr |= CHCR_IE;
 
-	ctrl_outl(chcr, CHCR[chan->chan]);
+	ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
 
 	if (chan->flags & DMA_TEI_CAPABLE) {
 		irq = get_dmte_irq(chan->chan);
@@ -150,9 +150,9 @@
 		disable_irq(irq);
 	}
 
-	chcr = ctrl_inl(CHCR[chan->chan]);
+	chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
 	chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
-	ctrl_outl(chcr, CHCR[chan->chan]);
+	ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
 }
 
 static int sh_dmac_xfer_dma(struct dma_channel *chan)
@@ -183,12 +183,13 @@
 	 */
 	if (chan->sar || (mach_is_dreamcast() &&
 			  chan->chan == PVR2_CASCADE_CHAN))
-		ctrl_outl(chan->sar, SAR[chan->chan]);
+		ctrl_outl(chan->sar, (dma_base_addr[chan->chan]+SAR));
 	if (chan->dar || (mach_is_dreamcast() &&
 			  chan->chan == PVR2_CASCADE_CHAN))
-		ctrl_outl(chan->dar, DAR[chan->chan]);
+		ctrl_outl(chan->dar, (dma_base_addr[chan->chan] + DAR));
 
-	ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]);
+	ctrl_outl(chan->count >> calc_xmit_shift(chan),
+		(dma_base_addr[chan->chan] + TCR));
 
 	sh_dmac_enable_dma(chan);
 
@@ -197,36 +198,26 @@
 
 static int sh_dmac_get_dma_residue(struct dma_channel *chan)
 {
-	if (!(ctrl_inl(CHCR[chan->chan]) & CHCR_DE))
+	if (!(ctrl_inl(dma_base_addr[chan->chan] + CHCR) & CHCR_DE))
 		return 0;
 
-	return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan);
+	return ctrl_inl(dma_base_addr[chan->chan] + TCR)
+		 << calc_xmit_shift(chan);
 }
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7709)
-#define dmaor_read_reg()	ctrl_inw(DMAOR)
-#define dmaor_write_reg(data)	ctrl_outw(data, DMAOR)
-#else
-#define dmaor_read_reg()	ctrl_inl(DMAOR)
-#define dmaor_write_reg(data)	ctrl_outl(data, DMAOR)
-#endif
-
-static inline int dmaor_reset(void)
+static inline int dmaor_reset(int no)
 {
-	unsigned long dmaor = dmaor_read_reg();
+	unsigned long dmaor = dmaor_read_reg(no);
 
 	/* Try to clear the error flags first, incase they are set */
 	dmaor &= ~(DMAOR_NMIF | DMAOR_AE);
-	dmaor_write_reg(dmaor);
+	dmaor_write_reg(no, dmaor);
 
 	dmaor |= DMAOR_INIT;
-	dmaor_write_reg(dmaor);
+	dmaor_write_reg(no, dmaor);
 
 	/* See if we got an error again */
-	if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) {
+	if ((dmaor_read_reg(no) & (DMAOR_AE | DMAOR_NMIF))) {
 		printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n");
 		return -EINVAL;
 	}
@@ -237,10 +228,33 @@
 #if defined(CONFIG_CPU_SH4)
 static irqreturn_t dma_err(int irq, void *dummy)
 {
-	dmaor_reset();
+#if defined(CONFIG_SH_DMA_IRQ_MULTI)
+	int cnt = 0;
+	switch (irq) {
+#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
+	case DMTE6_IRQ:
+		cnt++;
+#endif
+	case DMTE0_IRQ:
+		if (dmaor_read_reg(cnt) & (DMAOR_NMIF | DMAOR_AE)) {
+			disable_irq(irq);
+			/* DMA multi and error IRQ */
+			return IRQ_HANDLED;
+		}
+	default:
+		return IRQ_NONE;
+	}
+#else
+	dmaor_reset(0);
+#if defined(CONFIG_CPU_SUBTYPE_SH7723)	|| \
+		defined(CONFIG_CPU_SUBTYPE_SH7780)	|| \
+		defined(CONFIG_CPU_SUBTYPE_SH7785)
+	dmaor_reset(1);
+#endif
 	disable_irq(irq);
 
 	return IRQ_HANDLED;
+#endif
 }
 #endif
 
@@ -259,24 +273,59 @@
 	.flags		= DMAC_CHANNELS_TEI_CAPABLE,
 };
 
+#ifdef CONFIG_CPU_SH4
+static unsigned int get_dma_error_irq(int n)
+{
+#if defined(CONFIG_SH_DMA_IRQ_MULTI)
+	return (n == 0) ? get_dmte_irq(0) : get_dmte_irq(6);
+#else
+	return (n == 0) ? DMAE0_IRQ :
+#if defined(DMAE1_IRQ)
+				DMAE1_IRQ;
+#else
+				-1;
+#endif
+#endif
+}
+#endif
+
 static int __init sh_dmac_init(void)
 {
 	struct dma_info *info = &sh_dmac_info;
 	int i;
 
 #ifdef CONFIG_CPU_SH4
-	i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0);
-	if (unlikely(i < 0))
-		return i;
+	int n;
+
+	for (n = 0; n < NR_DMAE; n++) {
+		i = request_irq(get_dma_error_irq(n), dma_err,
+#if defined(CONFIG_SH_DMA_IRQ_MULTI)
+				IRQF_SHARED,
+#else
+				IRQF_DISABLED,
 #endif
+				dmae_name[n], (void *)dmae_name[n]);
+		if (unlikely(i < 0)) {
+			printk(KERN_ERR "%s request_irq fail\n", dmae_name[n]);
+			return i;
+		}
+	}
+#endif /* CONFIG_CPU_SH4 */
 
 	/*
 	 * Initialize DMAOR, and clean up any error flags that may have
 	 * been set.
 	 */
-	i = dmaor_reset();
+	i = dmaor_reset(0);
 	if (unlikely(i != 0))
 		return i;
+#if defined(CONFIG_CPU_SUBTYPE_SH7723)	|| \
+		defined(CONFIG_CPU_SUBTYPE_SH7780)	|| \
+		defined(CONFIG_CPU_SUBTYPE_SH7785)
+	i = dmaor_reset(1);
+	if (unlikely(i != 0))
+		return i;
+#endif
 
 	return register_dmac(info);
 }
@@ -284,8 +333,12 @@
 static void __exit sh_dmac_exit(void)
 {
 #ifdef CONFIG_CPU_SH4
-	free_irq(DMAE_IRQ, 0);
-#endif
+	int n;
+
+	for (n = 0; n < NR_DMAE; n++) {
+		free_irq(get_dma_error_irq(n), (void *)dmae_name[n]);
+	}
+#endif /* CONFIG_CPU_SH4 */
 	unregister_dmac(&sh_dmac_info);
 }
 
diff --git a/arch/sh/drivers/dma/dma-sh.h b/arch/sh/drivers/dma/dma-sh.h
deleted file mode 100644
index 05fecd5..0000000
--- a/arch/sh/drivers/dma/dma-sh.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * arch/sh/drivers/dma/dma-sh.h
- *
- * Copyright (C) 2000  Takashi YOSHII
- * Copyright (C) 2003  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.
- */
-#ifndef __DMA_SH_H
-#define __DMA_SH_H
-
-#include <cpu/dma.h>
-
-/* Definitions for the SuperH DMAC */
-#define REQ_L	0x00000000
-#define REQ_E	0x00080000
-#define RACK_H	0x00000000
-#define RACK_L	0x00040000
-#define ACK_R	0x00000000
-#define ACK_W	0x00020000
-#define ACK_H	0x00000000
-#define ACK_L	0x00010000
-#define DM_INC	0x00004000
-#define DM_DEC	0x00008000
-#define SM_INC	0x00001000
-#define SM_DEC	0x00002000
-#define RS_IN	0x00000200
-#define RS_OUT	0x00000300
-#define TS_BLK	0x00000040
-#define TM_BUR	0x00000020
-#define CHCR_DE 0x00000001
-#define CHCR_TE 0x00000002
-#define CHCR_IE 0x00000004
-
-/* DMAOR definitions */
-#define DMAOR_AE	0x00000004
-#define DMAOR_NMIF	0x00000002
-#define DMAOR_DME	0x00000001
-
-/*
- * Define the default configuration for dual address memory-memory transfer.
- * The 0x400 value represents auto-request, external->external.
- */
-#define RS_DUAL	(DM_INC | SM_INC | 0x400 | TS_32)
-
-#define MAX_DMAC_CHANNELS	(CONFIG_NR_ONCHIP_DMA_CHANNELS)
-
-/*
- * Subtypes that have fewer channels than this simply need to change
- * CONFIG_NR_ONCHIP_DMA_CHANNELS. Likewise, subtypes with a larger number
- * of channels should expand on this.
- *
- * For most subtypes we can easily figure these values out with some
- * basic calculation, unfortunately on other subtypes these are more
- * scattered, so we just leave it unrolled for simplicity.
- */
-#define SAR	((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \
-				   SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30, \
-				   SH_DMAC_BASE + 0x50, SH_DMAC_BASE + 0x60})
-#define DAR	((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \
-				   SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34, \
-				   SH_DMAC_BASE + 0x54, SH_DMAC_BASE + 0x64})
-#define DMATCR	((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \
-				   SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38, \
-				   SH_DMAC_BASE + 0x58, SH_DMAC_BASE + 0x68})
-#define CHCR	((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \
-				   SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c, \
-				   SH_DMAC_BASE + 0x5c, SH_DMAC_BASE + 0x6c})
-
-#define DMAOR	(SH_DMAC_BASE + 0x40)
-
-#endif /* __DMA_SH_H */
-
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
index 078dc44..773d575 100644
--- a/arch/sh/drivers/pci/pci-sh7780.c
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -127,8 +127,8 @@
 	pci_write_reg(word, SH4_PCILSR0);
 	pci_write_reg(0x00000001, SH4_PCILSR1);
 	/* Set the values on window 0 PCI config registers */
-	word = (CONFIG_MEMORY_SIZE > 0x08000000) ? 0x10000000 : 0x08000000;
-	pci_write_reg(word | 0xa0000000, SH4_PCILAR0);
+	word = CONFIG_MEMORY_START | (CONFIG_MEMORY_SIZE - 0x01000000);
+	pci_write_reg(word, SH4_PCILAR0);
 	pci_write_reg(word, SH7780_PCIMBAR0);
 	/* Set the values on window 1 PCI config registers */
 	pci_write_reg(0x00000000, SH4_PCILAR1);
diff --git a/arch/sh/include/asm/addrspace.h b/arch/sh/include/asm/addrspace.h
index 36736c7..80d4081 100644
--- a/arch/sh/include/asm/addrspace.h
+++ b/arch/sh/include/asm/addrspace.h
@@ -31,7 +31,7 @@
 /* Returns the physical address of a PnSEG (n=1,2) address   */
 #define PHYSADDR(a)	(((unsigned long)(a)) & 0x1fffffff)
 
-#ifdef CONFIG_29BIT
+#if defined(CONFIG_29BIT) || defined(CONFIG_PMB_FIXED)
 /*
  * Map an address to a certain privileged segment
  */
@@ -43,7 +43,7 @@
 	((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG))
 #define P4SEGADDR(a)	\
 	((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG))
-#endif /* 29BIT */
+#endif /* 29BIT || PMB_FIXED */
 #endif /* P1SEG */
 
 /* Check if an address can be reached in 29 bits */
diff --git a/arch/sh/include/asm/atomic-irq.h b/arch/sh/include/asm/atomic-irq.h
index 74f7943..a0b3480 100644
--- a/arch/sh/include/asm/atomic-irq.h
+++ b/arch/sh/include/asm/atomic-irq.h
@@ -11,7 +11,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	*(long *)v += i;
+	v->counter += i;
 	local_irq_restore(flags);
 }
 
@@ -20,7 +20,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	*(long *)v -= i;
+	v->counter -= i;
 	local_irq_restore(flags);
 }
 
@@ -29,9 +29,9 @@
 	unsigned long temp, flags;
 
 	local_irq_save(flags);
-	temp = *(long *)v;
+	temp = v->counter;
 	temp += i;
-	*(long *)v = temp;
+	v->counter = temp;
 	local_irq_restore(flags);
 
 	return temp;
@@ -42,9 +42,9 @@
 	unsigned long temp, flags;
 
 	local_irq_save(flags);
-	temp = *(long *)v;
+	temp = v->counter;
 	temp -= i;
-	*(long *)v = temp;
+	v->counter = temp;
 	local_irq_restore(flags);
 
 	return temp;
@@ -55,7 +55,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	*(long *)v &= ~mask;
+	v->counter &= ~mask;
 	local_irq_restore(flags);
 }
 
@@ -64,7 +64,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	*(long *)v |= mask;
+	v->counter |= mask;
 	local_irq_restore(flags);
 }
 
diff --git a/arch/sh/include/asm/bitops-llsc.h b/arch/sh/include/asm/bitops-llsc.h
index 1d2fc0b..d8328be 100644
--- a/arch/sh/include/asm/bitops-llsc.h
+++ b/arch/sh/include/asm/bitops-llsc.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_SH_BITOPS_LLSC_H
 #define __ASM_SH_BITOPS_LLSC_H
 
-static inline void set_bit(int nr, volatile void * addr)
+static inline void set_bit(int nr, volatile void *addr)
 {
 	int	mask;
 	volatile unsigned int *a = addr;
@@ -13,16 +13,16 @@
 	__asm__ __volatile__ (
 		"1:						\n\t"
 		"movli.l	@%1, %0	! set_bit		\n\t"
-		"or		%3, %0				\n\t"
+		"or		%2, %0				\n\t"
 		"movco.l	%0, @%1				\n\t"
 		"bf		1b				\n\t"
-		: "=&z" (tmp), "=r" (a)
-		: "1" (a), "r" (mask)
+		: "=&z" (tmp)
+		: "r" (a), "r" (mask)
 		: "t", "memory"
 	);
 }
 
-static inline void clear_bit(int nr, volatile void * addr)
+static inline void clear_bit(int nr, volatile void *addr)
 {
 	int	mask;
 	volatile unsigned int *a = addr;
@@ -34,16 +34,16 @@
 	__asm__ __volatile__ (
 		"1:						\n\t"
 		"movli.l	@%1, %0	! clear_bit		\n\t"
-		"and		%3, %0				\n\t"
+		"and		%2, %0				\n\t"
 		"movco.l	%0, @%1				\n\t"
 		"bf		1b				\n\t"
-		: "=&z" (tmp), "=r" (a)
-		: "1" (a), "r" (~mask)
+		: "=&z" (tmp)
+		: "r" (a), "r" (~mask)
 		: "t", "memory"
 	);
 }
 
-static inline void change_bit(int nr, volatile void * addr)
+static inline void change_bit(int nr, volatile void *addr)
 {
 	int	mask;
 	volatile unsigned int *a = addr;
@@ -55,86 +55,86 @@
 	__asm__ __volatile__ (
 		"1:						\n\t"
 		"movli.l	@%1, %0	! change_bit		\n\t"
+		"xor		%2, %0				\n\t"
+		"movco.l	%0, @%1				\n\t"
+		"bf		1b				\n\t"
+		: "=&z" (tmp)
+		: "r" (a), "r" (mask)
+		: "t", "memory"
+	);
+}
+
+static inline int test_and_set_bit(int nr, volatile void *addr)
+{
+	int	mask, retval;
+	volatile unsigned int *a = addr;
+	unsigned long tmp;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+
+	__asm__ __volatile__ (
+		"1:						\n\t"
+		"movli.l	@%2, %0	! test_and_set_bit	\n\t"
+		"mov		%0, %1				\n\t"
+		"or		%3, %0				\n\t"
+		"movco.l	%0, @%2				\n\t"
+		"bf		1b				\n\t"
+		"and		%3, %1				\n\t"
+		: "=&z" (tmp), "=&r" (retval)
+		: "r" (a), "r" (mask)
+		: "t", "memory"
+	);
+
+	return retval != 0;
+}
+
+static inline int test_and_clear_bit(int nr, volatile void *addr)
+{
+	int	mask, retval;
+	volatile unsigned int *a = addr;
+	unsigned long tmp;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+
+	__asm__ __volatile__ (
+		"1:						\n\t"
+		"movli.l	@%2, %0	! test_and_clear_bit	\n\t"
+		"mov		%0, %1				\n\t"
+		"and		%4, %0				\n\t"
+		"movco.l	%0, @%2				\n\t"
+		"bf		1b				\n\t"
+		"and		%3, %1				\n\t"
+		"synco						\n\t"
+		: "=&z" (tmp), "=&r" (retval)
+		: "r" (a), "r" (mask), "r" (~mask)
+		: "t", "memory"
+	);
+
+	return retval != 0;
+}
+
+static inline int test_and_change_bit(int nr, volatile void *addr)
+{
+	int	mask, retval;
+	volatile unsigned int *a = addr;
+	unsigned long tmp;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+
+	__asm__ __volatile__ (
+		"1:						\n\t"
+		"movli.l	@%2, %0	! test_and_change_bit	\n\t"
+		"mov		%0, %1				\n\t"
 		"xor		%3, %0				\n\t"
-		"movco.l	%0, @%1				\n\t"
+		"movco.l	%0, @%2				\n\t"
 		"bf		1b				\n\t"
-		: "=&z" (tmp), "=r" (a)
-		: "1" (a), "r" (mask)
-		: "t", "memory"
-	);
-}
-
-static inline int test_and_set_bit(int nr, volatile void * addr)
-{
-	int	mask, retval;
-	volatile unsigned int *a = addr;
-	unsigned long tmp;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-
-	__asm__ __volatile__ (
-		"1:						\n\t"
-		"movli.l	@%1, %0	! test_and_set_bit	\n\t"
-		"mov		%0, %2				\n\t"
-		"or		%4, %0				\n\t"
-		"movco.l	%0, @%1				\n\t"
-		"bf		1b				\n\t"
-		"and		%4, %2				\n\t"
-		: "=&z" (tmp), "=r" (a), "=&r" (retval)
-		: "1" (a), "r" (mask)
-		: "t", "memory"
-	);
-
-	return retval != 0;
-}
-
-static inline int test_and_clear_bit(int nr, volatile void * addr)
-{
-	int	mask, retval;
-	volatile unsigned int *a = addr;
-	unsigned long tmp;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-
-	__asm__ __volatile__ (
-		"1:						\n\t"
-		"movli.l	@%1, %0	! test_and_clear_bit	\n\t"
-		"mov		%0, %2				\n\t"
-		"and		%5, %0				\n\t"
-		"movco.l	%0, @%1				\n\t"
-		"bf		1b				\n\t"
-		"and		%4, %2				\n\t"
+		"and		%3, %1				\n\t"
 		"synco						\n\t"
-		: "=&z" (tmp), "=r" (a), "=&r" (retval)
-		: "1" (a), "r" (mask), "r" (~mask)
-		: "t", "memory"
-	);
-
-	return retval != 0;
-}
-
-static inline int test_and_change_bit(int nr, volatile void * addr)
-{
-	int	mask, retval;
-	volatile unsigned int *a = addr;
-	unsigned long tmp;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-
-	__asm__ __volatile__ (
-		"1:						\n\t"
-		"movli.l	@%1, %0	! test_and_change_bit	\n\t"
-		"mov		%0, %2				\n\t"
-		"xor		%4, %0				\n\t"
-		"movco.l	%0, @%1				\n\t"
-		"bf		1b				\n\t"
-		"and		%4, %2				\n\t"
-		"synco						\n\t"
-		: "=&z" (tmp), "=r" (a), "=&r" (retval)
-		: "1" (a), "r" (mask)
+		: "=&z" (tmp), "=&r" (retval)
+		: "r" (a), "r" (mask)
 		: "t", "memory"
 	);
 
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h
index f9c8858..2f6c962 100644
--- a/arch/sh/include/asm/clock.h
+++ b/arch/sh/include/asm/clock.h
@@ -15,6 +15,7 @@
 	void (*disable)(struct clk *clk);
 	void (*recalc)(struct clk *clk);
 	int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id);
+	int (*set_parent)(struct clk *clk, struct clk *parent);
 	long (*round_rate)(struct clk *clk, unsigned long rate);
 };
 
diff --git a/arch/sh/include/asm/cmpxchg-llsc.h b/arch/sh/include/asm/cmpxchg-llsc.h
index aee3bf2..0fac3da 100644
--- a/arch/sh/include/asm/cmpxchg-llsc.h
+++ b/arch/sh/include/asm/cmpxchg-llsc.h
@@ -8,14 +8,14 @@
 
 	__asm__ __volatile__ (
 		"1:					\n\t"
-		"movli.l	@%1, %0	! xchg_u32	\n\t"
-		"mov		%0, %2			\n\t"
-		"mov		%4, %0			\n\t"
-		"movco.l	%0, @%1			\n\t"
+		"movli.l	@%2, %0	! xchg_u32	\n\t"
+		"mov		%0, %1			\n\t"
+		"mov		%3, %0			\n\t"
+		"movco.l	%0, @%2			\n\t"
 		"bf		1b			\n\t"
 		"synco					\n\t"
-		: "=&z"(tmp), "=r" (m), "=&r" (retval)
-		: "1" (m), "r" (val)
+		: "=&z"(tmp), "=&r" (retval)
+		: "r" (m), "r" (val)
 		: "t", "memory"
 	);
 
@@ -29,14 +29,14 @@
 
 	__asm__ __volatile__ (
 		"1:					\n\t"
-		"movli.l	@%1, %0	! xchg_u8	\n\t"
-		"mov		%0, %2			\n\t"
-		"mov		%4, %0			\n\t"
-		"movco.l	%0, @%1			\n\t"
+		"movli.l	@%2, %0	! xchg_u8	\n\t"
+		"mov		%0, %1			\n\t"
+		"mov		%3, %0			\n\t"
+		"movco.l	%0, @%2			\n\t"
 		"bf		1b			\n\t"
 		"synco					\n\t"
-		: "=&z"(tmp), "=r" (m), "=&r" (retval)
-		: "1" (m), "r" (val & 0xff)
+		: "=&z"(tmp), "=&r" (retval)
+		: "r" (m), "r" (val & 0xff)
 		: "t", "memory"
 	);
 
@@ -51,17 +51,17 @@
 
 	__asm__ __volatile__ (
 		"1:						\n\t"
-		"movli.l	@%1, %0	! __cmpxchg_u32		\n\t"
-		"mov		%0, %2				\n\t"
-		"cmp/eq		%2, %4				\n\t"
+		"movli.l	@%2, %0	! __cmpxchg_u32		\n\t"
+		"mov		%0, %1				\n\t"
+		"cmp/eq		%1, %3				\n\t"
 		"bf		2f				\n\t"
-		"mov		%5, %0				\n\t"
+		"mov		%3, %0				\n\t"
 		"2:						\n\t"
-		"movco.l	%0, @%1				\n\t"
+		"movco.l	%0, @%2				\n\t"
 		"bf		1b				\n\t"
 		"synco						\n\t"
-		: "=&z" (tmp), "=r" (m), "=&r" (retval)
-		: "1" (m), "r" (old), "r" (new)
+		: "=&z" (tmp), "=&r" (retval)
+		: "r" (m), "r" (old), "r" (new)
 		: "t", "memory"
 	);
 
diff --git a/arch/sh/include/asm/cpu-features.h b/arch/sh/include/asm/cpu-features.h
index 86308aa..694abe4 100644
--- a/arch/sh/include/asm/cpu-features.h
+++ b/arch/sh/include/asm/cpu-features.h
@@ -21,5 +21,6 @@
 #define CPU_HAS_LLSC		0x0040	/* movli.l/movco.l */
 #define CPU_HAS_L2_CACHE	0x0080	/* Secondary cache / URAM */
 #define CPU_HAS_OP32		0x0100	/* 32-bit instruction support */
+#define CPU_HAS_PTEAEX		0x0200	/* PTE ASID Extension support */
 
 #endif /* __ASM_SH_CPU_FEATURES_H */
diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h
new file mode 100644
index 0000000..0c8f8e1
--- /dev/null
+++ b/arch/sh/include/asm/dma-sh.h
@@ -0,0 +1,118 @@
+/*
+ * arch/sh/include/asm/dma-sh.h
+ *
+ * Copyright (C) 2000  Takashi YOSHII
+ * Copyright (C) 2003  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.
+ */
+#ifndef __DMA_SH_H
+#define __DMA_SH_H
+
+#include <asm/dma.h>
+#include <cpu/dma.h>
+
+/* DMAOR contorl: The DMAOR access size is different by CPU.*/
+#if defined(CONFIG_CPU_SUBTYPE_SH7723)	|| \
+    defined(CONFIG_CPU_SUBTYPE_SH7780)	|| \
+    defined(CONFIG_CPU_SUBTYPE_SH7785)
+#define dmaor_read_reg(n) \
+    (n ? ctrl_inw(SH_DMAC_BASE1 + DMAOR) \
+	: ctrl_inw(SH_DMAC_BASE0 + DMAOR))
+#define dmaor_write_reg(n, data) \
+    (n ? ctrl_outw(data, SH_DMAC_BASE1 + DMAOR) \
+    : ctrl_outw(data, SH_DMAC_BASE0 + DMAOR))
+#else /* Other CPU */
+#define dmaor_read_reg(n) ctrl_inw(SH_DMAC_BASE0 + DMAOR)
+#define dmaor_write_reg(n, data) ctrl_outw(data, SH_DMAC_BASE0 + DMAOR)
+#endif
+
+static int dmte_irq_map[] __maybe_unused = {
+#if (MAX_DMA_CHANNELS >= 4)
+    DMTE0_IRQ,
+    DMTE0_IRQ + 1,
+    DMTE0_IRQ + 2,
+    DMTE0_IRQ + 3,
+#endif
+#if (MAX_DMA_CHANNELS >= 6)
+    DMTE4_IRQ,
+    DMTE4_IRQ + 1,
+#endif
+#if (MAX_DMA_CHANNELS >= 8)
+    DMTE6_IRQ,
+    DMTE6_IRQ + 1,
+#endif
+#if (MAX_DMA_CHANNELS >= 12)
+    DMTE8_IRQ,
+    DMTE9_IRQ,
+    DMTE10_IRQ,
+    DMTE11_IRQ,
+#endif
+};
+
+/* Definitions for the SuperH DMAC */
+#define REQ_L	0x00000000
+#define REQ_E	0x00080000
+#define RACK_H	0x00000000
+#define RACK_L	0x00040000
+#define ACK_R	0x00000000
+#define ACK_W	0x00020000
+#define ACK_H	0x00000000
+#define ACK_L	0x00010000
+#define DM_INC	0x00004000
+#define DM_DEC	0x00008000
+#define SM_INC	0x00001000
+#define SM_DEC	0x00002000
+#define RS_IN	0x00000200
+#define RS_OUT	0x00000300
+#define TS_BLK	0x00000040
+#define TM_BUR	0x00000020
+#define CHCR_DE 0x00000001
+#define CHCR_TE 0x00000002
+#define CHCR_IE 0x00000004
+
+/* DMAOR definitions */
+#define DMAOR_AE	0x00000004
+#define DMAOR_NMIF	0x00000002
+#define DMAOR_DME	0x00000001
+
+/*
+ * Define the default configuration for dual address memory-memory transfer.
+ * The 0x400 value represents auto-request, external->external.
+ */
+#define RS_DUAL	(DM_INC | SM_INC | 0x400 | TS_32)
+
+/* DMA base address */
+static u32 dma_base_addr[] __maybe_unused = {
+#if (MAX_DMA_CHANNELS >= 4)
+	SH_DMAC_BASE0 + 0x00,	/* channel 0 */
+	SH_DMAC_BASE0 + 0x10,
+	SH_DMAC_BASE0 + 0x20,
+	SH_DMAC_BASE0 + 0x30,
+#endif
+#if (MAX_DMA_CHANNELS >= 6)
+	SH_DMAC_BASE0 + 0x50,
+	SH_DMAC_BASE0 + 0x60,
+#endif
+#if (MAX_DMA_CHANNELS >= 8)
+	SH_DMAC_BASE1 + 0x00,
+	SH_DMAC_BASE1 + 0x10,
+#endif
+#if (MAX_DMA_CHANNELS >= 12)
+	SH_DMAC_BASE1 + 0x20,
+	SH_DMAC_BASE1 + 0x30,
+	SH_DMAC_BASE1 + 0x50,
+	SH_DMAC_BASE1 + 0x60, /* channel 11 */
+#endif
+};
+
+/* DMA register */
+#define SAR     0x00
+#define DAR     0x04
+#define TCR     0x08
+#define CHCR    0x0C
+#define DMAOR	0x40
+
+#endif /* __DMA_SH_H */
diff --git a/arch/sh/include/asm/dma.h b/arch/sh/include/asm/dma.h
index beca712..6bd1784 100644
--- a/arch/sh/include/asm/dma.h
+++ b/arch/sh/include/asm/dma.h
@@ -25,9 +25,9 @@
 #define MAX_DMA_ADDRESS		(PAGE_OFFSET+0x10000000)
 
 #ifdef CONFIG_NR_DMA_CHANNELS
-#  define MAX_DMA_CHANNELS	(CONFIG_NR_DMA_CHANNELS)
+#  define MAX_DMA_CHANNELS   (CONFIG_NR_DMA_CHANNELS)
 #else
-#  define MAX_DMA_CHANNELS	(CONFIG_NR_ONCHIP_DMA_CHANNELS)
+#  define MAX_DMA_CHANNELS   (CONFIG_NR_ONCHIP_DMA_CHANNELS)
 #endif
 
 /*
diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S
index 2dab0b8..3a4752a 100644
--- a/arch/sh/include/asm/entry-macros.S
+++ b/arch/sh/include/asm/entry-macros.S
@@ -31,3 +31,8 @@
 #endif	
 	.endm
 
+#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4)
+# define PREF(x)	pref	@x
+#else
+# define PREF(x)	nop
+#endif
diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h
index 9067365..61f93da 100644
--- a/arch/sh/include/asm/gpio.h
+++ b/arch/sh/include/asm/gpio.h
@@ -19,8 +19,42 @@
 #include <cpu/gpio.h>
 #endif
 
+#define ARCH_NR_GPIOS 512
+#include <asm-generic/gpio.h>
+
+#ifdef CONFIG_GPIOLIB
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	__gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+	return __gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	WARN_ON(1);
+	return -ENOSYS;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+	WARN_ON(1);
+	return -EINVAL;
+}
+
+#endif /* CONFIG_GPIOLIB */
+
 typedef unsigned short pinmux_enum_t;
-typedef unsigned char pinmux_flag_t;
+typedef unsigned short pinmux_flag_t;
 
 #define PINMUX_TYPE_NONE            0
 #define PINMUX_TYPE_FUNCTION        1
@@ -34,6 +68,11 @@
 #define PINMUX_FLAG_WANT_PULLUP     (1 << 3)
 #define PINMUX_FLAG_WANT_PULLDOWN   (1 << 4)
 
+#define PINMUX_FLAG_DBIT_SHIFT      5
+#define PINMUX_FLAG_DBIT            (0x1f << PINMUX_FLAG_DBIT_SHIFT)
+#define PINMUX_FLAG_DREG_SHIFT      10
+#define PINMUX_FLAG_DREG            (0x3f << PINMUX_FLAG_DREG_SHIFT)
+
 struct pinmux_gpio {
 	pinmux_enum_t enum_id;
 	pinmux_flag_t flags;
@@ -54,7 +93,7 @@
 	.enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)]) \
 
 struct pinmux_data_reg {
-	unsigned long reg, reg_width;
+	unsigned long reg, reg_width, reg_shadow;
 	pinmux_enum_t *enum_ids;
 };
 
@@ -89,34 +128,9 @@
 	unsigned int gpio_data_size;
 
 	unsigned long *gpio_in_use;
+	struct gpio_chip chip;
 };
 
 int register_pinmux(struct pinmux_info *pip);
 
-int __gpio_request(unsigned gpio);
-static inline int gpio_request(unsigned gpio, const char *label)
-{
-	return __gpio_request(gpio);
-}
-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);
-
-/* IRQ modes are unspported */
-static inline int gpio_to_irq(unsigned gpio)
-{
-	WARN_ON(1);
-	return -EINVAL;
-}
-
-static inline int irq_to_gpio(unsigned irq)
-{
-	WARN_ON(1);
-	return -EINVAL;
-}
-
-#include <asm-generic/gpio.h>
-
 #endif /* __ASM_SH_GPIO_H */
diff --git a/arch/sh/include/asm/hd64461.h b/arch/sh/include/asm/hd64461.h
index 8c1353b..52b4b62 100644
--- a/arch/sh/include/asm/hd64461.h
+++ b/arch/sh/include/asm/hd64461.h
@@ -242,7 +242,6 @@
 #include <asm/io_generic.h>
 
 /* arch/sh/cchips/hd6446x/hd64461/setup.c */
-int hd64461_irq_demux(int irq);
 void hd64461_register_irq_demux(int irq,
 				int (*demux) (int irq, void *dev), void *dev);
 void hd64461_unregister_irq_demux(int irq);
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 61f6dae..0454f8d 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -238,7 +238,7 @@
 static inline void __iomem *
 __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
 {
-#ifdef CONFIG_SUPERH32
+#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED)
 	unsigned long last_addr = offset + size - 1;
 #endif
 	void __iomem *ret;
@@ -247,7 +247,7 @@
 	if (ret)
 		return ret;
 
-#ifdef CONFIG_SUPERH32
+#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED)
 	/*
 	 * For P1 and P2 space this is trivial, as everything is already
 	 * mapped. Uncached access for P1 addresses are done through P2.
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 6078d8e..613644a 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -16,7 +16,7 @@
 	? (MAX_STACK_SIZE) \
 	: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
 
-#define regs_return_value(regs)		((regs)->regs[0])
+#define regs_return_value(_regs)		((_regs)->regs[0])
 #define flush_insn_slot(p)		do { } while (0)
 #define kretprobe_blacklist_size	0
 
diff --git a/arch/sh/include/asm/mmu_context.h b/arch/sh/include/asm/mmu_context.h
index 5d9157b..2a9c55f 100644
--- a/arch/sh/include/asm/mmu_context.h
+++ b/arch/sh/include/asm/mmu_context.h
@@ -19,13 +19,18 @@
  *    (a) TLB cache version (or round, cycle whatever expression you like)
  *    (b) ASID (Address Space IDentifier)
  */
+#ifdef CONFIG_CPU_HAS_PTEAEX
+#define MMU_CONTEXT_ASID_MASK		0x0000ffff
+#else
 #define MMU_CONTEXT_ASID_MASK		0x000000ff
-#define MMU_CONTEXT_VERSION_MASK	0xffffff00
-#define MMU_CONTEXT_FIRST_VERSION	0x00000100
-#define NO_CONTEXT			0UL
+#endif
 
-/* ASID is 8-bit value, so it can't be 0x100 */
-#define MMU_NO_ASID			0x100
+#define MMU_CONTEXT_VERSION_MASK	(~0UL & ~MMU_CONTEXT_ASID_MASK)
+#define MMU_CONTEXT_FIRST_VERSION	(MMU_CONTEXT_ASID_MASK + 1)
+
+/* Impossible ASID value, to differentiate from NO_CONTEXT. */
+#define MMU_NO_ASID			MMU_CONTEXT_FIRST_VERSION
+#define NO_CONTEXT			0UL
 
 #define asid_cache(cpu)		(cpu_data[cpu].asid_cache)
 
diff --git a/arch/sh/include/asm/mmu_context_32.h b/arch/sh/include/asm/mmu_context_32.h
index f4f9aeb..8ef800c 100644
--- a/arch/sh/include/asm/mmu_context_32.h
+++ b/arch/sh/include/asm/mmu_context_32.h
@@ -10,6 +10,17 @@
 	/* Do nothing */
 }
 
+#ifdef CONFIG_CPU_HAS_PTEAEX
+static inline void set_asid(unsigned long asid)
+{
+	__raw_writel(asid, MMU_PTEAEX);
+}
+
+static inline unsigned long get_asid(void)
+{
+	return __raw_readl(MMU_PTEAEX) & MMU_CONTEXT_ASID_MASK;
+}
+#else
 static inline void set_asid(unsigned long asid)
 {
 	unsigned long __dummy;
@@ -33,6 +44,7 @@
 	asid &= MMU_CONTEXT_ASID_MASK;
 	return asid;
 }
+#endif /* CONFIG_CPU_HAS_PTEAEX */
 
 /* MMU_TTB is used for optimizing the fault handling. */
 static inline void set_TTB(pgd_t *pgd)
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index 5871d78..9c6d21e 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -129,7 +129,12 @@
  * is not visible (it is part of the PMB mapping) and so needs to be
  * added or subtracted as required.
  */
-#ifdef CONFIG_32BIT
+#if defined(CONFIG_PMB_FIXED)
+/* phys = virt - PAGE_OFFSET - (__MEMORY_START & 0xe0000000) */
+#define PMB_OFFSET	(PAGE_OFFSET - PXSEG(__MEMORY_START))
+#define __pa(x)	((unsigned long)(x) - PMB_OFFSET)
+#define __va(x)	((void *)((unsigned long)(x) + PMB_OFFSET))
+#elif defined(CONFIG_32BIT)
 #define __pa(x)	((unsigned long)(x)-PAGE_OFFSET+__MEMORY_START)
 #define __va(x)	((void *)((unsigned long)(x)+PAGE_OFFSET-__MEMORY_START))
 #else
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index 1ef4b24..1fd58b4 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -31,7 +31,7 @@
 	CPU_SH7760, CPU_SH4_202, CPU_SH4_501,
 
 	/* SH-4A types */
-	CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
+	CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SH7786,
 	CPU_SH7723, CPU_SHX3,
 
 	/* SH4AL-DSP types */
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h
index d79063c..efdd78a 100644
--- a/arch/sh/include/asm/processor_32.h
+++ b/arch/sh/include/asm/processor_32.h
@@ -108,12 +108,12 @@
 /*
  * Do necessary setup to start up a newly executed thread.
  */
-#define start_thread(regs, new_pc, new_sp)	 \
+#define start_thread(_regs, new_pc, new_sp)	 \
 	set_fs(USER_DS);			 \
-	regs->pr = 0;				 \
-	regs->sr = SR_FD;	/* User mode. */ \
-	regs->pc = new_pc;			 \
-	regs->regs[15] = new_sp
+	_regs->pr = 0;				 \
+	_regs->sr = SR_FD;	/* User mode. */ \
+	_regs->pc = new_pc;			 \
+	_regs->regs[15] = new_sp
 
 /* Forward declaration, a strange C thing */
 struct task_struct;
@@ -189,10 +189,9 @@
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->pc)
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->regs[15])
 
-#define user_stack_pointer(regs)	((regs)->regs[15])
+#define user_stack_pointer(_regs)	((_regs)->regs[15])
 
-#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \
-    defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4)
 #define PREFETCH_STRIDE		L1_CACHE_BYTES
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h
index 803177f..5727d31 100644
--- a/arch/sh/include/asm/processor_64.h
+++ b/arch/sh/include/asm/processor_64.h
@@ -145,13 +145,13 @@
  */
 #define SR_USER (SR_MMU | SR_FD)
 
-#define start_thread(regs, new_pc, new_sp)			\
+#define start_thread(_regs, new_pc, new_sp)			\
 	set_fs(USER_DS);					\
-	regs->sr = SR_USER;	/* User mode. */		\
-	regs->pc = new_pc - 4;	/* Compensate syscall exit */	\
-	regs->pc |= 1;		/* Set SHmedia ! */		\
-	regs->regs[18] = 0;					\
-	regs->regs[15] = new_sp
+	_regs->sr = SR_USER;	/* User mode. */		\
+	_regs->pc = new_pc - 4;	/* Compensate syscall exit */	\
+	_regs->pc |= 1;		/* Set SHmedia ! */		\
+	_regs->regs[18] = 0;					\
+	_regs->regs[15] = new_sp
 
 /* Forward declaration, a strange C thing */
 struct task_struct;
@@ -226,7 +226,7 @@
 #define KSTK_EIP(tsk)  ((tsk)->thread.pc)
 #define KSTK_ESP(tsk)  ((tsk)->thread.sp)
 
-#define user_stack_pointer(regs)	((regs)->regs[15])
+#define user_stack_pointer(_regs)	((_regs)->regs[15])
 
 #endif	/* __ASSEMBLY__ */
 #endif /* __ASM_SH_PROCESSOR_64_H */
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index 12912ab..81c6568 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -122,14 +122,12 @@
 #ifdef CONFIG_SH_DSP
 #define task_pt_regs(task) \
 	((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
-		 - sizeof(struct pt_dspregs) - sizeof(unsigned long)) - 1)
+		 - sizeof(struct pt_dspregs)) - 1)
 #define task_pt_dspregs(task) \
-	((struct pt_dspregs *) (task_stack_page(task) + THREAD_SIZE \
-		 - sizeof(unsigned long)) - 1)
+	((struct pt_dspregs *) (task_stack_page(task) + THREAD_SIZE) - 1)
 #else
 #define task_pt_regs(task) \
-	((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
-		 - sizeof(unsigned long)) - 1)
+	((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE) - 1)
 #endif
 
 static inline unsigned long profile_pc(struct pt_regs *regs)
diff --git a/arch/sh/include/asm/sections.h b/arch/sh/include/asm/sections.h
index 8f8f4ad..01a4076a37 100644
--- a/arch/sh/include/asm/sections.h
+++ b/arch/sh/include/asm/sections.h
@@ -3,6 +3,7 @@
 
 #include <asm-generic/sections.h>
 
+extern void __nosave_begin, __nosave_end;
 extern long __machvec_start, __machvec_end;
 extern char __uncached_start, __uncached_end;
 extern char _ebss[];
diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h
new file mode 100644
index 0000000..b1b9953
--- /dev/null
+++ b/arch/sh/include/asm/suspend.h
@@ -0,0 +1,22 @@
+#ifndef _ASM_SH_SUSPEND_H
+#define _ASM_SH_SUSPEND_H
+
+#ifndef __ASSEMBLY__
+static inline int arch_prepare_suspend(void) { return 0; }
+
+#include <asm/ptrace.h>
+
+struct swsusp_arch_regs {
+	struct pt_regs user_regs;
+	unsigned long bank1_regs[8];
+};
+#endif
+
+/* flags passed to assembly suspend code */
+#define SUSP_SH_SLEEP		(1 << 0) /* Regular sleep mode */
+#define SUSP_SH_STANDBY		(1 << 1) /* SH-Mobile Software standby mode */
+#define SUSP_SH_RSTANDBY	(1 << 2) /* SH-Mobile R-standby mode */
+#define SUSP_SH_USTANDBY	(1 << 3) /* SH-Mobile U-standby mode */
+#define SUSP_SH_SF		(1 << 4) /* Enable self-refresh */
+
+#endif /* _ASM_SH_SUSPEND_H */
diff --git a/arch/sh/include/asm/timer.h b/arch/sh/include/asm/timer.h
index a7ca3a1..4c3b66e3 100644
--- a/arch/sh/include/asm/timer.h
+++ b/arch/sh/include/asm/timer.h
@@ -9,7 +9,6 @@
 	int (*init)(void);
 	int (*start)(void);
 	int (*stop)(void);
-	cycle_t (*read)(void);
 #ifndef CONFIG_GENERIC_TIME
 	unsigned long (*get_offset)(void);
 #endif
@@ -39,6 +38,7 @@
 
 /* arch/sh/kernel/time.c */
 void handle_timer_tick(void);
-extern unsigned long sh_hpt_frequency;
+
+extern struct clocksource clocksource_sh;
 
 #endif /* __ASM_SH_TIMER_H */
diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h
index 88ff1ae..9c16f73 100644
--- a/arch/sh/include/asm/tlb.h
+++ b/arch/sh/include/asm/tlb.h
@@ -6,22 +6,106 @@
 #endif
 
 #ifndef __ASSEMBLY__
+#include <linux/pagemap.h>
 
-#define tlb_start_vma(tlb, vma) \
-	flush_cache_range(vma, vma->vm_start, vma->vm_end)
-
-#define tlb_end_vma(tlb, vma)	\
-	flush_tlb_range(vma, vma->vm_start, vma->vm_end)
-
-#define __tlb_remove_tlb_entry(tlb, pte, address)	do { } while (0)
+#ifdef CONFIG_MMU
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 /*
- * Flush whole TLBs for MM
+ * TLB handling.  This allows us to remove pages from the page
+ * tables, and efficiently handle the TLB issues.
  */
-#define tlb_flush(tlb)				flush_tlb_mm((tlb)->mm)
+struct mmu_gather {
+	struct mm_struct	*mm;
+	unsigned int		fullmm;
+	unsigned long		start, end;
+};
 
-#include <linux/pagemap.h>
+DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+static inline void init_tlb_gather(struct mmu_gather *tlb)
+{
+	tlb->start = TASK_SIZE;
+	tlb->end = 0;
+
+	if (tlb->fullmm) {
+		tlb->start = 0;
+		tlb->end = TASK_SIZE;
+	}
+}
+
+static inline struct mmu_gather *
+tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
+{
+	struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
+
+	tlb->mm = mm;
+	tlb->fullmm = full_mm_flush;
+
+	init_tlb_gather(tlb);
+
+	return tlb;
+}
+
+static inline void
+tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
+{
+	if (tlb->fullmm)
+		flush_tlb_mm(tlb->mm);
+
+	/* keep the page table cache within bounds */
+	check_pgt_cache();
+
+	put_cpu_var(mmu_gathers);
+}
+
+static inline void
+tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long address)
+{
+	if (tlb->start > address)
+		tlb->start = address;
+	if (tlb->end < address + PAGE_SIZE)
+		tlb->end = address + PAGE_SIZE;
+}
+
+/*
+ * In the case of tlb vma handling, we can optimise these away in the
+ * case where we're doing a full MM flush.  When we're doing a munmap,
+ * the vmas are adjusted to only cover the region to be torn down.
+ */
+static inline void
+tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+{
+	if (!tlb->fullmm)
+		flush_cache_range(vma, vma->vm_start, vma->vm_end);
+}
+
+static inline void
+tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+{
+	if (!tlb->fullmm && tlb->end) {
+		flush_tlb_range(vma, tlb->start, tlb->end);
+		init_tlb_gather(tlb);
+	}
+}
+
+#define tlb_remove_page(tlb,page)	free_page_and_swap_cache(page)
+#define pte_free_tlb(tlb, ptep)		pte_free((tlb)->mm, ptep)
+#define pmd_free_tlb(tlb, pmdp)		pmd_free((tlb)->mm, pmdp)
+#define pud_free_tlb(tlb, pudp)		pud_free((tlb)->mm, pudp)
+
+#define tlb_migrate_finish(mm)		do { } while (0)
+
+#else /* CONFIG_MMU */
+
+#define tlb_start_vma(tlb, vma)				do { } while (0)
+#define tlb_end_vma(tlb, vma)				do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, pte, address)	do { } while (0)
+#define tlb_flush(tlb)					do { } while (0)
+
 #include <asm-generic/tlb.h>
 
+#endif /* CONFIG_MMU */
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_SH_TLB_H */
diff --git a/arch/sh/include/cpu-sh3/cpu/dma.h b/arch/sh/include/cpu-sh3/cpu/dma.h
index 6813c32..0ea15f3 100644
--- a/arch/sh/include/cpu-sh3/cpu/dma.h
+++ b/arch/sh/include/cpu-sh3/cpu/dma.h
@@ -1,22 +1,17 @@
 #ifndef __ASM_CPU_SH3_DMA_H
 #define __ASM_CPU_SH3_DMA_H
 
-
 #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
-#define SH_DMAC_BASE	0xa4010020
-#else
-#define SH_DMAC_BASE	0xa4000020
+    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7710) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7712)
+#define SH_DMAC_BASE0	0xa4010020
+#else /* SH7705/06/07/09 */
+#define SH_DMAC_BASE0	0xa4000020
 #endif
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7720) || defined(CONFIG_CPU_SUBTYPE_SH7709)
 #define DMTE0_IRQ	48
-#define DMTE1_IRQ	49
-#define DMTE2_IRQ	50
-#define DMTE3_IRQ	51
 #define DMTE4_IRQ	76
-#define DMTE5_IRQ	77
-#endif
 
 /* Definitions for the SuperH DMAC */
 #define TM_BURST	0x00000020
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
new file mode 100644
index 0000000..0ed5178
--- /dev/null
+++ b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
@@ -0,0 +1,94 @@
+#ifndef __ASM_SH_CPU_SH4_DMA_SH7780_H
+#define __ASM_SH_CPU_SH4_DMA_SH7780_H
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7343) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7722) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7730)
+#define DMTE0_IRQ	48
+#define DMTE4_IRQ	76
+#define DMAE0_IRQ	78	/* DMA Error IRQ*/
+#define SH_DMAC_BASE0	0xFE008020
+#define SH_DMARS_BASE	0xFE009000
+#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7764)
+#define DMTE0_IRQ	34
+#define DMTE4_IRQ	44
+#define DMAE0_IRQ	38
+#define SH_DMAC_BASE0	0xFF608020
+#define SH_DMARS_BASE	0xFF609000
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#define DMTE0_IRQ	48	/* DMAC0A*/
+#define DMTE4_IRQ	40	/* DMAC0B */
+#define DMTE6_IRQ	42
+#define DMTE8_IRQ	76	/* DMAC1A */
+#define DMTE9_IRQ	77
+#define DMTE10_IRQ	72	/* DMAC1B */
+#define DMTE11_IRQ	73
+#define DMAE0_IRQ	78	/* DMA Error IRQ*/
+#define DMAE1_IRQ	74	/* DMA Error IRQ*/
+#define SH_DMAC_BASE0	0xFE008020
+#define SH_DMAC_BASE1	0xFDC08020
+#define SH_DMARS_BASE	0xFDC09000
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+#define DMTE0_IRQ	34
+#define DMTE4_IRQ	44
+#define DMTE6_IRQ	46
+#define DMTE8_IRQ	92
+#define DMTE9_IRQ	93
+#define DMTE10_IRQ	94
+#define DMTE11_IRQ	95
+#define DMAE0_IRQ	38	/* DMA Error IRQ */
+#define SH_DMAC_BASE0	0xFC808020
+#define SH_DMAC_BASE1	0xFC818020
+#define SH_DMARS_BASE	0xFC809000
+#else /* SH7785 */
+#define DMTE0_IRQ	33
+#define DMTE4_IRQ	37
+#define DMTE6_IRQ	52
+#define DMTE8_IRQ	54
+#define DMTE9_IRQ	55
+#define DMTE10_IRQ	56
+#define DMTE11_IRQ	57
+#define DMAE0_IRQ	39	/* DMA Error IRQ0 */
+#define DMAE1_IRQ	58	/* DMA Error IRQ1 */
+#define SH_DMAC_BASE0	0xFC808020
+#define SH_DMAC_BASE1	0xFCC08020
+#define SH_DMARS_BASE	0xFC809000
+#endif
+
+#define REQ_HE	0x000000C0
+#define REQ_H	0x00000080
+#define REQ_LE	0x00000040
+#define TM_BURST 0x0000020
+#define TS_8	0x00000000
+#define TS_16	0x00000008
+#define TS_32	0x00000010
+#define TS_16BLK	0x00000018
+#define TS_32BLK	0x00100000
+
+/*
+ * The SuperH DMAC supports a number of transmit sizes, we list them here,
+ * with their respective values as they appear in the CHCR registers.
+ *
+ * Defaults to a 64-bit transfer size.
+ */
+enum {
+	XMIT_SZ_8BIT,
+	XMIT_SZ_16BIT,
+	XMIT_SZ_32BIT,
+	XMIT_SZ_128BIT,
+	XMIT_SZ_256BIT,
+};
+
+/*
+ * The DMA count is defined as the number of bytes to transfer.
+ */
+static unsigned int ts_shift[] __maybe_unused = {
+	[XMIT_SZ_8BIT]		= 0,
+	[XMIT_SZ_16BIT]		= 1,
+	[XMIT_SZ_32BIT]		= 2,
+	[XMIT_SZ_128BIT]	= 4,
+	[XMIT_SZ_256BIT]	= 5,
+};
+
+#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh7780.h b/arch/sh/include/cpu-sh4/cpu/dma-sh7780.h
deleted file mode 100644
index 71b426a..0000000
--- a/arch/sh/include/cpu-sh4/cpu/dma-sh7780.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef __ASM_SH_CPU_SH4_DMA_SH7780_H
-#define __ASM_SH_CPU_SH4_DMA_SH7780_H
-
-#define REQ_HE	0x000000C0
-#define REQ_H	0x00000080
-#define REQ_LE	0x00000040
-#define TM_BURST 0x0000020
-#define TS_8	0x00000000
-#define TS_16	0x00000008
-#define TS_32	0x00000010
-#define TS_16BLK	0x00000018
-#define TS_32BLK	0x00100000
-
-/*
- * The SuperH DMAC supports a number of transmit sizes, we list them here,
- * with their respective values as they appear in the CHCR registers.
- *
- * Defaults to a 64-bit transfer size.
- */
-enum {
-	XMIT_SZ_8BIT,
-	XMIT_SZ_16BIT,
-	XMIT_SZ_32BIT,
-	XMIT_SZ_128BIT,
-	XMIT_SZ_256BIT,
-};
-
-/*
- * The DMA count is defined as the number of bytes to transfer.
- */
-static unsigned int ts_shift[] __maybe_unused = {
-	[XMIT_SZ_8BIT]		= 0,
-	[XMIT_SZ_16BIT]		= 1,
-	[XMIT_SZ_32BIT]		= 2,
-	[XMIT_SZ_128BIT]	= 4,
-	[XMIT_SZ_256BIT]	= 5,
-};
-
-#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma.h b/arch/sh/include/cpu-sh4/cpu/dma.h
index 235b7cd..bcb3024 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma.h
@@ -1,31 +1,29 @@
 #ifndef __ASM_CPU_SH4_DMA_H
 #define __ASM_CPU_SH4_DMA_H
 
-#define DMAOR_INIT	( 0x8000 | DMAOR_DME )
-
 /* SH7751/7760/7780 DMA IRQ sources */
-#define DMTE0_IRQ	34
-#define DMTE1_IRQ	35
-#define DMTE2_IRQ	36
-#define DMTE3_IRQ	37
-#define DMTE4_IRQ	44
-#define DMTE5_IRQ	45
-#define DMTE6_IRQ	46
-#define DMTE7_IRQ	47
-#define DMAE_IRQ	38
 
 #ifdef CONFIG_CPU_SH4A
-#define SH_DMAC_BASE	0xfc808020
 
+#define DMAOR_INIT	(DMAOR_DME)
 #define CHCR_TS_MASK	0x18
 #define CHCR_TS_SHIFT	3
 
-#include <cpu/dma-sh7780.h>
-#else
-#define SH_DMAC_BASE	0xffa00000
+#include <cpu/dma-sh4a.h>
+#else /* CONFIG_CPU_SH4A */
+/*
+ * SH7750/SH7751/SH7760
+ */
+#define DMTE0_IRQ	34
+#define DMTE4_IRQ	44
+#define DMTE6_IRQ	46
+#define DMAE0_IRQ	38
 
+#define DMAOR_INIT	(0x8000|DMAOR_DME)
+#define SH_DMAC_BASE0	0xffa00000
+#define SH_DMAC_BASE1	0xffa00070
 /* Definitions for the SuperH DMAC */
-#define TM_BURST	0x0000080
+#define TM_BURST	0x00000080
 #define TS_8		0x00000010
 #define TS_16		0x00000020
 #define TS_32		0x00000030
diff --git a/arch/sh/include/cpu-sh4/cpu/freq.h b/arch/sh/include/cpu-sh4/cpu/freq.h
index c23af81..749d1c4 100644
--- a/arch/sh/include/cpu-sh4/cpu/freq.h
+++ b/arch/sh/include/cpu-sh4/cpu/freq.h
@@ -29,6 +29,10 @@
 #define FRQCR0			0xffc80000
 #define FRQCR1			0xffc80004
 #define FRQMR1			0xffc80014
+#elif defined(CONFIG_CPU_SUBTYPE_SH7786)
+#define FRQCR0			0xffc40000
+#define FRQCR1			0xffc40004
+#define FRQMR1			0xffc40014
 #elif defined(CONFIG_CPU_SUBTYPE_SHX3)
 #define FRQCR			0xffc00014
 #else
diff --git a/arch/sh/include/cpu-sh4/cpu/mmu_context.h b/arch/sh/include/cpu-sh4/cpu/mmu_context.h
index 9ea8eb2..3ce7ef6 100644
--- a/arch/sh/include/cpu-sh4/cpu/mmu_context.h
+++ b/arch/sh/include/cpu-sh4/cpu/mmu_context.h
@@ -14,28 +14,35 @@
 #define MMU_PTEL	0xFF000004	/* Page table entry register LOW */
 #define MMU_TTB		0xFF000008	/* Translation table base register */
 #define MMU_TEA		0xFF00000C	/* TLB Exception Address */
-#define MMU_PTEA	0xFF000034	/* Page table entry assistance register */
+#define MMU_PTEA	0xFF000034	/* PTE assistance register */
+#define MMU_PTEAEX	0xFF00007C	/* PTE ASID extension register */
 
 #define MMUCR		0xFF000010	/* MMU Control Register */
 
-#define MMU_ITLB_ADDRESS_ARRAY	0xF2000000
 #define MMU_UTLB_ADDRESS_ARRAY	0xF6000000
+#define MMU_UTLB_ADDRESS_ARRAY2	0xF6800000
 #define MMU_PAGE_ASSOC_BIT	0x80
 
 #define MMUCR_TI		(1<<2)
 
-#ifdef CONFIG_X2TLB
-#define MMUCR_ME		(1 << 7)
-#else
-#define MMUCR_ME		(0)
-#endif
-
 #if defined(CONFIG_32BIT) && defined(CONFIG_CPU_SUBTYPE_ST40)
 #define MMUCR_SE		(1 << 4)
 #else
 #define MMUCR_SE		(0)
 #endif
 
+#ifdef CONFIG_CPU_HAS_PTEAEX
+#define MMUCR_AEX		(1 << 6)
+#else
+#define MMUCR_AEX		(0)
+#endif
+
+#ifdef CONFIG_X2TLB
+#define MMUCR_ME		(1 << 7)
+#else
+#define MMUCR_ME		(0)
+#endif
+
 #ifdef CONFIG_SH_STORE_QUEUES
 #define MMUCR_SQMD		(1 << 9)
 #else
@@ -43,17 +50,7 @@
 #endif
 
 #define MMU_NTLB_ENTRIES	64
-#define MMU_CONTROL_INIT	(0x05|MMUCR_SQMD|MMUCR_ME|MMUCR_SE)
-
-#define MMU_ITLB_DATA_ARRAY	0xF3000000
-#define MMU_UTLB_DATA_ARRAY	0xF7000000
-
-#define MMU_UTLB_ENTRIES	   64
-#define MMU_U_ENTRY_SHIFT	    8
-#define MMU_UTLB_VALID		0x100
-#define MMU_ITLB_ENTRIES	    4
-#define MMU_I_ENTRY_SHIFT	    8
-#define MMU_ITLB_VALID		0x100
+#define MMU_CONTROL_INIT	(0x05|MMUCR_SQMD|MMUCR_ME|MMUCR_SE|MMUCR_AEX)
 
 #define TRA	0xff000020
 #define EXPEVT	0xff000024
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7786.h b/arch/sh/include/cpu-sh4/cpu/sh7786.h
new file mode 100644
index 0000000..48688ad
--- /dev/null
+++ b/arch/sh/include/cpu-sh4/cpu/sh7786.h
@@ -0,0 +1,192 @@
+/*
+ * SH7786 Pinmux
+ *
+ * Copyright (C) 2008, 2009  Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ *  Based on sh7785.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.
+ */
+
+#ifndef __CPU_SH7786_H__
+#define __CPU_SH7786_H__
+
+enum {
+	/* PA */
+	GPIO_PA7, GPIO_PA6, GPIO_PA5, GPIO_PA4,
+	GPIO_PA3, GPIO_PA2, GPIO_PA1, GPIO_PA0,
+
+	/* PB */
+	GPIO_PB7, GPIO_PB6, GPIO_PB5, GPIO_PB4,
+	GPIO_PB3, GPIO_PB2, GPIO_PB1, GPIO_PB0,
+
+	/* PC */
+	GPIO_PC7, GPIO_PC6, GPIO_PC5, GPIO_PC4,
+	GPIO_PC3, GPIO_PC2, GPIO_PC1, GPIO_PC0,
+
+	/* PD */
+	GPIO_PD7, GPIO_PD6, GPIO_PD5, GPIO_PD4,
+	GPIO_PD3, GPIO_PD2, GPIO_PD1, GPIO_PD0,
+
+	/* PE */
+	GPIO_PE5, GPIO_PE4, GPIO_PE3, GPIO_PE2,
+	GPIO_PE1, GPIO_PE0,
+
+	/* PF */
+	GPIO_PF7, GPIO_PF6, GPIO_PF5, GPIO_PF4,
+	GPIO_PF3, GPIO_PF2, GPIO_PF1, GPIO_PF0,
+
+	/* PG */
+	GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4,
+	GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0,
+
+	/* PH */
+	GPIO_PH7, GPIO_PH6, GPIO_PH5, GPIO_PH4,
+	GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0,
+
+	/* PJ */
+	GPIO_PJ7, GPIO_PJ6, GPIO_PJ5, GPIO_PJ4,
+	GPIO_PJ3, GPIO_PJ2, GPIO_PJ1, GPIO_PJ0,
+
+	GPIO_FN_CDE,
+	GPIO_FN_ETH_MAGIC,
+	GPIO_FN_DISP,
+	GPIO_FN_ETH_LINK,
+	GPIO_FN_DR5,
+	GPIO_FN_ETH_TX_ER,
+	GPIO_FN_DR4,
+	GPIO_FN_ETH_TX_EN,
+	GPIO_FN_DR3,
+	GPIO_FN_ETH_TXD3,
+	GPIO_FN_DR2,
+	GPIO_FN_ETH_TXD2,
+	GPIO_FN_DR1,
+	GPIO_FN_ETH_TXD1,
+	GPIO_FN_DR0,
+	GPIO_FN_ETH_TXD0,
+	GPIO_FN_VSYNC,
+	GPIO_FN_HSPI_CLK,
+	GPIO_FN_ODDF,
+	GPIO_FN_HSPI_CS,
+	GPIO_FN_DG5,
+	GPIO_FN_ETH_MDIO,
+	GPIO_FN_DG4,
+	GPIO_FN_ETH_RX_CLK,
+	GPIO_FN_DG3,
+	GPIO_FN_ETH_MDC,
+	GPIO_FN_DG2,
+	GPIO_FN_ETH_COL,
+	GPIO_FN_DG1,
+	GPIO_FN_ETH_TX_CLK,
+	GPIO_FN_DG0,
+	GPIO_FN_ETH_CRS,
+	GPIO_FN_DCLKIN,
+	GPIO_FN_HSPI_RX,
+	GPIO_FN_HSYNC,
+	GPIO_FN_HSPI_TX,
+	GPIO_FN_DB5,
+	GPIO_FN_ETH_RXD3,
+	GPIO_FN_DB4,
+	GPIO_FN_ETH_RXD2,
+	GPIO_FN_DB3,
+	GPIO_FN_ETH_RXD1,
+	GPIO_FN_DB2,
+	GPIO_FN_ETH_RXD0,
+	GPIO_FN_DB1,
+	GPIO_FN_ETH_RX_DV,
+	GPIO_FN_DB0,
+	GPIO_FN_ETH_RX_ER,
+	GPIO_FN_DCLKOUT,
+	GPIO_FN_SCIF1_SLK,
+	GPIO_FN_SCIF1_RXD,
+	GPIO_FN_SCIF1_TXD,
+	GPIO_FN_DACK1,
+	GPIO_FN_BACK,
+	GPIO_FN_FALE,
+	GPIO_FN_DACK0,
+	GPIO_FN_FCLE,
+	GPIO_FN_DREQ1,
+	GPIO_FN_BREQ,
+	GPIO_FN_USB_OVC1,
+	GPIO_FN_DREQ0,
+	GPIO_FN_USB_OVC0,
+	GPIO_FN_USB_PENC1,
+	GPIO_FN_USB_PENC0,
+	GPIO_FN_HAC1_SDOUT,
+	GPIO_FN_SSI1_SDATA,
+	GPIO_FN_SDIF1CMD,
+	GPIO_FN_HAC1_SDIN,
+	GPIO_FN_SSI1_SCK,
+	GPIO_FN_SDIF1CD,
+	GPIO_FN_HAC1_SYNC,
+	GPIO_FN_SSI1_WS,
+	GPIO_FN_SDIF1WP,
+	GPIO_FN_HAC1_BITCLK,
+	GPIO_FN_SSI1_CLK,
+	GPIO_FN_SDIF1CLK,
+	GPIO_FN_HAC0_SDOUT,
+	GPIO_FN_SSI0_SDATA,
+	GPIO_FN_SDIF1D3,
+	GPIO_FN_HAC0_SDIN,
+	GPIO_FN_SSI0_SCK,
+	GPIO_FN_SDIF1D2,
+	GPIO_FN_HAC0_SYNC,
+	GPIO_FN_SSI0_WS,
+	GPIO_FN_SDIF1D1,
+	GPIO_FN_HAC0_BITCLK,
+	GPIO_FN_SSI0_CLK,
+	GPIO_FN_SDIF1D0,
+	GPIO_FN_SCIF3_SCK,
+	GPIO_FN_SSI2_SDATA,
+	GPIO_FN_SCIF3_RXD,
+	GPIO_FN_TCLK,
+	GPIO_FN_SSI2_SCK,
+	GPIO_FN_SCIF3_TXD,
+	GPIO_FN_HAC_RES,
+	GPIO_FN_SSI2_WS,
+	GPIO_FN_DACK3,
+	GPIO_FN_SDIF0CMD,
+	GPIO_FN_DACK2,
+	GPIO_FN_SDIF0CD,
+	GPIO_FN_DREQ3,
+	GPIO_FN_SDIF0WP,
+	GPIO_FN_SCIF0_CTS,
+	GPIO_FN_DREQ2,
+	GPIO_FN_SDIF0CLK,
+	GPIO_FN_SCIF0_RTS,
+	GPIO_FN_IRL7,
+	GPIO_FN_SDIF0D3,
+	GPIO_FN_SCIF0_SCK,
+	GPIO_FN_IRL6,
+	GPIO_FN_SDIF0D2,
+	GPIO_FN_SCIF0_RXD,
+	GPIO_FN_IRL5,
+	GPIO_FN_SDIF0D1,
+	GPIO_FN_SCIF0_TXD,
+	GPIO_FN_IRL4,
+	GPIO_FN_SDIF0D0,
+	GPIO_FN_SCIF5_SCK,
+	GPIO_FN_FRB,
+	GPIO_FN_SCIF5_RXD,
+	GPIO_FN_IOIS16,
+	GPIO_FN_SCIF5_TXD,
+	GPIO_FN_CE2B,
+	GPIO_FN_DRAK3,
+	GPIO_FN_CE2A,
+	GPIO_FN_SCIF4_SCK,
+	GPIO_FN_DRAK2,
+	GPIO_FN_SSI3_WS,
+	GPIO_FN_SCIF4_RXD,
+	GPIO_FN_DRAK1,
+	GPIO_FN_SSI3_SDATA,
+	GPIO_FN_FSTATUS,
+	GPIO_FN_SCIF4_TXD,
+	GPIO_FN_DRAK0,
+	GPIO_FN_SSI3_SCK,
+	GPIO_FN_FSE,
+};
+
+#endif /* __CPU_SH7786_H__ */
diff --git a/arch/sh/include/mach-common/mach/urquell.h b/arch/sh/include/mach-common/mach/urquell.h
new file mode 100644
index 0000000..14b3e1d
--- /dev/null
+++ b/arch/sh/include/mach-common/mach/urquell.h
@@ -0,0 +1,68 @@
+#ifndef __MACH_URQUELL_H
+#define __MACH_URQUELL_H
+
+/*
+ * ------ 0x00000000 ------------------------------------
+ *  CS0 | (SW1,SW47)    EEPROM, SRAM, NOR FLASH
+ * -----+ 0x04000000 ------------------------------------
+ *  CS1 | (SW47)        SRAM, SRAM-LAN-PCMCIA, NOR FLASH
+ * -----+ 0x08000000 ------------------------------------
+ *  CS2 |               DDR3
+ *  CS3 |
+ * -----+ 0x10000000 ------------------------------------
+ *  CS4 |               PCIe
+ * -----+ 0x14000000 ------------------------------------
+ *  CS5 | (SW47)        LRAM/URAM, SRAM-LAN-PCMCIA
+ * -----+ 0x18000000 ------------------------------------
+ *  CS6 |               ATA, NAND FLASH
+ * -----+ 0x1c000000 ------------------------------------
+ *  CS7 |               SH7786 register
+ * -----+------------------------------------------------
+ */
+
+#define NOR_FLASH_ADDR	0x00000000
+#define NOR_FLASH_SIZE	0x04000000
+
+#define CS1_BASE	0x05000000
+#define CS5_BASE	0x15000000
+#define FPGA_BASE	CS1_BASE
+
+#define BOARDREG(ofs)	(FPGA_BASE + ofs##_OFS)
+#define UBOARDREG(ofs)	(0xa0000000 + FPGA_BASE + ofs##_OFS)
+
+#define SRSTR_OFS	0x0000 /* System reset register */
+#define BDMR_OFS	0x0010 /* Board operating mode resister */
+#define IRL0SR_OFS	0x0020 /* IRL0 Status register */
+#define IRL0MSKR_OFS	0x0030 /* IRL0 Mask register */
+#define IRL1SR_OFS	0x0040 /* IRL1 Status register */
+#define IRL1MSKR_OFS	0x0050 /* IRL1 Mask register */
+#define IRL2SR_OFS	0x0060 /* IRL2 Status register */
+#define IRL2MSKR_OFS	0x0070 /* IRL2 Mask register */
+#define IRL3SR_OFS	0x0080 /* IRL3 Status register */
+#define IRL3MSKR_OFS	0x0090 /* IRL3 Mask register */
+#define SOFTINTR_OFS	0x0120 /* Softwear Interrupt register */
+#define SLEDR_OFS	0x0130 /* LED control resister */
+#define MAPSCIFSWR_OFS	0x0140 /* Map/SCIF Switch register */
+#define FPVERR_OFS	0x0150 /* FPGA Version register */
+#define FPDATER_OFS	0x0160 /* FPGA Date register */
+#define FPYEARR_OFS	0x0170 /* FPGA Year register */
+#define TCLKCR_OFS	0x0180 /* TCLK Control register */
+#define DIPSWMR_OFS	0x1000 /* DIPSW monitor register */
+#define FPODR_OFS	0x1010 /* Output port data register */
+#define ATACNR_OFS	0x1020 /* ATA-CN Control/status register */
+#define FPINDR_OFS	0x1030 /* Input port data register */
+#define MDSWMR_OFS	0x1040 /* MODE SW monitor register */
+#define DDR3BUPCR_OFS	0x1050 /* DDR3 Backup control register */
+#define SSICODECCR_OFS	0x1060 /* SSI-CODEC control register */
+#define PCIESLOTSR_OFS	0x1070 /* PCIexpress Slot status register */
+#define ETHERPORTSR_OFS	0x1080 /* EtherPhy Port status register */
+#define LATCHCR_OFS	0x3000 /* Latch control register */
+#define LATCUAR_OFS	0x3010 /* Latch upper address register */
+#define LATCLAR_OFS	0x3012 /* Latch lower address register */
+#define LATCLUDR_OFS	0x3024 /* Latch D31-16 register */
+#define LATCLLDR_OFS	0x3026 /* Latch D15-0 register */
+
+#define CHARLED_OFS	0x2000 /* Character LED */
+
+#endif  /* __MACH_URQUELL_H */
+
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
index 2e1b86e..82a3a15 100644
--- a/arch/sh/kernel/Makefile_32
+++ b/arch/sh/kernel/Makefile_32
@@ -30,5 +30,6 @@
 obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_DUMP_CODE)		+= disassemble.o
+obj-$(CONFIG_HIBERNATION)	+= swsusp.o
 
 EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
index 57cf0e0..99aceb28 100644
--- a/arch/sh/kernel/asm-offsets.c
+++ b/arch/sh/kernel/asm-offsets.c
@@ -12,8 +12,10 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/kbuild.h>
+#include <linux/suspend.h>
 
 #include <asm/thread_info.h>
+#include <asm/suspend.h>
 
 int main(void)
 {
@@ -25,5 +27,11 @@
 	DEFINE(TI_PRE_COUNT,	offsetof(struct thread_info, preempt_count));
 	DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
 
+#ifdef CONFIG_HIBERNATION
+	DEFINE(PBE_ADDRESS, offsetof(struct pbe, address));
+	DEFINE(PBE_ORIG_ADDRESS, offsetof(struct pbe, orig_address));
+	DEFINE(PBE_NEXT, offsetof(struct pbe, next));
+	DEFINE(SWSUSP_ARCH_REGS_SIZE, sizeof(struct swsusp_arch_regs));
+#endif
 	return 0;
 }
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index f471d24..2600641 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -11,6 +11,7 @@
 # Special cases for family ancestry.
 
 obj-$(CONFIG_CPU_SH4A)		+= sh4a/
+obj-$(CONFIG_ARCH_SHMOBILE)	+= shmobile/
 
 # Common interfaces.
 
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 7b17137..1dc8964 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -20,6 +20,8 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/kref.h>
+#include <linux/kobject.h>
+#include <linux/sysdev.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
@@ -239,6 +241,35 @@
 }
 EXPORT_SYMBOL_GPL(clk_recalc_rate);
 
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = -EINVAL;
+	struct clk *old;
+
+	if (!parent || !clk)
+		return ret;
+
+	old = clk->parent;
+	if (likely(clk->ops && clk->ops->set_parent)) {
+		unsigned long flags;
+		spin_lock_irqsave(&clock_lock, flags);
+		ret = clk->ops->set_parent(clk, parent);
+		spin_unlock_irqrestore(&clock_lock, flags);
+		clk->parent = (ret ? old : parent);
+	}
+
+	if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
+		propagate_rate(clk);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	if (likely(clk->ops && clk->ops->round_rate)) {
@@ -329,6 +360,70 @@
 	return p - buf;
 }
 
+#ifdef CONFIG_PM
+static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
+{
+	static pm_message_t prev_state;
+	struct clk *clkp;
+
+	switch (state.event) {
+	case PM_EVENT_ON:
+		/* Resumeing from hibernation */
+		if (prev_state.event == PM_EVENT_FREEZE) {
+			list_for_each_entry(clkp, &clock_list, node)
+				if (likely(clkp->ops)) {
+					unsigned long rate = clkp->rate;
+
+					if (likely(clkp->ops->set_parent))
+						clkp->ops->set_parent(clkp,
+							clkp->parent);
+					if (likely(clkp->ops->set_rate))
+						clkp->ops->set_rate(clkp,
+							rate, NO_CHANGE);
+					else if (likely(clkp->ops->recalc))
+						clkp->ops->recalc(clkp);
+					}
+		}
+		break;
+	case PM_EVENT_FREEZE:
+		break;
+	case PM_EVENT_SUSPEND:
+		break;
+	}
+
+	prev_state = state;
+	return 0;
+}
+
+static int clks_sysdev_resume(struct sys_device *dev)
+{
+	return clks_sysdev_suspend(dev, PMSG_ON);
+}
+
+static struct sysdev_class clks_sysdev_class = {
+	.name = "clks",
+};
+
+static struct sysdev_driver clks_sysdev_driver = {
+	.suspend = clks_sysdev_suspend,
+	.resume = clks_sysdev_resume,
+};
+
+static struct sys_device clks_sysdev_dev = {
+	.cls = &clks_sysdev_class,
+};
+
+static int __init clk_sysdev_init(void)
+{
+	sysdev_class_register(&clks_sysdev_class);
+	sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver);
+	sysdev_register(&clks_sysdev_dev);
+
+	return 0;
+}
+subsys_initcall(clk_sysdev_init);
+#endif
+
 int __init clk_init(void)
 {
 	int i, ret = 0;
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 56e5878..0e32d8e 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -2,6 +2,7 @@
  * SH7619 Setup
  *
  *  Copyright (C) 2006  Yoshinori Sato
+ *  Copyright (C) 2009  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
@@ -18,15 +19,10 @@
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
 	WDT, EDMAC, CMT0, CMT1,
-	SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
-	SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
-	SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI,
+	SCIF0, SCIF1, SCIF2,
 	HIF_HIFI, HIF_HIFBI,
 	DMAC0, DMAC1, DMAC2, DMAC3,
 	SIOF,
-
-	/* interrupt groups */
-	SCIF0, SCIF1, SCIF2,
 };
 
 static struct intc_vect vectors[] __initdata = {
@@ -36,24 +32,18 @@
 	INTC_IRQ(IRQ6, 82), INTC_IRQ(IRQ7, 83),
 	INTC_IRQ(WDT, 84), INTC_IRQ(EDMAC, 85),
 	INTC_IRQ(CMT0, 86), INTC_IRQ(CMT1, 87),
-	INTC_IRQ(SCIF0_ERI, 88), INTC_IRQ(SCIF0_RXI, 89),
-	INTC_IRQ(SCIF0_BRI, 90), INTC_IRQ(SCIF0_TXI, 91),
-	INTC_IRQ(SCIF1_ERI, 92), INTC_IRQ(SCIF1_RXI, 93),
-	INTC_IRQ(SCIF1_BRI, 94), INTC_IRQ(SCIF1_TXI, 95),
-	INTC_IRQ(SCIF2_ERI, 96), INTC_IRQ(SCIF2_RXI, 97),
-	INTC_IRQ(SCIF2_BRI, 98), INTC_IRQ(SCIF2_TXI, 99),
+	INTC_IRQ(SCIF0, 88), INTC_IRQ(SCIF0, 89),
+	INTC_IRQ(SCIF0, 90), INTC_IRQ(SCIF0, 91),
+	INTC_IRQ(SCIF1, 92), INTC_IRQ(SCIF1, 93),
+	INTC_IRQ(SCIF1, 94), INTC_IRQ(SCIF1, 95),
+	INTC_IRQ(SCIF2, 96), INTC_IRQ(SCIF2, 97),
+	INTC_IRQ(SCIF2, 98), INTC_IRQ(SCIF2, 99),
 	INTC_IRQ(HIF_HIFI, 100), INTC_IRQ(HIF_HIFBI, 101),
 	INTC_IRQ(DMAC0, 104), INTC_IRQ(DMAC1, 105),
 	INTC_IRQ(DMAC2, 106), INTC_IRQ(DMAC3, 107),
 	INTC_IRQ(SIOF, 108),
 };
 
-static struct intc_group groups[] __initdata = {
-	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
-	INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
-	INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
-};
-
 static struct intc_prio_reg prio_registers[] __initdata = {
 	{ 0xf8140006, 0, 16, 4, /* IPRA */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
 	{ 0xf8140008, 0, 16, 4, /* IPRB */ { IRQ4, IRQ5, IRQ6, IRQ7 } },
@@ -64,7 +54,7 @@
 	{ 0xf8080008, 0, 16, 4, /* IPRG */ { SIOF } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7619", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7619", vectors, NULL,
 			 NULL, prio_registers, NULL);
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -72,17 +62,17 @@
 		.mapbase	= 0xf8400000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 88, 89, 91, 90},
+		.irqs		= { 88, 88, 88, 88 },
 	}, {
 		.mapbase	= 0xf8410000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 92, 93, 95, 94},
+		.irqs		= { 92, 92, 92, 92 },
 	}, {
 		.mapbase	= 0xf8420000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 96, 97, 99, 98},
+		.irqs		= { 96, 96, 96, 96 },
 	}, {
 		.flags = 0,
 	}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
index e611d79..8442937 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
@@ -1,7 +1,7 @@
 /*
  * Renesas MX-G (R8A03022BG) Setup
  *
- *  Copyright (C) 2008  Paul Mundt
+ *  Copyright (C) 2008, 2009  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
@@ -20,23 +20,15 @@
 	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,
+	SCIF0, SCIF1,
 
-	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,
+	MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5
+	MTU2_TGI3B, MTU2_TGI3C,
 
 	/* interrupt groups */
-	PINT, SCIF0, SCIF1,
-	MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5
+	PINT,
 };
 
 static struct intc_vect vectors[] __initdata = {
@@ -59,47 +51,36 @@
 	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(SCIF0, 220), INTC_IRQ(SCIF0, 221),
+	INTC_IRQ(SCIF0, 222), INTC_IRQ(SCIF0, 223),
+	INTC_IRQ(SCIF1, 224), INTC_IRQ(SCIF1, 225),
+	INTC_IRQ(SCIF1, 226), INTC_IRQ(SCIF1, 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_GROUP1, 228), INTC_IRQ(MTU2_GROUP1, 229),
+	INTC_IRQ(MTU2_GROUP1, 230), INTC_IRQ(MTU2_GROUP1, 231),
+	INTC_IRQ(MTU2_GROUP1, 232), INTC_IRQ(MTU2_GROUP1, 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_GROUP2, 234), INTC_IRQ(MTU2_GROUP2, 235),
+	INTC_IRQ(MTU2_GROUP2, 236), INTC_IRQ(MTU2_GROUP2, 237),
+	INTC_IRQ(MTU2_GROUP2, 238), INTC_IRQ(MTU2_GROUP2, 239),
 
-	INTC_IRQ(MTU2_TGI2B, 240), INTC_IRQ(MTU2_TCI2V, 241),
-	INTC_IRQ(MTU2_TCI2U, 242), INTC_IRQ(MTU2_TGI3A, 243),
+	INTC_IRQ(MTU2_GROUP3, 240), INTC_IRQ(MTU2_GROUP3, 241),
+	INTC_IRQ(MTU2_GROUP3, 242), INTC_IRQ(MTU2_GROUP3, 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_GROUP4, 246), INTC_IRQ(MTU2_GROUP4, 247),
+	INTC_IRQ(MTU2_GROUP4, 248), INTC_IRQ(MTU2_GROUP4, 249),
+	INTC_IRQ(MTU2_GROUP4, 250), INTC_IRQ(MTU2_GROUP4, 251),
 
-	INTC_IRQ(MTU2_TCI4V, 252), INTC_IRQ(MTU2_TGI5U, 253),
-	INTC_IRQ(MTU2_TGI5V, 254), INTC_IRQ(MTU2_TGI5W, 255),
+	INTC_IRQ(MTU2_GROUP5, 252), INTC_IRQ(MTU2_GROUP5, 253),
+	INTC_IRQ(MTU2_GROUP5, 254), INTC_IRQ(MTU2_GROUP5, 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 = {
@@ -137,7 +118,7 @@
 		.mapbase	= 0xff804000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 223, 220, 221, 222 },
+		.irqs		= { 220, 220, 220, 220 },
 	}, {
 		.flags = 0,
 	}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
index 0631e42..00f42f9 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
@@ -2,6 +2,7 @@
  *  SH7201 setup
  *
  *  Copyright (C) 2008  Peter Griffin pgriffin@mpc-data.co.uk
+ *  Copyright (C) 2009  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
@@ -18,57 +19,32 @@
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
 	PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
+
 	ADC_ADI,
-	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,
-	RTC_ARM, RTC_PRD, RTC_CUP,
-	WDT,
-	IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI, IIC30_TEI,
-	IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI, IIC31_TEI,
-	IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI, IIC32_TEI,
+
+	MTU20_ABCD, MTU20_VEF, MTU21_AB, MTU21_VU, MTU22_AB, MTU22_VU,
+	MTU23_ABCD, MTU24_ABCD, MTU25_UVW, MTU2_TCI3V, MTU2_TCI4V,
+
+	RTC, WDT,
+
+	IIC30, IIC31, IIC32,
 
 	DMAC0_DMINT0, DMAC1_DMINT1,
 	DMAC2_DMINT2, DMAC3_DMINT3,
 
-	SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
-	SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
-	SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
-	SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI,
-	SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI,
-	SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI,
-	SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI,
-	SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI,
+	SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7,
 
 	DMAC0_DMINTA, DMAC4_DMINT4, DMAC5_DMINT5, DMAC6_DMINT6,
 	DMAC7_DMINT7,
 
-	RCAN0_ERS, RCAN0_OVR,
-	RCAN0_SLE,
-	RCAN0_RM0, RCAN0_RM1,
-
-	RCAN1_ERS, RCAN1_OVR,
-	RCAN1_SLE,
-	RCAN1_RM0, RCAN1_RM1,
+	RCAN0, RCAN1,
 
 	SSI0_SSII, SSI1_SSII,
 
-	TMR0_CMIA0, TMR0_CMIB0, TMR0_OVI0,
-	TMR1_CMIA1, TMR1_CMIB1, TMR1_OVI1,
+	TMR0, TMR1,
 
 	/* interrupt groups */
-
-	IRQ, PINT, ADC,
-	MTU20_ABCD, MTU20_VEF, MTU21_AB, MTU21_VU, MTU22_AB, MTU22_VU,
-	MTU23_ABCD, MTU24_ABCD, MTU25_UVW,
-	RTC, IIC30, IIC31, IIC32,
-	SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7,
-	RCAN0, RCAN1, TMR0, TMR1
-
+	PINT,
 };
 
 static struct intc_vect vectors[] __initdata = {
@@ -76,6 +52,7 @@
 	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(PINT0, 80), INTC_IRQ(PINT1, 81),
 	INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83),
 	INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
@@ -83,123 +60,92 @@
 
 	INTC_IRQ(ADC_ADI, 92),
 
-	INTC_IRQ(MTU2_TGI0A, 108), INTC_IRQ(MTU2_TGI0B, 109),
-	INTC_IRQ(MTU2_TGI0C, 110), INTC_IRQ(MTU2_TGI0D, 111),
-	INTC_IRQ(MTU2_TCI0V, 112),
-	INTC_IRQ(MTU2_TGI0E, 113), INTC_IRQ(MTU2_TGI0F, 114),
+	INTC_IRQ(MTU20_ABCD, 108), INTC_IRQ(MTU20_ABCD, 109),
+	INTC_IRQ(MTU20_ABCD, 110), INTC_IRQ(MTU20_ABCD, 111),
 
-	INTC_IRQ(MTU2_TGI1A, 116), INTC_IRQ(MTU2_TGI1B, 117),
-	INTC_IRQ(MTU2_TCI1V, 120), INTC_IRQ(MTU2_TCI1U, 121),
+	INTC_IRQ(MTU20_VEF, 112), INTC_IRQ(MTU20_VEF, 113),
+	INTC_IRQ(MTU20_VEF, 114),
 
-	INTC_IRQ(MTU2_TGI2A, 124), INTC_IRQ(MTU2_TGI2B, 125),
-	INTC_IRQ(MTU2_TCI2V, 128), INTC_IRQ(MTU2_TCI2U, 129),
+	INTC_IRQ(MTU21_AB, 116), INTC_IRQ(MTU21_AB, 117),
+	INTC_IRQ(MTU21_VU, 120), INTC_IRQ(MTU21_VU, 121),
 
-	INTC_IRQ(MTU2_TGI3A, 132), INTC_IRQ(MTU2_TGI3B, 133),
-	INTC_IRQ(MTU2_TGI3C, 134), INTC_IRQ(MTU2_TGI3D, 135),
+	INTC_IRQ(MTU22_AB, 124), INTC_IRQ(MTU22_AB, 125),
+	INTC_IRQ(MTU22_VU, 128), INTC_IRQ(MTU22_VU, 129),
+
+	INTC_IRQ(MTU23_ABCD, 132), INTC_IRQ(MTU23_ABCD, 133),
+	INTC_IRQ(MTU23_ABCD, 134), INTC_IRQ(MTU23_ABCD, 135),
+
 	INTC_IRQ(MTU2_TCI3V, 136),
 
-	INTC_IRQ(MTU2_TGI4A, 140), INTC_IRQ(MTU2_TGI4B, 141),
-	INTC_IRQ(MTU2_TGI4C, 142), INTC_IRQ(MTU2_TGI4D, 143),
+	INTC_IRQ(MTU24_ABCD, 140), INTC_IRQ(MTU24_ABCD, 141),
+	INTC_IRQ(MTU24_ABCD, 142), INTC_IRQ(MTU24_ABCD, 143),
+
 	INTC_IRQ(MTU2_TCI4V, 144),
 
-	INTC_IRQ(MTU2_TGI5U, 148), INTC_IRQ(MTU2_TGI5V, 149),
-	INTC_IRQ(MTU2_TGI5W, 150),
+	INTC_IRQ(MTU25_UVW, 148), INTC_IRQ(MTU25_UVW, 149),
+	INTC_IRQ(MTU25_UVW, 150),
 
-	INTC_IRQ(RTC_ARM, 152), INTC_IRQ(RTC_PRD, 153),
-	INTC_IRQ(RTC_CUP, 154), INTC_IRQ(WDT, 156),
+	INTC_IRQ(RTC, 152), INTC_IRQ(RTC, 153),
+	INTC_IRQ(RTC, 154),
 
-	INTC_IRQ(IIC30_STPI, 157), INTC_IRQ(IIC30_NAKI, 158),
-	INTC_IRQ(IIC30_RXI, 159), INTC_IRQ(IIC30_TXI, 160),
-	INTC_IRQ(IIC30_TEI, 161),
+	INTC_IRQ(WDT, 156),
 
-	INTC_IRQ(IIC31_STPI, 164), INTC_IRQ(IIC31_NAKI, 165),
-	INTC_IRQ(IIC31_RXI, 166), INTC_IRQ(IIC31_TXI, 167),
-	INTC_IRQ(IIC31_TEI, 168),
+	INTC_IRQ(IIC30, 157), INTC_IRQ(IIC30, 158),
+	INTC_IRQ(IIC30, 159), INTC_IRQ(IIC30, 160),
+	INTC_IRQ(IIC30, 161),
 
-	INTC_IRQ(IIC32_STPI, 170), INTC_IRQ(IIC32_NAKI, 171),
-	INTC_IRQ(IIC32_RXI, 172), INTC_IRQ(IIC32_TXI, 173),
-	INTC_IRQ(IIC32_TEI, 174),
+	INTC_IRQ(IIC31, 164), INTC_IRQ(IIC31, 165),
+	INTC_IRQ(IIC31, 166), INTC_IRQ(IIC31, 167),
+	INTC_IRQ(IIC31, 168),
+
+	INTC_IRQ(IIC32, 170), INTC_IRQ(IIC32, 171),
+	INTC_IRQ(IIC32, 172), INTC_IRQ(IIC32, 173),
+	INTC_IRQ(IIC32, 174),
 
 	INTC_IRQ(DMAC0_DMINT0, 176), INTC_IRQ(DMAC1_DMINT1, 177),
 	INTC_IRQ(DMAC2_DMINT2, 178), INTC_IRQ(DMAC3_DMINT3, 179),
 
-	INTC_IRQ(SCIF0_BRI, 180), INTC_IRQ(SCIF0_ERI, 181),
-	INTC_IRQ(SCIF0_RXI, 182), INTC_IRQ(SCIF0_TXI, 183),
-	INTC_IRQ(SCIF1_BRI, 184), INTC_IRQ(SCIF1_ERI, 185),
-	INTC_IRQ(SCIF1_RXI, 186), INTC_IRQ(SCIF1_TXI, 187),
-	INTC_IRQ(SCIF2_BRI, 188), INTC_IRQ(SCIF2_ERI, 189),
-	INTC_IRQ(SCIF2_RXI, 190), INTC_IRQ(SCIF2_TXI, 191),
-	INTC_IRQ(SCIF3_BRI, 192), INTC_IRQ(SCIF3_ERI, 193),
-	INTC_IRQ(SCIF3_RXI, 194), INTC_IRQ(SCIF3_TXI, 195),
-	INTC_IRQ(SCIF4_BRI, 196), INTC_IRQ(SCIF4_ERI, 197),
-	INTC_IRQ(SCIF4_RXI, 198), INTC_IRQ(SCIF4_TXI, 199),
-	INTC_IRQ(SCIF5_BRI, 200), INTC_IRQ(SCIF5_ERI, 201),
-	INTC_IRQ(SCIF5_RXI, 202), INTC_IRQ(SCIF5_TXI, 203),
-	INTC_IRQ(SCIF6_BRI, 204), INTC_IRQ(SCIF6_ERI, 205),
-	INTC_IRQ(SCIF6_RXI, 206), INTC_IRQ(SCIF6_TXI, 207),
-	INTC_IRQ(SCIF7_BRI, 208), INTC_IRQ(SCIF7_ERI, 209),
-	INTC_IRQ(SCIF7_RXI, 210), INTC_IRQ(SCIF7_TXI, 211),
+	INTC_IRQ(SCIF0, 180), INTC_IRQ(SCIF0, 181),
+	INTC_IRQ(SCIF0, 182), INTC_IRQ(SCIF0, 183),
+	INTC_IRQ(SCIF1, 184), INTC_IRQ(SCIF1, 185),
+	INTC_IRQ(SCIF1, 186), INTC_IRQ(SCIF1, 187),
+	INTC_IRQ(SCIF2, 188), INTC_IRQ(SCIF2, 189),
+	INTC_IRQ(SCIF2, 190), INTC_IRQ(SCIF2, 191),
+	INTC_IRQ(SCIF3, 192), INTC_IRQ(SCIF3, 193),
+	INTC_IRQ(SCIF3, 194), INTC_IRQ(SCIF3, 195),
+	INTC_IRQ(SCIF4, 196), INTC_IRQ(SCIF4, 197),
+	INTC_IRQ(SCIF4, 198), INTC_IRQ(SCIF4, 199),
+	INTC_IRQ(SCIF5, 200), INTC_IRQ(SCIF5, 201),
+	INTC_IRQ(SCIF5, 202), INTC_IRQ(SCIF5, 203),
+	INTC_IRQ(SCIF6, 204), INTC_IRQ(SCIF6, 205),
+	INTC_IRQ(SCIF6, 206), INTC_IRQ(SCIF6, 207),
+	INTC_IRQ(SCIF7, 208), INTC_IRQ(SCIF7, 209),
+	INTC_IRQ(SCIF7, 210), INTC_IRQ(SCIF7, 211),
 
 	INTC_IRQ(DMAC0_DMINTA, 212), INTC_IRQ(DMAC4_DMINT4, 216),
 	INTC_IRQ(DMAC5_DMINT5, 217), INTC_IRQ(DMAC6_DMINT6, 218),
 	INTC_IRQ(DMAC7_DMINT7, 219),
 
-	INTC_IRQ(RCAN0_ERS, 228), INTC_IRQ(RCAN0_OVR, 229),
-	INTC_IRQ(RCAN0_SLE, 230),
-	INTC_IRQ(RCAN0_RM0, 231), INTC_IRQ(RCAN0_RM1, 232),
+	INTC_IRQ(RCAN0, 228), INTC_IRQ(RCAN0, 229),
+	INTC_IRQ(RCAN0, 230),
+	INTC_IRQ(RCAN0, 231), INTC_IRQ(RCAN0, 232),
 
-	INTC_IRQ(RCAN1_ERS, 234), INTC_IRQ(RCAN1_OVR, 235),
-	INTC_IRQ(RCAN1_SLE, 236),
-	INTC_IRQ(RCAN1_RM0, 237), INTC_IRQ(RCAN1_RM1, 238),
+	INTC_IRQ(RCAN1, 234), INTC_IRQ(RCAN1, 235),
+	INTC_IRQ(RCAN1, 236),
+	INTC_IRQ(RCAN1, 237), INTC_IRQ(RCAN1, 238),
 
 	INTC_IRQ(SSI0_SSII, 244), INTC_IRQ(SSI1_SSII, 245),
 
-	INTC_IRQ(TMR0_CMIA0, 246), INTC_IRQ(TMR0_CMIB0, 247),
-	INTC_IRQ(TMR0_OVI0, 248),
+	INTC_IRQ(TMR0, 246), INTC_IRQ(TMR0, 247),
+	INTC_IRQ(TMR0, 248),
 
-	INTC_IRQ(TMR1_CMIA1, 252), INTC_IRQ(TMR1_CMIB1, 253),
-	INTC_IRQ(TMR1_OVI1, 254),
-
+	INTC_IRQ(TMR1, 252), INTC_IRQ(TMR1, 253),
+	INTC_IRQ(TMR1, 254),
 };
 
 static struct intc_group groups[] __initdata = {
 	INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
 		   PINT4, PINT5, PINT6, PINT7),
-	INTC_GROUP(MTU20_ABCD, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D),
-	INTC_GROUP(MTU20_VEF, MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F),
-
-	INTC_GROUP(MTU21_AB, MTU2_TGI1A, MTU2_TGI1B),
-	INTC_GROUP(MTU21_VU, MTU2_TCI1V, MTU2_TCI1U),
-	INTC_GROUP(MTU22_AB, MTU2_TGI2A, MTU2_TGI2B),
-	INTC_GROUP(MTU22_VU, MTU2_TCI2V, MTU2_TCI2U),
-	INTC_GROUP(MTU23_ABCD, MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D),
-	INTC_GROUP(MTU24_ABCD, MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D),
-	INTC_GROUP(MTU25_UVW, MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W),
-	INTC_GROUP(RTC, RTC_ARM, RTC_PRD, RTC_CUP ),
-
-	INTC_GROUP(IIC30, IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI,
-		   IIC30_TEI),
-	INTC_GROUP(IIC31, IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI,
-		   IIC31_TEI),
-	INTC_GROUP(IIC32, IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI,
-		   IIC32_TEI),
-
-	INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
-	INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
-	INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
-	INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI),
-	INTC_GROUP(SCIF4, SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI),
-	INTC_GROUP(SCIF5, SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI),
-	INTC_GROUP(SCIF6, SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI),
-	INTC_GROUP(SCIF7, SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI),
-
-	INTC_GROUP(RCAN0, RCAN0_ERS, RCAN0_OVR, RCAN0_RM0, RCAN0_RM1,
-		   RCAN0_SLE),
-	INTC_GROUP(RCAN1, RCAN1_ERS, RCAN1_OVR, RCAN1_RM0, RCAN1_RM1,
-		   RCAN1_SLE),
-
-	INTC_GROUP(TMR0, TMR0_CMIA0, TMR0_CMIB0, TMR0_OVI0),
-	INTC_GROUP(TMR1, TMR1_CMIA1, TMR1_CMIB1, TMR1_OVI1),
 };
 
 static struct intc_prio_reg prio_registers[] __initdata = {
@@ -212,7 +158,7 @@
 
 	{ 0xfffe9806, 0, 16, 4, /* IPR09 */ { RTC, WDT, IIC30, 0 } },
 	{ 0xfffe9808, 0, 16, 4, /* IPR10 */ { IIC31, IIC32, DMAC0_DMINT0, DMAC1_DMINT1 } },
-	{ 0xfffe980a, 0, 16, 4, /* IPR11 */ { DMAC2_DMINT2, DMAC3_DMINT3, SCIF0 , SCIF1 } },
+	{ 0xfffe980a, 0, 16, 4, /* IPR11 */ { DMAC2_DMINT2, DMAC3_DMINT3, SCIF0, SCIF1 } },
 	{ 0xfffe980c, 0, 16, 4, /* IPR12 */ { SCIF2, SCIF3, SCIF4, SCIF5 } },
 	{ 0xfffe980e, 0, 16, 4, /* IPR13 */ { SCIF6, SCIF7, DMAC0_DMINTA, DMAC4_DMINT4  } },
 	{ 0xfffe9810, 0, 16, 4, /* IPR14 */ { DMAC5_DMINT5, DMAC6_DMINT6, DMAC7_DMINT7, 0 } },
@@ -234,42 +180,42 @@
 		.mapbase	= 0xfffe8000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 181, 182, 183, 180}
+		.irqs		= { 180, 180, 180, 180 }
 	}, {
 		.mapbase	= 0xfffe8800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 185, 186, 187, 184}
+		.irqs		= { 184, 184, 184, 184 }
 	}, {
 		.mapbase	= 0xfffe9000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 189, 186, 187, 188}
+		.irqs		= { 188, 188, 188, 188 }
 	}, {
 		.mapbase	= 0xfffe9800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 193, 194, 195, 192}
+		.irqs		= { 192, 192, 192, 192 }
 	}, {
 		.mapbase	= 0xfffea000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 196, 198, 199, 196}
+		.irqs		= { 196, 196, 196, 196 }
 	}, {
 		.mapbase	= 0xfffea800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 201, 202, 203, 200}
+		.irqs		= { 200, 200, 200, 200 }
 	}, {
 		.mapbase	= 0xfffeb000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 205, 206, 207, 204}
+		.irqs		= { 204, 204, 204, 204 }
 	}, {
 		.mapbase	= 0xfffeb800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 209, 210, 211, 208}
+		.irqs		= { 208, 208, 208, 208 }
 	}, {
 		.flags = 0,
 	}
@@ -290,17 +236,7 @@
 		.flags	= IORESOURCE_IO,
 	},
 	[1] = {
-		/* Period IRQ */
-		.start	= 153,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		/* Carry IRQ */
-		.start	= 154,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		/* Alarm IRQ */
+		/* Shared Period/Carry/Alarm IRQ */
 		.start	= 152,
 		.flags	= IORESOURCE_IRQ,
 	},
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
index e98dc44..820dfb2 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
@@ -1,7 +1,7 @@
 /*
  * SH7203 and SH7263 Setup
  *
- *  Copyright (C) 2007  Paul Mundt
+ *  Copyright (C) 2007 - 2009  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
@@ -18,50 +18,27 @@
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
 	PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
-	DMAC0_DEI, DMAC0_HEI, DMAC1_DEI, DMAC1_HEI,
-	DMAC2_DEI, DMAC2_HEI, DMAC3_DEI, DMAC3_HEI,
-	DMAC4_DEI, DMAC4_HEI, DMAC5_DEI, DMAC5_HEI,
-	DMAC6_DEI, DMAC6_HEI, DMAC7_DEI, DMAC7_HEI,
+	DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
 	USB, LCDC, CMT0, CMT1, BSC, WDT,
-	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,
+
+	MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
+	MTU3_ABCD, MTU4_ABCD, MTU2_TCI3V, MTU2_TCI4V,
+
 	ADC_ADI,
-	IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI, IIC30_TEI,
-	IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI, IIC31_TEI,
-	IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI, IIC32_TEI,
-	IIC33_STPI, IIC33_NAKI, IIC33_RXI, IIC33_TXI, IIC33_TEI,
-	SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
-	SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
-	SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
-	SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI,
-	SSU0_SSERI, SSU0_SSRXI, SSU0_SSTXI,
-	SSU1_SSERI, SSU1_SSRXI, SSU1_SSTXI,
+
+	IIC30, IIC31, IIC32, IIC33,
+	SCIF0, SCIF1, SCIF2, SCIF3,
+
+	SSU0, SSU1,
+
 	SSI0_SSII, SSI1_SSII, SSI2_SSII, SSI3_SSII,
 
 	/* ROM-DEC, SDHI, SRC, and IEB are SH7263 specific */
-	ROMDEC_ISY, ROMDEC_IERR, ROMDEC_IARG, ROMDEC_ISEC, ROMDEC_IBUF,
-	ROMDEC_IREADY,
-
-	FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
-
-	SDHI3, SDHI0, SDHI1,
-
-	RTC_ARM, RTC_PRD, RTC_CUP,
-	RCAN0_ERS, RCAN0_OVR, RCAN0_RM0, RCAN0_RM1, RCAN0_SLE,
-	RCAN1_ERS, RCAN1_OVR, RCAN1_RM0, RCAN1_RM1, RCAN1_SLE,
-
-	SRC_OVF, SRC_ODFI, SRC_IDEI, IEBI,
+	ROMDEC, FLCTL, SDHI, RTC, RCAN0, RCAN1,
+	SRC, IEBI,
 
 	/* interrupt groups */
-	PINT, DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
-	MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
-	MTU3_ABCD, MTU4_ABCD,
-	IIC30, IIC31, IIC32, IIC33, SCIF0, SCIF1, SCIF2, SCIF3,
-	SSU0, SSU1, ROMDEC, SDHI, FLCTL, RTC, RCAN0, RCAN1, SRC
+	PINT,
 };
 
 static struct intc_vect vectors[] __initdata = {
@@ -73,79 +50,80 @@
 	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(DMAC0_DEI, 108), INTC_IRQ(DMAC0_HEI, 109),
-	INTC_IRQ(DMAC1_DEI, 112), INTC_IRQ(DMAC1_HEI, 113),
-	INTC_IRQ(DMAC2_DEI, 116), INTC_IRQ(DMAC2_HEI, 117),
-	INTC_IRQ(DMAC3_DEI, 120), INTC_IRQ(DMAC3_HEI, 121),
-	INTC_IRQ(DMAC4_DEI, 124), INTC_IRQ(DMAC4_HEI, 125),
-	INTC_IRQ(DMAC5_DEI, 128), INTC_IRQ(DMAC5_HEI, 129),
-	INTC_IRQ(DMAC6_DEI, 132), INTC_IRQ(DMAC6_HEI, 133),
-	INTC_IRQ(DMAC7_DEI, 136), INTC_IRQ(DMAC7_HEI, 137),
+	INTC_IRQ(DMAC0, 108), INTC_IRQ(DMAC0, 109),
+	INTC_IRQ(DMAC1, 112), INTC_IRQ(DMAC1, 113),
+	INTC_IRQ(DMAC2, 116), INTC_IRQ(DMAC2, 117),
+	INTC_IRQ(DMAC3, 120), INTC_IRQ(DMAC3, 121),
+	INTC_IRQ(DMAC4, 124), INTC_IRQ(DMAC4, 125),
+	INTC_IRQ(DMAC5, 128), INTC_IRQ(DMAC5, 129),
+	INTC_IRQ(DMAC6, 132), INTC_IRQ(DMAC6, 133),
+	INTC_IRQ(DMAC7, 136), INTC_IRQ(DMAC7, 137),
 	INTC_IRQ(USB, 140), INTC_IRQ(LCDC, 141),
 	INTC_IRQ(CMT0, 142), INTC_IRQ(CMT1, 143),
 	INTC_IRQ(BSC, 144), INTC_IRQ(WDT, 145),
-	INTC_IRQ(MTU2_TGI0A, 146), INTC_IRQ(MTU2_TGI0B, 147),
-	INTC_IRQ(MTU2_TGI0C, 148), INTC_IRQ(MTU2_TGI0D, 149),
-	INTC_IRQ(MTU2_TCI0V, 150),
-	INTC_IRQ(MTU2_TGI0E, 151), INTC_IRQ(MTU2_TGI0F, 152),
-	INTC_IRQ(MTU2_TGI1A, 153), INTC_IRQ(MTU2_TGI1B, 154),
-	INTC_IRQ(MTU2_TCI1V, 155), INTC_IRQ(MTU2_TCI1U, 156),
-	INTC_IRQ(MTU2_TGI2A, 157), INTC_IRQ(MTU2_TGI2B, 158),
-	INTC_IRQ(MTU2_TCI2V, 159), INTC_IRQ(MTU2_TCI2U, 160),
-	INTC_IRQ(MTU2_TGI3A, 161), INTC_IRQ(MTU2_TGI3B, 162),
-	INTC_IRQ(MTU2_TGI3C, 163), INTC_IRQ(MTU2_TGI3D, 164),
+	INTC_IRQ(MTU0_ABCD, 146), INTC_IRQ(MTU0_ABCD, 147),
+	INTC_IRQ(MTU0_ABCD, 148), INTC_IRQ(MTU0_ABCD, 149),
+	INTC_IRQ(MTU0_VEF, 150),
+	INTC_IRQ(MTU0_VEF, 151), INTC_IRQ(MTU0_VEF, 152),
+	INTC_IRQ(MTU1_AB, 153), INTC_IRQ(MTU1_AB, 154),
+	INTC_IRQ(MTU1_VU, 155), INTC_IRQ(MTU1_VU, 156),
+	INTC_IRQ(MTU2_AB, 157), INTC_IRQ(MTU2_AB, 158),
+	INTC_IRQ(MTU2_VU, 159), INTC_IRQ(MTU2_VU, 160),
+	INTC_IRQ(MTU3_ABCD, 161), INTC_IRQ(MTU3_ABCD, 162),
+	INTC_IRQ(MTU3_ABCD, 163), INTC_IRQ(MTU3_ABCD, 164),
 	INTC_IRQ(MTU2_TCI3V, 165),
-	INTC_IRQ(MTU2_TGI4A, 166), INTC_IRQ(MTU2_TGI4B, 167),
-	INTC_IRQ(MTU2_TGI4C, 168), INTC_IRQ(MTU2_TGI4D, 169),
+	INTC_IRQ(MTU4_ABCD, 166), INTC_IRQ(MTU4_ABCD, 167),
+	INTC_IRQ(MTU4_ABCD, 168), INTC_IRQ(MTU4_ABCD, 169),
 	INTC_IRQ(MTU2_TCI4V, 170),
 	INTC_IRQ(ADC_ADI, 171),
-	INTC_IRQ(IIC30_STPI, 172), INTC_IRQ(IIC30_NAKI, 173),
-	INTC_IRQ(IIC30_RXI, 174), INTC_IRQ(IIC30_TXI, 175),
-	INTC_IRQ(IIC30_TEI, 176),
-	INTC_IRQ(IIC31_STPI, 177), INTC_IRQ(IIC31_NAKI, 178),
-	INTC_IRQ(IIC31_RXI, 179), INTC_IRQ(IIC31_TXI, 180),
-	INTC_IRQ(IIC31_TEI, 181),
-	INTC_IRQ(IIC32_STPI, 182), INTC_IRQ(IIC32_NAKI, 183),
-	INTC_IRQ(IIC32_RXI, 184), INTC_IRQ(IIC32_TXI, 185),
-	INTC_IRQ(IIC32_TEI, 186),
-	INTC_IRQ(IIC33_STPI, 187), INTC_IRQ(IIC33_NAKI, 188),
-	INTC_IRQ(IIC33_RXI, 189), INTC_IRQ(IIC33_TXI, 190),
-	INTC_IRQ(IIC33_TEI, 191),
-	INTC_IRQ(SCIF0_BRI, 192), INTC_IRQ(SCIF0_ERI, 193),
-	INTC_IRQ(SCIF0_RXI, 194), INTC_IRQ(SCIF0_TXI, 195),
-	INTC_IRQ(SCIF1_BRI, 196), INTC_IRQ(SCIF1_ERI, 197),
-	INTC_IRQ(SCIF1_RXI, 198), INTC_IRQ(SCIF1_TXI, 199),
-	INTC_IRQ(SCIF2_BRI, 200), INTC_IRQ(SCIF2_ERI, 201),
-	INTC_IRQ(SCIF2_RXI, 202), INTC_IRQ(SCIF2_TXI, 203),
-	INTC_IRQ(SCIF3_BRI, 204), INTC_IRQ(SCIF3_ERI, 205),
-	INTC_IRQ(SCIF3_RXI, 206), INTC_IRQ(SCIF3_TXI, 207),
-	INTC_IRQ(SSU0_SSERI, 208), INTC_IRQ(SSU0_SSRXI, 209),
-	INTC_IRQ(SSU0_SSTXI, 210),
-	INTC_IRQ(SSU1_SSERI, 211), INTC_IRQ(SSU1_SSRXI, 212),
-	INTC_IRQ(SSU1_SSTXI, 213),
+	INTC_IRQ(IIC30, 172), INTC_IRQ(IIC30, 173),
+	INTC_IRQ(IIC30, 174), INTC_IRQ(IIC30, 175),
+	INTC_IRQ(IIC30, 176),
+	INTC_IRQ(IIC31, 177), INTC_IRQ(IIC31, 178),
+	INTC_IRQ(IIC31, 179), INTC_IRQ(IIC31, 180),
+	INTC_IRQ(IIC31, 181),
+	INTC_IRQ(IIC32, 182), INTC_IRQ(IIC32, 183),
+	INTC_IRQ(IIC32, 184), INTC_IRQ(IIC32, 185),
+	INTC_IRQ(IIC32, 186),
+	INTC_IRQ(IIC33, 187), INTC_IRQ(IIC33, 188),
+	INTC_IRQ(IIC33, 189), INTC_IRQ(IIC33, 190),
+	INTC_IRQ(IIC33, 191),
+	INTC_IRQ(SCIF0, 192), INTC_IRQ(SCIF0, 193),
+	INTC_IRQ(SCIF0, 194), INTC_IRQ(SCIF0, 195),
+	INTC_IRQ(SCIF1, 196), INTC_IRQ(SCIF1, 197),
+	INTC_IRQ(SCIF1, 198), INTC_IRQ(SCIF1, 199),
+	INTC_IRQ(SCIF2, 200), INTC_IRQ(SCIF2, 201),
+	INTC_IRQ(SCIF2, 202), INTC_IRQ(SCIF2, 203),
+	INTC_IRQ(SCIF3, 204), INTC_IRQ(SCIF3, 205),
+	INTC_IRQ(SCIF3, 206), INTC_IRQ(SCIF3, 207),
+	INTC_IRQ(SSU0, 208), INTC_IRQ(SSU0, 209),
+	INTC_IRQ(SSU0, 210),
+	INTC_IRQ(SSU1, 211), INTC_IRQ(SSU1, 212),
+	INTC_IRQ(SSU1, 213),
 	INTC_IRQ(SSI0_SSII, 214), INTC_IRQ(SSI1_SSII, 215),
 	INTC_IRQ(SSI2_SSII, 216), INTC_IRQ(SSI3_SSII, 217),
-	INTC_IRQ(FLCTL_FLSTEI, 224), INTC_IRQ(FLCTL_FLTENDI, 225),
-	INTC_IRQ(FLCTL_FLTREQ0I, 226), INTC_IRQ(FLCTL_FLTREQ1I, 227),
-	INTC_IRQ(RTC_ARM, 231), INTC_IRQ(RTC_PRD, 232),
-	INTC_IRQ(RTC_CUP, 233),
-	INTC_IRQ(RCAN0_ERS, 234), INTC_IRQ(RCAN0_OVR, 235),
-	INTC_IRQ(RCAN0_RM0, 236), INTC_IRQ(RCAN0_RM1, 237),
-	INTC_IRQ(RCAN0_SLE, 238),
-	INTC_IRQ(RCAN1_ERS, 239), INTC_IRQ(RCAN1_OVR, 240),
-	INTC_IRQ(RCAN1_RM0, 241), INTC_IRQ(RCAN1_RM1, 242),
-	INTC_IRQ(RCAN1_SLE, 243),
+	INTC_IRQ(FLCTL, 224), INTC_IRQ(FLCTL, 225),
+	INTC_IRQ(FLCTL, 226), INTC_IRQ(FLCTL, 227),
+	INTC_IRQ(RTC, 231), INTC_IRQ(RTC, 232),
+	INTC_IRQ(RTC, 233),
+	INTC_IRQ(RCAN0, 234), INTC_IRQ(RCAN0, 235),
+	INTC_IRQ(RCAN0, 236), INTC_IRQ(RCAN0, 237),
+	INTC_IRQ(RCAN0, 238),
+	INTC_IRQ(RCAN1, 239), INTC_IRQ(RCAN1, 240),
+	INTC_IRQ(RCAN1, 241), INTC_IRQ(RCAN1, 242),
+	INTC_IRQ(RCAN1, 243),
 
 	/* SH7263-specific trash */
 #ifdef CONFIG_CPU_SUBTYPE_SH7263
-	INTC_IRQ(ROMDEC_ISY, 218), INTC_IRQ(ROMDEC_IERR, 219),
-	INTC_IRQ(ROMDEC_IARG, 220), INTC_IRQ(ROMDEC_ISEC, 221),
-	INTC_IRQ(ROMDEC_IBUF, 222), INTC_IRQ(ROMDEC_IREADY, 223),
+	INTC_IRQ(ROMDEC, 218), INTC_IRQ(ROMDEC, 219),
+	INTC_IRQ(ROMDEC, 220), INTC_IRQ(ROMDEC, 221),
+	INTC_IRQ(ROMDEC, 222), INTC_IRQ(ROMDEC, 223),
 
-	INTC_IRQ(SDHI3, 228), INTC_IRQ(SDHI0, 229), INTC_IRQ(SDHI1, 230),
+	INTC_IRQ(SDHI, 228), INTC_IRQ(SDHI, 229),
+	INTC_IRQ(SDHI, 230),
 
-	INTC_IRQ(SRC_OVF, 244), INTC_IRQ(SRC_ODFI, 245),
-	INTC_IRQ(SRC_IDEI, 246),
+	INTC_IRQ(SRC, 244), INTC_IRQ(SRC, 245),
+	INTC_IRQ(SRC, 246),
 
 	INTC_IRQ(IEBI, 247),
 #endif
@@ -154,50 +132,6 @@
 static struct intc_group groups[] __initdata = {
 	INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
 		   PINT4, PINT5, PINT6, PINT7),
-	INTC_GROUP(DMAC0, DMAC0_DEI, DMAC0_HEI),
-	INTC_GROUP(DMAC1, DMAC1_DEI, DMAC1_HEI),
-	INTC_GROUP(DMAC2, DMAC2_DEI, DMAC2_HEI),
-	INTC_GROUP(DMAC3, DMAC3_DEI, DMAC3_HEI),
-	INTC_GROUP(DMAC4, DMAC4_DEI, DMAC4_HEI),
-	INTC_GROUP(DMAC5, DMAC5_DEI, DMAC5_HEI),
-	INTC_GROUP(DMAC6, DMAC6_DEI, DMAC6_HEI),
-	INTC_GROUP(DMAC7, DMAC7_DEI, DMAC7_HEI),
-	INTC_GROUP(MTU0_ABCD, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D),
-	INTC_GROUP(MTU0_VEF, MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F),
-	INTC_GROUP(MTU1_AB, MTU2_TGI1A, MTU2_TGI1B),
-	INTC_GROUP(MTU1_VU, MTU2_TCI1V, MTU2_TCI1U),
-	INTC_GROUP(MTU2_AB, MTU2_TGI2A, MTU2_TGI2B),
-	INTC_GROUP(MTU2_VU, MTU2_TCI2V, MTU2_TCI2U),
-	INTC_GROUP(MTU3_ABCD, MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D),
-	INTC_GROUP(MTU4_ABCD, MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D),
-	INTC_GROUP(IIC30, IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI,
-		   IIC30_TEI),
-	INTC_GROUP(IIC31, IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI,
-		   IIC31_TEI),
-	INTC_GROUP(IIC32, IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI,
-		   IIC32_TEI),
-	INTC_GROUP(IIC33, IIC33_STPI, IIC33_NAKI, IIC33_RXI, IIC33_TXI,
-		   IIC33_TEI),
-	INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
-	INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
-	INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
-	INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI),
-	INTC_GROUP(SSU0, SSU0_SSERI, SSU0_SSRXI, SSU0_SSTXI),
-	INTC_GROUP(SSU1, SSU1_SSERI, SSU1_SSRXI, SSU1_SSTXI),
-	INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I,
-		   FLCTL_FLTREQ1I),
-	INTC_GROUP(RTC, RTC_ARM, RTC_PRD, RTC_CUP),
-	INTC_GROUP(RCAN0, RCAN0_ERS, RCAN0_OVR, RCAN0_RM0, RCAN0_RM1,
-		   RCAN0_SLE),
-	INTC_GROUP(RCAN1, RCAN1_ERS, RCAN1_OVR, RCAN1_RM0, RCAN1_RM1,
-		   RCAN1_SLE),
-
-#ifdef CONFIG_CPU_SUBTYPE_SH7263
-	INTC_GROUP(ROMDEC, ROMDEC_ISY, ROMDEC_IERR, ROMDEC_IARG,
-		   ROMDEC_ISEC, ROMDEC_IBUF, ROMDEC_IREADY),
-	INTC_GROUP(SDHI, SDHI3, SDHI0, SDHI1),
-	INTC_GROUP(SRC, SRC_OVF, SRC_ODFI, SRC_IDEI),
-#endif
 };
 
 static struct intc_prio_reg prio_registers[] __initdata = {
@@ -242,22 +176,22 @@
 		.mapbase	= 0xfffe8000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 193, 194, 195, 192 },
+		.irqs		=  { 192, 192, 192, 192 },
 	}, {
 		.mapbase	= 0xfffe8800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 197, 198, 199, 196 },
+		.irqs		=  { 196, 196, 196, 196 },
 	}, {
 		.mapbase	= 0xfffe9000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 201, 202, 203, 200 },
+		.irqs		=  { 200, 200, 200, 200 },
 	}, {
 		.mapbase	= 0xfffe9800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 205, 206, 207, 204 },
+		.irqs		=  { 204, 204, 204, 204 },
 	}, {
 		.flags = 0,
 	}
@@ -278,17 +212,7 @@
 		.flags	= IORESOURCE_IO,
 	},
 	[1] = {
-		/* Period IRQ */
-		.start	= 232,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		/* Carry IRQ */
-		.start	= 233,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		/* Alarm IRQ */
+		/* Shared Period/Carry/Alarm IRQ */
 		.start	= 231,
 		.flags	= IORESOURCE_IRQ,
 	},
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index e6d4ec4..c46a835 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -2,6 +2,7 @@
  * SH7206 Setup
  *
  *  Copyright (C) 2006  Yoshinori Sato
+ *  Copyright (C) 2009  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
@@ -19,34 +20,23 @@
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
 	PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
 	ADC_ADI0, ADC_ADI1,
-	DMAC0_DEI, DMAC0_HEI, DMAC1_DEI, DMAC1_HEI,
-	DMAC2_DEI, DMAC2_HEI, DMAC3_DEI, DMAC3_HEI,
-	DMAC4_DEI, DMAC4_HEI, DMAC5_DEI, DMAC5_HEI,
-	DMAC6_DEI, DMAC6_HEI, DMAC7_DEI, DMAC7_HEI,
-	CMT0, CMT1, BSC, WDT,
-	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,
-	POE2_OEI1, POE2_OEI2,
-	MTU2S_TGI3A, MTU2S_TGI3B, MTU2S_TGI3C, MTU2S_TGI3D, MTU2S_TCI3V,
-	MTU2S_TGI4A, MTU2S_TGI4B, MTU2S_TGI4C, MTU2S_TGI4D, MTU2S_TCI4V,
-	MTU2S_TGI5U, MTU2S_TGI5V, MTU2S_TGI5W,
-	POE2_OEI3,
-	IIC3_STPI, IIC3_NAKI, IIC3_RXI, IIC3_TXI, IIC3_TEI,
-	SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
-	SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
-	SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
-	SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI,
 
-	/* interrupt groups */
-	PINT, DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
+	DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
+
 	MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
 	MTU3_ABCD, MTU4_ABCD, MTU5, POE2_12, MTU3S_ABCD, MTU4S_ABCD, MTU5S,
-	IIC3, SCIF0, SCIF1, SCIF2, SCIF3,
+	IIC3,
+
+	CMT0, CMT1, BSC, WDT,
+
+	MTU2_TCI3V, MTU2_TCI4V, MTU2S_TCI3V, MTU2S_TCI4V,
+
+	POE2_OEI3,
+
+	SCIF0, SCIF1, SCIF2, SCIF3,
+
+	/* interrupt groups */
+	PINT,
 };
 
 static struct intc_vect vectors[] __initdata = {
@@ -59,86 +49,58 @@
 	INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
 	INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
 	INTC_IRQ(ADC_ADI0, 92), INTC_IRQ(ADC_ADI1, 96),
-	INTC_IRQ(DMAC0_DEI, 108), INTC_IRQ(DMAC0_HEI, 109),
-	INTC_IRQ(DMAC1_DEI, 112), INTC_IRQ(DMAC1_HEI, 113),
-	INTC_IRQ(DMAC2_DEI, 116), INTC_IRQ(DMAC2_HEI, 117),
-	INTC_IRQ(DMAC3_DEI, 120), INTC_IRQ(DMAC3_HEI, 121),
-	INTC_IRQ(DMAC4_DEI, 124), INTC_IRQ(DMAC4_HEI, 125),
-	INTC_IRQ(DMAC5_DEI, 128), INTC_IRQ(DMAC5_HEI, 129),
-	INTC_IRQ(DMAC6_DEI, 132), INTC_IRQ(DMAC6_HEI, 133),
-	INTC_IRQ(DMAC7_DEI, 136), INTC_IRQ(DMAC7_HEI, 137),
+	INTC_IRQ(DMAC0, 108), INTC_IRQ(DMAC0, 109),
+	INTC_IRQ(DMAC1, 112), INTC_IRQ(DMAC1, 113),
+	INTC_IRQ(DMAC2, 116), INTC_IRQ(DMAC2, 117),
+	INTC_IRQ(DMAC3, 120), INTC_IRQ(DMAC3, 121),
+	INTC_IRQ(DMAC4, 124), INTC_IRQ(DMAC4, 125),
+	INTC_IRQ(DMAC5, 128), INTC_IRQ(DMAC5, 129),
+	INTC_IRQ(DMAC6, 132), INTC_IRQ(DMAC6, 133),
+	INTC_IRQ(DMAC7, 136), INTC_IRQ(DMAC7, 137),
 	INTC_IRQ(CMT0, 140), INTC_IRQ(CMT1, 144),
 	INTC_IRQ(BSC, 148), INTC_IRQ(WDT, 152),
-	INTC_IRQ(MTU2_TGI0A, 156), INTC_IRQ(MTU2_TGI0B, 157),
-	INTC_IRQ(MTU2_TGI0C, 158), INTC_IRQ(MTU2_TGI0D, 159),
-	INTC_IRQ(MTU2_TCI0V, 160),
-	INTC_IRQ(MTU2_TGI0E, 161), INTC_IRQ(MTU2_TGI0F, 162),
-	INTC_IRQ(MTU2_TGI1A, 164), INTC_IRQ(MTU2_TGI1B, 165),
-	INTC_IRQ(MTU2_TCI1V, 168), INTC_IRQ(MTU2_TCI1U, 169),
-	INTC_IRQ(MTU2_TGI2A, 172), INTC_IRQ(MTU2_TGI2B, 173),
-	INTC_IRQ(MTU2_TCI2V, 176), INTC_IRQ(MTU2_TCI2U, 177),
-	INTC_IRQ(MTU2_TGI3A, 180), INTC_IRQ(MTU2_TGI3B, 181),
-	INTC_IRQ(MTU2_TGI3C, 182), INTC_IRQ(MTU2_TGI3D, 183),
+	INTC_IRQ(MTU0_ABCD, 156), INTC_IRQ(MTU0_ABCD, 157),
+	INTC_IRQ(MTU0_ABCD, 158), INTC_IRQ(MTU0_ABCD, 159),
+	INTC_IRQ(MTU0_VEF, 160), INTC_IRQ(MTU0_VEF, 161),
+	INTC_IRQ(MTU0_VEF, 162),
+	INTC_IRQ(MTU1_AB, 164), INTC_IRQ(MTU1_AB, 165),
+	INTC_IRQ(MTU1_VU, 168), INTC_IRQ(MTU1_VU, 169),
+	INTC_IRQ(MTU2_AB, 172), INTC_IRQ(MTU2_AB, 173),
+	INTC_IRQ(MTU2_VU, 176), INTC_IRQ(MTU2_VU, 177),
+	INTC_IRQ(MTU3_ABCD, 180), INTC_IRQ(MTU3_ABCD, 181),
+	INTC_IRQ(MTU3_ABCD, 182), INTC_IRQ(MTU3_ABCD, 183),
 	INTC_IRQ(MTU2_TCI3V, 184),
-	INTC_IRQ(MTU2_TGI4A, 188), INTC_IRQ(MTU2_TGI4B, 189),
-	INTC_IRQ(MTU2_TGI4C, 190), INTC_IRQ(MTU2_TGI4D, 191),
+	INTC_IRQ(MTU4_ABCD, 188), INTC_IRQ(MTU4_ABCD, 189),
+	INTC_IRQ(MTU4_ABCD, 190), INTC_IRQ(MTU4_ABCD, 191),
 	INTC_IRQ(MTU2_TCI4V, 192),
-	INTC_IRQ(MTU2_TGI5U, 196), INTC_IRQ(MTU2_TGI5V, 197),
-	INTC_IRQ(MTU2_TGI5W, 198),
-	INTC_IRQ(POE2_OEI1, 200), INTC_IRQ(POE2_OEI2, 201),
-	INTC_IRQ(MTU2S_TGI3A, 204), INTC_IRQ(MTU2S_TGI3B, 205),
-	INTC_IRQ(MTU2S_TGI3C, 206), INTC_IRQ(MTU2S_TGI3D, 207),
+	INTC_IRQ(MTU5, 196), INTC_IRQ(MTU5, 197),
+	INTC_IRQ(MTU5, 198),
+	INTC_IRQ(POE2_12, 200), INTC_IRQ(POE2_12, 201),
+	INTC_IRQ(MTU3S_ABCD, 204), INTC_IRQ(MTU3S_ABCD, 205),
+	INTC_IRQ(MTU3S_ABCD, 206), INTC_IRQ(MTU3S_ABCD, 207),
 	INTC_IRQ(MTU2S_TCI3V, 208),
-	INTC_IRQ(MTU2S_TGI4A, 212), INTC_IRQ(MTU2S_TGI4B, 213),
-	INTC_IRQ(MTU2S_TGI4C, 214), INTC_IRQ(MTU2S_TGI4D, 215),
+	INTC_IRQ(MTU4S_ABCD, 212), INTC_IRQ(MTU4S_ABCD, 213),
+	INTC_IRQ(MTU4S_ABCD, 214), INTC_IRQ(MTU4S_ABCD, 215),
 	INTC_IRQ(MTU2S_TCI4V, 216),
-	INTC_IRQ(MTU2S_TGI5U, 220), INTC_IRQ(MTU2S_TGI5V, 221),
-	INTC_IRQ(MTU2S_TGI5W, 222),
+	INTC_IRQ(MTU5S, 220), INTC_IRQ(MTU5S, 221),
+	INTC_IRQ(MTU5S, 222),
 	INTC_IRQ(POE2_OEI3, 224),
-	INTC_IRQ(IIC3_STPI, 228), INTC_IRQ(IIC3_NAKI, 229),
-	INTC_IRQ(IIC3_RXI, 230), INTC_IRQ(IIC3_TXI, 231),
-	INTC_IRQ(IIC3_TEI, 232),
-	INTC_IRQ(SCIF0_BRI, 240), INTC_IRQ(SCIF0_ERI, 241),
-	INTC_IRQ(SCIF0_RXI, 242), INTC_IRQ(SCIF0_TXI, 243),
-	INTC_IRQ(SCIF1_BRI, 244), INTC_IRQ(SCIF1_ERI, 245),
-	INTC_IRQ(SCIF1_RXI, 246), INTC_IRQ(SCIF1_TXI, 247),
-	INTC_IRQ(SCIF2_BRI, 248), INTC_IRQ(SCIF2_ERI, 249),
-	INTC_IRQ(SCIF2_RXI, 250), INTC_IRQ(SCIF2_TXI, 251),
-	INTC_IRQ(SCIF3_BRI, 252), INTC_IRQ(SCIF3_ERI, 253),
-	INTC_IRQ(SCIF3_RXI, 254), INTC_IRQ(SCIF3_TXI, 255),
+	INTC_IRQ(IIC3, 228), INTC_IRQ(IIC3, 229),
+	INTC_IRQ(IIC3, 230), INTC_IRQ(IIC3, 231),
+	INTC_IRQ(IIC3, 232),
+	INTC_IRQ(SCIF0, 240), INTC_IRQ(SCIF0, 241),
+	INTC_IRQ(SCIF0, 242), INTC_IRQ(SCIF0, 243),
+	INTC_IRQ(SCIF1, 244), INTC_IRQ(SCIF1, 245),
+	INTC_IRQ(SCIF1, 246), INTC_IRQ(SCIF1, 247),
+	INTC_IRQ(SCIF2, 248), INTC_IRQ(SCIF2, 249),
+	INTC_IRQ(SCIF2, 250), INTC_IRQ(SCIF2, 251),
+	INTC_IRQ(SCIF3, 252), INTC_IRQ(SCIF3, 253),
+	INTC_IRQ(SCIF3, 254), INTC_IRQ(SCIF3, 255),
 };
 
 static struct intc_group groups[] __initdata = {
 	INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
 		   PINT4, PINT5, PINT6, PINT7),
-	INTC_GROUP(DMAC0, DMAC0_DEI, DMAC0_HEI),
-	INTC_GROUP(DMAC1, DMAC1_DEI, DMAC1_HEI),
-	INTC_GROUP(DMAC2, DMAC2_DEI, DMAC2_HEI),
-	INTC_GROUP(DMAC3, DMAC3_DEI, DMAC3_HEI),
-	INTC_GROUP(DMAC4, DMAC4_DEI, DMAC4_HEI),
-	INTC_GROUP(DMAC5, DMAC5_DEI, DMAC5_HEI),
-	INTC_GROUP(DMAC6, DMAC6_DEI, DMAC6_HEI),
-	INTC_GROUP(DMAC7, DMAC7_DEI, DMAC7_HEI),
-	INTC_GROUP(MTU0_ABCD, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D),
-	INTC_GROUP(MTU0_VEF, MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F),
-	INTC_GROUP(MTU1_AB, MTU2_TGI1A, MTU2_TGI1B),
-	INTC_GROUP(MTU1_VU, MTU2_TCI1V, MTU2_TCI1U),
-	INTC_GROUP(MTU2_AB, MTU2_TGI2A, MTU2_TGI2B),
-	INTC_GROUP(MTU2_VU, MTU2_TCI2V, MTU2_TCI2U),
-	INTC_GROUP(MTU3_ABCD, MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D),
-	INTC_GROUP(MTU4_ABCD, MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D),
-	INTC_GROUP(MTU5, MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W),
-	INTC_GROUP(POE2_12, POE2_OEI1, POE2_OEI2),
-	INTC_GROUP(MTU3S_ABCD, MTU2S_TGI3A, MTU2S_TGI3B,
-		   MTU2S_TGI3C, MTU2S_TGI3D),
-	INTC_GROUP(MTU4S_ABCD, MTU2S_TGI4A, MTU2S_TGI4B,
-		   MTU2S_TGI4C, MTU2S_TGI4D),
-	INTC_GROUP(MTU5S, MTU2S_TGI5U, MTU2S_TGI5V, MTU2S_TGI5W),
-	INTC_GROUP(IIC3, IIC3_STPI, IIC3_NAKI, IIC3_RXI, IIC3_TXI, IIC3_TEI),
-	INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
-	INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
-	INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
-	INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI),
 };
 
 static struct intc_prio_reg prio_registers[] __initdata = {
@@ -174,22 +136,22 @@
 		.mapbase	= 0xfffe8000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 241, 242, 243, 240 },
+		.irqs		= { 240, 240, 240, 240 },
 	}, {
 		.mapbase	= 0xfffe8800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 245, 246, 247, 244 },
+		.irqs		= { 244, 244, 244, 244 },
 	}, {
 		.mapbase	= 0xfffe9000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 249, 250, 251, 248 },
+		.irqs		= { 248, 248, 248, 248 },
 	}, {
 		.mapbase	= 0xfffe9800,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		=  { 253, 254, 255, 252 },
+		.irqs		= { 252, 252, 252, 252 },
 	}, {
 		.flags = 0,
 	}
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile
index e07c69e..ecab274 100644
--- a/arch/sh/kernel/cpu/sh3/Makefile
+++ b/arch/sh/kernel/cpu/sh3/Makefile
@@ -4,6 +4,8 @@
 
 obj-y	:= ex.o probe.o entry.o setup-sh3.o
 
+obj-$(CONFIG_HIBERNATION)		+= swsusp.o
+
 # CPU subtype setup
 obj-$(CONFIG_CPU_SUBTYPE_SH7705)	+= setup-sh7705.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7706)	+= setup-sh770x.o
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index b4106d0..55da0ff 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -16,6 +16,7 @@
 #include <asm/unistd.h>
 #include <cpu/mmu_context.h>
 #include <asm/page.h>
+#include <asm/cache.h>
 
 ! NOTE:
 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -187,44 +188,35 @@
 #if defined(CONFIG_SH_STANDARD_BIOS)
 	/* Unwind the stack and jmp to the debug entry */
 ENTRY(sh_bios_handler)
-	mov.l	@r15+, r0
-	mov.l	@r15+, r1
-	mov.l	@r15+, r2
-	mov.l	@r15+, r3
-	mov.l	@r15+, r4
-	mov.l	@r15+, r5
-	mov.l	@r15+, r6
-	mov.l	@r15+, r7
-	stc	sr, r8
-	mov.l	1f, r9			! BL =1, RB=1, IMASK=0x0F
-	or	r9, r8
-	ldc	r8, sr			! here, change the register bank
-	mov.l	@r15+, r8
-	mov.l	@r15+, r9
-	mov.l	@r15+, r10
-	mov.l	@r15+, r11
-	mov.l	@r15+, r12
-	mov.l	@r15+, r13
-	mov.l	@r15+, r14
-	mov.l	@r15+, k0
-	ldc.l	@r15+, spc
-	lds.l	@r15+, pr
-	mov.l	@r15+, k1
-	ldc.l	@r15+, gbr
-	lds.l	@r15+, mach
-	lds.l	@r15+, macl
-	mov	k0, r15
+	mov.l	1f, r8
+	bsr	restore_regs
+	 nop
+
+	lds	k2, pr			! restore pr
+	mov	k4, r15
 	!
 	mov.l	2f, k0
 	mov.l	@k0, k0
 	jmp	@k0
-	 ldc	k1, ssr
+	 ldc	k3, ssr
 	.align	2
 1:	.long	0x300000f0
 2:	.long	gdb_vbr_vector
 #endif /* CONFIG_SH_STANDARD_BIOS */
 
-restore_all:
+! restore_regs()
+! - restore r0, r1, r2, r3, r4, r5, r6, r7 from the stack
+! - switch bank
+! - restore r8, r9, r10, r11, r12, r13, r14, r15 from the stack
+! - restore spc, pr*, ssr, gbr, mach, macl, skip default tra
+! k2 returns original pr
+! k3 returns original sr
+! k4 returns original stack pointer
+! r8 passes SR bitmask, overwritten with restored data on return
+! r9 trashed
+! BL=0 on entry, on exit BL=1 (depending on r8).
+
+ENTRY(restore_regs)
 	mov.l	@r15+, r0
 	mov.l	@r15+, r1
 	mov.l	@r15+, r2
@@ -234,10 +226,9 @@
 	mov.l	@r15+, r6
 	mov.l	@r15+, r7
 	!
-	stc	sr, r8
-	mov.l	7f, r9
-	or	r9, r8			! BL =1, RB=1
-	ldc	r8, sr			! here, change the register bank
+	stc	sr, r9
+	or	r8, r9
+	ldc	r9, sr
 	!
 	mov.l	@r15+, r8
 	mov.l	@r15+, r9
@@ -248,12 +239,20 @@
 	mov.l	@r15+, r14
 	mov.l	@r15+, k4		! original stack pointer
 	ldc.l	@r15+, spc
-	lds.l	@r15+, pr
+	mov.l	@r15+, k2		! original PR
 	mov.l	@r15+, k3		! original SR
 	ldc.l	@r15+, gbr
 	lds.l	@r15+, mach
 	lds.l	@r15+, macl
-	add	#4, r15			! Skip syscall number
+	rts
+	 add	#4, r15			! Skip syscall number
+
+restore_all:
+	mov.l	7f, r8
+	bsr	restore_regs
+	 nop
+
+	lds	k2, pr			! restore pr
 	!
 #ifdef CONFIG_SH_DSP
 	mov.l	@r15+, k0		! DSP mode marker
@@ -294,7 +293,7 @@
 	mov	#0xf0, k1
 	extu.b	k1, k1
 	not	k1, k1
-	and	k1, k2			! Mask orignal SR value
+	and	k1, k2			! Mask original SR value
 	!
 	mov	k3, k0			! Calculate IMASK-bits
 	shlr2	k0
@@ -313,7 +312,6 @@
 	mov	#0, k1
 	mov.b	k1, @k0
 #endif
-	mov.l	@r15+, k2		! restore EXPEVT
 	mov	k4, r15
 	rte
 	 nop
@@ -336,81 +334,55 @@
 ENTRY(vbr_base)
 	.long	0
 !
+! 0x100: General exception vector
+!
 	.balign 	256,0,256
 general_exception:
-	mov.l	1f, k2
-	mov.l	2f, k3
-#ifdef CONFIG_CPU_SUBTYPE_SHX3
-	mov.l	@k2, k2
+#ifndef CONFIG_CPU_SUBTYPE_SHX3
+	bra	handle_exception
+	 sts	pr, k3		! save original pr value in k3
+#else
+	mov.l	1f, k4
+	mov.l	@k4, k4
 
 	! Is EXPEVT larger than 0x800?
 	mov	#0x8, k0
 	shll8	k0
-	cmp/hs	k0, k2
+	cmp/hs	k0, k4
 	bf	0f
 
 	! then add 0x580 (k2 is 0xd80 or 0xda0)
 	mov	#0x58, k0
 	shll2	k0
 	shll2	k0
-	add	k0, k2
+	add	k0, k4
 0:
-	bra	handle_exception
+	! Setup stack and save DSP context (k0 contains original r15 on return)
+	bsr	prepare_stack_save_dsp
 	 nop
-#else
-	bra	handle_exception
-	 mov.l	@k2, k2
+
+	! Save registers / Switch to bank 0
+	mov		k4, k2		! keep vector in k2
+	mov.l	1f, k4		! SR bits to clear in k4
+	bsr	save_regs	! needs original pr value in k3
+	 nop
+
+	bra	handle_exception_special
+	 nop
+
+	.align	2
+1:	.long	EXPEVT
 #endif
-	.align	2
-1:	.long	EXPEVT
-2:	.long	ret_from_exception
-!
-!
 
-	.balign 	1024,0,1024
-tlb_miss:
-	mov.l	1f, k2
-	mov.l	4f, k3
-	bra	handle_exception
-	 mov.l	@k2, k2
-!
-	.balign 	512,0,512
-interrupt:
-	mov.l	3f, k3
-#if defined(CONFIG_KGDB)
-	mov.l	2f, k2
-	! Debounce (filter nested NMI)
-	mov.l	@k2, k0
-	mov.l	5f, k1
-	cmp/eq	k1, k0
-	bf	0f
-	mov.l	6f, k1
-	tas.b	@k1
-	bt	0f
-	rte
-	 nop
-	.align	2
-2:	.long	INTEVT
-5:	.long	NMI_VEC
-6:	.long	in_nmi
-0:
-#endif /* defined(CONFIG_KGDB) */
-	bra	handle_exception
-	 mov	#-1, k2		! interrupt exception marker
+! prepare_stack_save_dsp()
+! - roll back gRB
+! - switch to kernel stack
+! - save DSP
+! k0 returns original sp (after roll back)
+! k1 trashed
+! k2 trashed
 
-	.align	2
-1:	.long	EXPEVT
-3:	.long	ret_from_irq
-4:	.long	ret_from_exception
-
-!
-!
-	.align	2
-ENTRY(handle_exception)
-	! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
-	! save all registers onto stack.
-	!
-
+prepare_stack_save_dsp:
 #ifdef CONFIG_GUSA
 	! Check for roll back gRB (User and Kernel)
 	mov	r15, k0
@@ -430,7 +402,7 @@
 2:	mov	k1, r15		! SP = r1
 1:
 #endif
-
+	! Switch to kernel stack if needed
 	stc	ssr, k0		! Is it from kernel space?
 	shll	k0		! Check MD bit (bit30) by shifting it into...
 	shll	k0		!       ...the T bit
@@ -443,18 +415,17 @@
 	add	current, k1
 	mov	k1, r15		! change to kernel stack
 	!
-1:	mov.l	2f, k1
-	!
+1:
 #ifdef CONFIG_SH_DSP
-	mov.l	r2, @-r15		! Save r2, we need another reg
-	stc	sr, k4
-	mov.l	1f, r2
-	tst	r2, k4			! Check if in DSP mode
-	mov.l	@r15+, r2		! Restore r2 now
+	! Save DSP context if needed
+	stc	sr, k1
+	mov	#0x10, k2
+	shll8   k2			! DSP=1 (0x00001000)
+	tst	k2, k1			! Check if in DSP mode (passed in k2)
 	bt/s	skip_save
-	 mov	#0, k4			! Set marker for no stack frame
+	 mov	#0, k1			! Set marker for no stack frame
 
-	mov	r2, k4			! Backup r2 (in k4) for later
+	mov	k2, k1			! Save has-frame marker
 
 	! Save DSP registers on stack
 	stc.l	mod, @-r15
@@ -473,35 +444,74 @@
 	! as we're not at all interested in supporting ancient toolchains at
 	! this point. -- PFM.
 
-	mov	r15, r2
+	mov	r15, k2
 	.word	0xf653			! movs.l	a1, @-r2
 	.word	0xf6f3			! movs.l	a0g, @-r2
 	.word	0xf6d3			! movs.l	a1g, @-r2
 	.word	0xf6c3			! movs.l	m0, @-r2
 	.word	0xf6e3			! movs.l	m1, @-r2
-	mov	r2, r15
+	mov	k2, r15
 
-	mov	k4, r2			! Restore r2
-	mov.l	1f, k4			! Force DSP stack frame
 skip_save:
-	mov.l	k4, @-r15		! Push DSP mode marker onto stack
+	mov.l	k1, @-r15		! Push DSP mode marker onto stack
 #endif
-	! Save the user registers on the stack.
-	mov.l	k2, @-r15	! EXPEVT
+	rts
+	 nop
+!
+! 0x400: Instruction and Data TLB miss exception vector
+!
+	.balign 	1024,0,1024
+tlb_miss:
+	sts	pr, k3		! save original pr value in k3
 
-	mov	#-1, k4
-	mov.l	k4, @-r15	! set TRA (default: -1)
-	!
+handle_exception:
+	mova	exception_data, k0
+
+	! Setup stack and save DSP context (k0 contains original r15 on return)
+	bsr	prepare_stack_save_dsp
+	 PREF(k0)
+
+	! Save registers / Switch to bank 0
+	mov.l	5f, k2		! vector register address
+	mov.l	1f, k4		! SR bits to clear in k4
+	bsr	save_regs	! needs original pr value in k3
+	 mov.l	@k2, k2		! read out vector and keep in k2
+
+handle_exception_special:
+	! Setup return address and jump to exception handler
+	mov.l	7f, r9		! fetch return address
+	stc	r2_bank, r0	! k2 (vector)
+	mov.l	6f, r10
+	shlr2	r0
+	shlr	r0
+	mov.l	@(r0, r10), r10
+	jmp	@r10
+	 lds	r9, pr		! put return address in pr
+
+	.align	L1_CACHE_SHIFT
+
+! save_regs()
+! - save default tra, macl, mach, gbr, ssr, pr* and spc on the stack
+! - save r15*, r14, r13, r12, r11, r10, r9, r8 on the stack
+! - switch bank
+! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
+! k0 contains original stack pointer*
+! k1 trashed
+! k3 passes original pr*
+! k4 passes SR bitmask
+! BL=1 on entry, on exit BL=0.
+
+ENTRY(save_regs)
+	mov	#-1, r1
+	mov.l	k1, @-r15	! set TRA (default: -1)
 	sts.l	macl, @-r15
 	sts.l	mach, @-r15
 	stc.l	gbr, @-r15
 	stc.l	ssr, @-r15
-	sts.l	pr, @-r15
+	mov.l	k3, @-r15	! original pr in k3
 	stc.l	spc, @-r15
-	!
-	lds	k3, pr		! Set the return address to pr
-	!
-	mov.l	k0, @-r15	! save orignal stack
+
+	mov.l	k0, @-r15	! original stack pointer in k0
 	mov.l	r14, @-r15
 	mov.l	r13, @-r15
 	mov.l	r12, @-r15
@@ -509,13 +519,23 @@
 	mov.l	r10, @-r15
 	mov.l	r9, @-r15
 	mov.l	r8, @-r15
-	!
-	stc	sr, r8		! Back to normal register bank, and
-	or	k1, r8		! Block all interrupts
-	mov.l	3f, k1
-	and	k1, r8		! ...
-	ldc	r8, sr		! ...changed here.
-	!
+
+	mov.l	0f, k3		! SR bits to set in k3
+
+	! fall-through
+
+! save_low_regs()
+! - modify SR for bank switch
+! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
+! k3 passes bits to set in SR
+! k4 passes bits to clear in SR
+
+ENTRY(save_low_regs)
+	stc	sr, r8
+	or	k3, r8
+	and	k4, r8
+	ldc	r8, sr
+
 	mov.l	r7, @-r15
 	mov.l	r6, @-r15
 	mov.l	r5, @-r15
@@ -523,52 +543,63 @@
 	mov.l	r3, @-r15
 	mov.l	r2, @-r15
 	mov.l	r1, @-r15
-	mov.l	r0, @-r15
-
-	/*
-	 * This gets a bit tricky.. in the INTEVT case we don't want to use
-	 * the VBR offset as a destination in the jump call table, since all
-	 * of the destinations are the same. In this case, (interrupt) sets
-	 * a marker in r2 (now r2_bank since SR.RB changed), which we check
-	 * to determine the exception type. For all other exceptions, we
-	 * forcibly read EXPEVT from memory and fix up the jump address, in
-	 * the interrupt exception case we jump to do_IRQ() and defer the
-	 * INTEVT read until there. As a bonus, we can also clean up the SR.RB
-	 * checks that do_IRQ() was doing..
-	 */
-	stc	r2_bank, r8
-	cmp/pz	r8
-	bf	interrupt_exception
-	shlr2	r8
-	shlr	r8
-	mov.l	4f, r9
-	add	r8, r9
-	mov.l	@r9, r9
-	jmp	@r9
-	 nop
 	rts
+	 mov.l	r0, @-r15
+
+!
+! 0x600: Interrupt / NMI vector
+!
+	.balign 	512,0,512
+ENTRY(handle_interrupt)
+#if defined(CONFIG_KGDB)
+	mov.l	2f, k2
+	! Debounce (filter nested NMI)
+	mov.l	@k2, k0
+	mov.l	9f, k1
+	cmp/eq	k1, k0
+	bf	11f
+	mov.l	10f, k1
+	tas.b	@k1
+	bt	11f
+	rte
 	 nop
-
 	.align	2
-1:	.long	0x00001000	! DSP=1
-2:	.long	0x000080f0	! FD=1, IMASK=15
-3:	.long	0xcfffffff	! RB=0, BL=0
-4:	.long	exception_handling_table
+9:	.long	NMI_VEC
+10:	.long	in_nmi
+11:
+#endif /* defined(CONFIG_KGDB) */
+	sts	pr, k3		! save original pr value in k3
+	mova	exception_data, k0
 
-interrupt_exception:
-	mov.l	1f, r9
+	! Setup stack and save DSP context (k0 contains original r15 on return)
+	bsr	prepare_stack_save_dsp
+	 PREF(k0)
+
+	! Save registers / Switch to bank 0
+	mov.l	1f, k4		! SR bits to clear in k4
+	bsr	save_regs	! needs original pr value in k3
+	 mov	#-1, k2		! default vector kept in k2
+
+	! Setup return address and jump to do_IRQ
+	mov.l	4f, r9		! fetch return address
+	lds	r9, pr		! put return address in pr
 	mov.l	2f, r4
-	mov.l	@r4, r4
+	mov.l	3f, r9
+	mov.l	@r4, r4		! pass INTEVT vector as arg0
 	jmp	@r9
-	 mov	r15, r5
-	rts
-	 nop
+	 mov	r15, r5		! pass saved registers as arg1
 
-	.align 2
-1:	.long	do_IRQ
-2:	.long	INTEVT
-
-	.align	2
 ENTRY(exception_none)
 	rts
 	 nop
+
+	.align	L1_CACHE_SHIFT
+exception_data:
+0:	.long	0x000080f0	! FD=1, IMASK=15
+1:	.long	0xcfffffff	! RB=0, BL=0
+2:	.long	INTEVT
+3:	.long	do_IRQ
+4:	.long	ret_from_irq
+5:	.long	EXPEVT
+6:	.long	exception_handling_table
+7:	.long	ret_from_exception
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index 6468ae8..63b67ba 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -1,7 +1,7 @@
 /*
  * SH7705 Setup
  *
- *  Copyright (C) 2006, 2007  Paul Mundt
+ *  Copyright (C) 2006 - 2009  Paul Mundt
  *  Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -21,51 +21,36 @@
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
 	PINT07, PINT815,
-	DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3,
-	SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
-	SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
-	ADC_ADI,
-	USB_USI0, USB_USI1,
-	TPU0, TPU1, TPU2, TPU3,
-	TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
-	RTC_ATI, RTC_PRI, RTC_CUI,
-	WDT,
-	REF_RCMI,
 
-	/* interrupt groups */
-	RTC, TMU2, DMAC, USB, SCIF2, SCIF0,
+	DMAC, SCIF0, SCIF2, ADC_ADI, USB,
+
+	TPU0, TPU1, TPU2, TPU3,
+	TMU0, TMU1, TMU2,
+
+	RTC, WDT, REF_RCMI,
 };
 
 static struct intc_vect vectors[] __initdata = {
 	/* IRQ0->5 are handled in setup-sh3.c */
 	INTC_VECT(PINT07, 0x700), INTC_VECT(PINT815, 0x720),
-	INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820),
-	INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860),
-	INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0),
-	INTC_VECT(SCIF0_TXI, 0x8e0),
-	INTC_VECT(SCIF2_ERI, 0x900), INTC_VECT(SCIF2_RXI, 0x920),
-	INTC_VECT(SCIF2_TXI, 0x960),
+	INTC_VECT(DMAC, 0x800), INTC_VECT(DMAC, 0x820),
+	INTC_VECT(DMAC, 0x840), INTC_VECT(DMAC, 0x860),
+	INTC_VECT(SCIF0, 0x880), INTC_VECT(SCIF0, 0x8a0),
+	INTC_VECT(SCIF0, 0x8e0),
+	INTC_VECT(SCIF2, 0x900), INTC_VECT(SCIF2, 0x920),
+	INTC_VECT(SCIF2, 0x960),
 	INTC_VECT(ADC_ADI, 0x980),
-	INTC_VECT(USB_USI0, 0xa20), INTC_VECT(USB_USI1, 0xa40),
+	INTC_VECT(USB, 0xa20), INTC_VECT(USB, 0xa40),
 	INTC_VECT(TPU0, 0xc00), INTC_VECT(TPU1, 0xc20),
 	INTC_VECT(TPU2, 0xc80), INTC_VECT(TPU3, 0xca0),
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
-	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
-	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
-	INTC_VECT(RTC_CUI, 0x4c0),
+	INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
+	INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+	INTC_VECT(RTC, 0x4c0),
 	INTC_VECT(WDT, 0x560),
 	INTC_VECT(REF_RCMI, 0x580),
 };
 
-static struct intc_group groups[] __initdata = {
-	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
-	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
-	INTC_GROUP(DMAC, DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3),
-	INTC_GROUP(USB, USB_USI0, USB_USI1),
-	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
-	INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
-};
-
 static struct intc_prio_reg prio_registers[] __initdata = {
 	{ 0xfffffee2, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
 	{ 0xfffffee4, 0, 16, 4, /* IPRB */ { WDT, REF_RCMI, 0, 0 } },
@@ -78,7 +63,7 @@
 
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, NULL,
 			 NULL, prio_registers, NULL);
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -86,12 +71,12 @@
 		.mapbase	= 0xa4410000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 56, 57, 59 },
+		.irqs		= { 56, 56, 56 },
 	}, {
 		.mapbase	= 0xa4400000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 52, 53, 55 },
+		.irqs		= { 52, 52, 52 },
 	}, {
 		.flags = 0,
 	}
@@ -115,14 +100,6 @@
 		.start  = 20,
 		.flags	= IORESOURCE_IRQ,
 	},
-	[2] =	{
-		.start	= 21,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] =	{
-		.start	= 22,
-		.flags  = IORESOURCE_IRQ,
-	},
 };
 
 static struct sh_rtc_platform_info rtc_info = {
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
index 93c55e2..a74f960 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
@@ -2,6 +2,7 @@
  * SH3 Setup code for SH7706, SH7707, SH7708, SH7709
  *
  *  Copyright (C) 2007  Magnus Damm
+ *  Copyright (C) 2009  Paul Mundt
  *
  * Based on setup-sh7709.c
  *
@@ -24,46 +25,37 @@
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
 	PINT07, PINT815,
-	DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3,
-	SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
-	SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI,
-	SCI_ERI, SCI_RXI, SCI_TXI, SCI_TEI,
-	ADC_ADI,
+	DMAC, SCIF0, SCIF2, SCI, ADC_ADI,
 	LCDC, PCC0, PCC1,
-	TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
-	RTC_ATI, RTC_PRI, RTC_CUI,
-	WDT,
-	REF_RCMI, REF_ROVI,
-
-	/* interrupt groups */
-	RTC, REF, TMU2, DMAC, SCI, SCIF2, SCIF0,
+	TMU0, TMU1, TMU2,
+	RTC, WDT, REF,
 };
 
 static struct intc_vect vectors[] __initdata = {
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
-	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
-	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
-	INTC_VECT(RTC_CUI, 0x4c0),
-	INTC_VECT(SCI_ERI, 0x4e0), INTC_VECT(SCI_RXI, 0x500),
-	INTC_VECT(SCI_TXI, 0x520), INTC_VECT(SCI_TEI, 0x540),
+	INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
+	INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+	INTC_VECT(RTC, 0x4c0),
+	INTC_VECT(SCI, 0x4e0), INTC_VECT(SCI, 0x500),
+	INTC_VECT(SCI, 0x520), INTC_VECT(SCI, 0x540),
 	INTC_VECT(WDT, 0x560),
-	INTC_VECT(REF_RCMI, 0x580),
-	INTC_VECT(REF_ROVI, 0x5a0),
+	INTC_VECT(REF, 0x580),
+	INTC_VECT(REF, 0x5a0),
 #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
     defined(CONFIG_CPU_SUBTYPE_SH7707) || \
     defined(CONFIG_CPU_SUBTYPE_SH7709)
 	/* IRQ0->5 are handled in setup-sh3.c */
-	INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820),
-	INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860),
+	INTC_VECT(DMAC, 0x800), INTC_VECT(DMAC, 0x820),
+	INTC_VECT(DMAC, 0x840), INTC_VECT(DMAC, 0x860),
 	INTC_VECT(ADC_ADI, 0x980),
-	INTC_VECT(SCIF2_ERI, 0x900), INTC_VECT(SCIF2_RXI, 0x920),
-	INTC_VECT(SCIF2_BRI, 0x940), INTC_VECT(SCIF2_TXI, 0x960),
+	INTC_VECT(SCIF2, 0x900), INTC_VECT(SCIF2, 0x920),
+	INTC_VECT(SCIF2, 0x940), INTC_VECT(SCIF2, 0x960),
 #endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
     defined(CONFIG_CPU_SUBTYPE_SH7709)
 	INTC_VECT(PINT07, 0x700), INTC_VECT(PINT815, 0x720),
-	INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0),
-	INTC_VECT(SCIF0_BRI, 0x8c0), INTC_VECT(SCIF0_TXI, 0x8e0),
+	INTC_VECT(SCIF0, 0x880), INTC_VECT(SCIF0, 0x8a0),
+	INTC_VECT(SCIF0, 0x8c0), INTC_VECT(SCIF0, 0x8e0),
 #endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7707)
 	INTC_VECT(LCDC, 0x9a0),
@@ -71,16 +63,6 @@
 #endif
 };
 
-static struct intc_group groups[] __initdata = {
-	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
-	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
-	INTC_GROUP(REF, REF_RCMI, REF_ROVI),
-	INTC_GROUP(DMAC, DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3),
-	INTC_GROUP(SCI, SCI_ERI, SCI_RXI, SCI_TXI, SCI_TEI),
-	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
-	INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
-};
-
 static struct intc_prio_reg prio_registers[] __initdata = {
 	{ 0xfffffee2, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
 	{ 0xfffffee4, 0, 16, 4, /* IPRB */ { WDT, REF, SCI, 0 } },
@@ -101,7 +83,7 @@
 #endif
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh770x", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh770x", vectors, NULL,
 			 NULL, prio_registers, NULL);
 
 static struct resource rtc_resources[] = {
@@ -111,14 +93,6 @@
 		.flags  = IORESOURCE_IO,
 	},
 	[1] =	{
-		.start  = 21,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] =	{
-		.start	= 22,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] =	{
 		.start	= 20,
 		.flags  = IORESOURCE_IRQ,
 	},
@@ -136,7 +110,7 @@
 		.mapbase	= 0xfffffe80,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCI,
-		.irqs		= { 23, 24, 25, 0 },
+		.irqs		= { 23, 23, 23, 0 },
 	},
 #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
     defined(CONFIG_CPU_SUBTYPE_SH7707) || \
@@ -145,7 +119,7 @@
 		.mapbase	= 0xa4000150,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 56, 57, 59, 58 },
+		.irqs		= { 56, 56, 56, 56 },
 	},
 #endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
@@ -154,7 +128,7 @@
 		.mapbase	= 0xa4000140,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_IRDA,
-		.irqs		= { 52, 53, 55, 54 },
+		.irqs		= { 52, 52, 52, 52 },
 	},
 #endif
 	{
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index 77eee48..335098b 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -1,7 +1,7 @@
 /*
  * SH3 Setup code for SH7710, SH7712
  *
- *  Copyright (C) 2006, 2007  Paul Mundt
+ *  Copyright (C) 2006 - 2009  Paul Mundt
  *  Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -20,59 +20,40 @@
 
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
-	DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3,
-	SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
-	SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
-	DMAC_DEI4, DMAC_DEI5,
-	IPSEC,
+	DMAC1, SCIF0, SCIF1, DMAC2, IPSEC,
 	EDMAC0, EDMAC1, EDMAC2,
-	SIOF0_ERI, SIOF0_TXI, SIOF0_RXI, SIOF0_CCI,
-	SIOF1_ERI, SIOF1_TXI, SIOF1_RXI, SIOF1_CCI,
-	TMU0, TMU1, TMU2,
-	RTC_ATI, RTC_PRI, RTC_CUI,
-	WDT,
-	REF,
+	SIOF0, SIOF1,
 
-	/* interrupt groups */
-	RTC, DMAC1, SCIF0, SCIF1, DMAC2, SIOF0, SIOF1,
+	TMU0, TMU1, TMU2,
+	RTC, WDT, REF,
 };
 
 static struct intc_vect vectors[] __initdata = {
 	/* IRQ0->5 are handled in setup-sh3.c */
-	INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820),
-	INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860),
-	INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0),
-	INTC_VECT(SCIF0_BRI, 0x8c0), INTC_VECT(SCIF0_TXI, 0x8e0),
-	INTC_VECT(SCIF1_ERI, 0x900), INTC_VECT(SCIF1_RXI, 0x920),
-	INTC_VECT(SCIF1_BRI, 0x940), INTC_VECT(SCIF1_TXI, 0x960),
-	INTC_VECT(DMAC_DEI4, 0xb80), INTC_VECT(DMAC_DEI5, 0xba0),
+	INTC_VECT(DMAC1, 0x800), INTC_VECT(DMAC1, 0x820),
+	INTC_VECT(DMAC1, 0x840), INTC_VECT(DMAC1, 0x860),
+	INTC_VECT(SCIF0, 0x880), INTC_VECT(SCIF0, 0x8a0),
+	INTC_VECT(SCIF0, 0x8c0), INTC_VECT(SCIF0, 0x8e0),
+	INTC_VECT(SCIF1, 0x900), INTC_VECT(SCIF1, 0x920),
+	INTC_VECT(SCIF1, 0x940), INTC_VECT(SCIF1, 0x960),
+	INTC_VECT(DMAC2, 0xb80), INTC_VECT(DMAC2, 0xba0),
 #ifdef CONFIG_CPU_SUBTYPE_SH7710
 	INTC_VECT(IPSEC, 0xbe0),
 #endif
 	INTC_VECT(EDMAC0, 0xc00), INTC_VECT(EDMAC1, 0xc20),
 	INTC_VECT(EDMAC2, 0xc40),
-	INTC_VECT(SIOF0_ERI, 0xe00), INTC_VECT(SIOF0_TXI, 0xe20),
-	INTC_VECT(SIOF0_RXI, 0xe40), INTC_VECT(SIOF0_CCI, 0xe60),
-	INTC_VECT(SIOF1_ERI, 0xe80), INTC_VECT(SIOF1_TXI, 0xea0),
-	INTC_VECT(SIOF1_RXI, 0xec0), INTC_VECT(SIOF1_CCI, 0xee0),
+	INTC_VECT(SIOF0, 0xe00), INTC_VECT(SIOF0, 0xe20),
+	INTC_VECT(SIOF0, 0xe40), INTC_VECT(SIOF0, 0xe60),
+	INTC_VECT(SIOF1, 0xe80), INTC_VECT(SIOF1, 0xea0),
+	INTC_VECT(SIOF1, 0xec0), INTC_VECT(SIOF1, 0xee0),
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
 	INTC_VECT(TMU2, 0x440),
-	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
-	INTC_VECT(RTC_CUI, 0x4c0),
+	INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+	INTC_VECT(RTC, 0x4c0),
 	INTC_VECT(WDT, 0x560),
 	INTC_VECT(REF, 0x580),
 };
 
-static struct intc_group groups[] __initdata = {
-	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
-	INTC_GROUP(DMAC1, DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3),
-	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
-	INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
-	INTC_GROUP(DMAC2, DMAC_DEI4, DMAC_DEI5),
-	INTC_GROUP(SIOF0, SIOF0_ERI, SIOF0_TXI, SIOF0_RXI, SIOF0_CCI),
-	INTC_GROUP(SIOF1, SIOF1_ERI, SIOF1_TXI, SIOF1_RXI, SIOF1_CCI),
-};
-
 static struct intc_prio_reg prio_registers[] __initdata = {
 	{ 0xfffffee2, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
 	{ 0xfffffee4, 0, 16, 4, /* IPRB */ { WDT, REF, 0, 0 } },
@@ -85,7 +66,7 @@
 	{ 0xa4080006, 0, 16, 4, /* IPRI */ { 0, 0, SIOF1 } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7710", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7710", vectors, NULL,
 			 NULL, prio_registers, NULL);
 
 static struct resource rtc_resources[] = {
@@ -98,14 +79,6 @@
 		.start  = 20,
 		.flags	= IORESOURCE_IRQ,
 	},
-	[2] =	{
-		.start	= 21,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] =	{
-		.start	= 22,
-		.flags  = IORESOURCE_IRQ,
-	},
 };
 
 static struct sh_rtc_platform_info rtc_info = {
@@ -127,12 +100,12 @@
 		.mapbase	= 0xa4400000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 52, 53, 55, 54 },
+		.irqs		= { 52, 52, 52, 52 },
 	}, {
 		.mapbase	= 0xa4410000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs           = { 56, 57, 59, 58 },
+		.irqs           = { 56, 56, 56, 56 },
 	}, {
 
 		.flags = 0,
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
index f807a21..003874a 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
@@ -2,6 +2,7 @@
  * SH7720 Setup
  *
  *  Copyright (C) 2007  Markus Brunner, Mark Jonas
+ *  Copyright (C) 2009  Paul Mundt
  *
  *  Based on arch/sh/kernel/cpu/sh4/setup-sh7750.c:
  *
@@ -26,17 +27,7 @@
 		.flags	= IORESOURCE_IO,
 	},
 	[1] = {
-		/* Period IRQ */
-		.start	= 21,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		/* Carry IRQ */
-		.start	= 22,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		/* Alarm IRQ */
+		/* Shared Period/Carry/Alarm IRQ */
 		.start	= 20,
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -150,62 +141,49 @@
 	UNUSED = 0,
 
 	/* interrupt sources */
-	TMU0, TMU1, TMU2, RTC_ATI, RTC_PRI, RTC_CUI,
-	WDT, REF_RCMI, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEND,
+	TMU0, TMU1, TMU2, RTC,
+	WDT, REF_RCMI, SIM,
 	IRQ0, IRQ1, IRQ2, IRQ3,
 	USBF_SPD, TMU_SUNI, IRQ5, IRQ4,
-	DMAC1_DEI0, DMAC1_DEI1, DMAC1_DEI2, DMAC1_DEI3, LCDC, SSL,
-	ADC, DMAC2_DEI4, DMAC2_DEI5, USBFI0, USBFI1, CMT,
+	DMAC1, LCDC, SSL,
+	ADC, DMAC2, USBFI, CMT,
 	SCIF0, SCIF1,
-	PINT07, PINT815, TPU0, TPU1, TPU2, TPU3, IIC,
-	SIOF0, SIOF1, MMCI0, MMCI1, MMCI2, MMCI3, PCC,
+	PINT07, PINT815, TPU, IIC,
+	SIOF0, SIOF1, MMC, PCC,
 	USBHI, AFEIF,
 	H_UDI,
-	/* interrupt groups */
-	TMU, RTC, SIM, DMAC1, USBFI, DMAC2, USB, TPU, MMC,
 };
 
 static struct intc_vect vectors[] __initdata = {
 	/* IRQ0->5 are handled in setup-sh3.c */
 	INTC_VECT(TMU0, 0x400),       INTC_VECT(TMU1, 0x420),
-	INTC_VECT(TMU2, 0x440),       INTC_VECT(RTC_ATI, 0x480),
-	INTC_VECT(RTC_PRI, 0x4a0),    INTC_VECT(RTC_CUI, 0x4c0),
-	INTC_VECT(SIM_ERI, 0x4e0),    INTC_VECT(SIM_RXI, 0x500),
-	INTC_VECT(SIM_TXI, 0x520),    INTC_VECT(SIM_TEND, 0x540),
+	INTC_VECT(TMU2, 0x440),       INTC_VECT(RTC, 0x480),
+	INTC_VECT(RTC, 0x4a0),	      INTC_VECT(RTC, 0x4c0),
+	INTC_VECT(SIM, 0x4e0),	      INTC_VECT(SIM, 0x500),
+	INTC_VECT(SIM, 0x520),	      INTC_VECT(SIM, 0x540),
 	INTC_VECT(WDT, 0x560),        INTC_VECT(REF_RCMI, 0x580),
 	/* H_UDI cannot be masked */  INTC_VECT(TMU_SUNI, 0x6c0),
-	INTC_VECT(USBF_SPD, 0x6e0),   INTC_VECT(DMAC1_DEI0, 0x800),
-	INTC_VECT(DMAC1_DEI1, 0x820), INTC_VECT(DMAC1_DEI2, 0x840),
-	INTC_VECT(DMAC1_DEI3, 0x860), INTC_VECT(LCDC, 0x900),
+	INTC_VECT(USBF_SPD, 0x6e0),   INTC_VECT(DMAC1, 0x800),
+	INTC_VECT(DMAC1, 0x820),      INTC_VECT(DMAC1, 0x840),
+	INTC_VECT(DMAC1, 0x860),      INTC_VECT(LCDC, 0x900),
 #if defined(CONFIG_CPU_SUBTYPE_SH7720)
 	INTC_VECT(SSL, 0x980),
 #endif
-	INTC_VECT(USBFI0, 0xa20),     INTC_VECT(USBFI1, 0xa40),
+	INTC_VECT(USBFI, 0xa20),      INTC_VECT(USBFI, 0xa40),
 	INTC_VECT(USBHI, 0xa60),
-	INTC_VECT(DMAC2_DEI4, 0xb80), INTC_VECT(DMAC2_DEI5, 0xba0),
+	INTC_VECT(DMAC2, 0xb80),      INTC_VECT(DMAC2, 0xba0),
 	INTC_VECT(ADC, 0xbe0),        INTC_VECT(SCIF0, 0xc00),
 	INTC_VECT(SCIF1, 0xc20),      INTC_VECT(PINT07, 0xc80),
 	INTC_VECT(PINT815, 0xca0),    INTC_VECT(SIOF0, 0xd00),
-	INTC_VECT(SIOF1, 0xd20),      INTC_VECT(TPU0, 0xd80),
-	INTC_VECT(TPU1, 0xda0),       INTC_VECT(TPU2, 0xdc0),
-	INTC_VECT(TPU3, 0xde0),       INTC_VECT(IIC, 0xe00),
-	INTC_VECT(MMCI0, 0xe80),      INTC_VECT(MMCI1, 0xea0),
-	INTC_VECT(MMCI2, 0xec0),      INTC_VECT(MMCI3, 0xee0),
+	INTC_VECT(SIOF1, 0xd20),      INTC_VECT(TPU, 0xd80),
+	INTC_VECT(TPU, 0xda0),        INTC_VECT(TPU, 0xdc0),
+	INTC_VECT(TPU, 0xde0),        INTC_VECT(IIC, 0xe00),
+	INTC_VECT(MMC, 0xe80),        INTC_VECT(MMC, 0xea0),
+	INTC_VECT(MMC, 0xec0),        INTC_VECT(MMC, 0xee0),
 	INTC_VECT(CMT, 0xf00),        INTC_VECT(PCC, 0xf60),
 	INTC_VECT(AFEIF, 0xfe0),
 };
 
-static struct intc_group groups[] __initdata = {
-	INTC_GROUP(TMU, TMU0, TMU1, TMU2),
-	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
-	INTC_GROUP(SIM, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEND),
-	INTC_GROUP(DMAC1, DMAC1_DEI0, DMAC1_DEI1, DMAC1_DEI2, DMAC1_DEI3),
-	INTC_GROUP(USBFI, USBFI0, USBFI1),
-	INTC_GROUP(DMAC2, DMAC2_DEI4, DMAC2_DEI5),
-	INTC_GROUP(TPU, TPU0, TPU1, TPU2, TPU3),
-	INTC_GROUP(MMC, MMCI0, MMCI1, MMCI2, MMCI3),
-};
-
 static struct intc_prio_reg prio_registers[] __initdata = {
 	{ 0xA414FEE2UL, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
 	{ 0xA414FEE4UL, 0, 16, 4, /* IPRB */ { WDT, REF_RCMI, SIM, 0 } },
@@ -219,7 +197,7 @@
 	{ 0xA4080008UL, 0, 16, 4, /* IPRJ */ { 0, USBHI, 0, AFEIF } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7720", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7720", vectors, NULL,
 		NULL, prio_registers, NULL);
 
 void __init plat_irq_setup(void)
diff --git a/arch/sh/kernel/cpu/sh3/swsusp.S b/arch/sh/kernel/cpu/sh3/swsusp.S
new file mode 100644
index 0000000..0114542
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/swsusp.S
@@ -0,0 +1,147 @@
+/*
+ * arch/sh/kernel/cpu/sh3/swsusp.S
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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/sys.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+
+#define k0	r0
+#define k1	r1
+#define k2	r2
+#define k3	r3
+#define k4	r4
+
+! swsusp_arch_resume()
+! - copy restore_pblist pages
+! - restore registers from swsusp_arch_regs_cpu0
+
+ENTRY(swsusp_arch_resume)
+	mov.l	1f, r15
+	mov.l	2f, r4
+	mov.l	@r4, r4
+
+swsusp_copy_loop:
+	mov	r4, r0
+	cmp/eq	#0, r0
+	bt	swsusp_restore_regs
+
+	mov.l	@(PBE_ADDRESS, r4), r2
+	mov.l	@(PBE_ORIG_ADDRESS, r4), r5
+
+	mov	#(PAGE_SIZE >> 10), r3
+	shll8	r3
+	shlr2	r3 /* PAGE_SIZE / 16 */
+swsusp_copy_page:
+	dt	r3
+	mov.l	@r2+,r1   /*  16n+0 */
+	mov.l	r1,@r5
+	add	#4,r5
+	mov.l	@r2+,r1	  /*  16n+4 */
+	mov.l	r1,@r5
+	add	#4,r5
+	mov.l	@r2+,r1   /*  16n+8 */
+	mov.l	r1,@r5
+	add	#4,r5
+	mov.l	@r2+,r1   /*  16n+12 */
+	mov.l	r1,@r5
+	bf/s	swsusp_copy_page
+	 add	#4,r5
+
+	bra	swsusp_copy_loop
+	 mov.l	@(PBE_NEXT, r4), r4
+
+swsusp_restore_regs:
+	! BL=0: R7->R0 is bank0
+	mov.l	3f, r8
+	mov.l	4f, r5
+	jsr	@r5
+	 nop
+
+	! BL=1: R7->R0 is bank1
+	lds	k2, pr
+	ldc	k3, ssr
+
+	mov.l	@r15+, r0
+	mov.l	@r15+, r1
+	mov.l	@r15+, r2
+	mov.l	@r15+, r3
+	mov.l	@r15+, r4
+	mov.l	@r15+, r5
+	mov.l	@r15+, r6
+	mov.l	@r15+, r7
+
+	rte
+	 nop
+	! BL=0: R7->R0 is bank0
+
+	.align	2
+1:	.long	swsusp_arch_regs_cpu0
+2:	.long	restore_pblist
+3:	.long	0x20000000 ! RB=1
+4:	.long	restore_regs
+
+! swsusp_arch_suspend()
+! - prepare pc for resume, return from function without swsusp_save on resume
+! - save registers in swsusp_arch_regs_cpu0
+! - call swsusp_save write suspend image
+
+ENTRY(swsusp_arch_suspend)
+	sts	pr, r0		! save pr in r0
+	mov	r15, r2		! save sp in r2
+	mov	r8, r5		! save r8 in r5
+	stc	sr, r1
+	ldc	r1, ssr		! save sr in ssr
+	mov.l	1f, r1
+	ldc	r1, spc		! setup pc value for resuming
+	mov.l	5f, r15		! use swsusp_arch_regs_cpu0 as stack
+	mov.l	6f, r3
+	add	r3, r15		! save from top of structure
+
+	! BL=0: R7->R0 is bank0
+	mov.l	2f, r3		! get new SR value for bank1
+	mov	#0, r4
+	mov.l	7f, r1
+	jsr	@r1		! switch to bank1 and save bank1 r7->r0
+	 not	r4, r4
+
+	! BL=1: R7->R0 is bank1
+	stc	r2_bank, k0	! fetch old sp from r2_bank0
+	mov.l	3f, k4		! SR bits to clear in k4
+	mov.l	8f, k1
+	jsr	@k1		! switch to bank0 and save all regs
+	 stc	r0_bank, k3	! fetch old pr from r0_bank0
+
+	! BL=0: R7->R0 is bank0
+	mov	r2, r15		! restore old sp
+	mov	r5, r8		! restore old r8
+	stc	ssr, r1
+	ldc	r1, sr		! restore old sr
+	lds	r0, pr		! restore old pr
+	mov.l	4f, r0
+	jmp	@r0
+	 nop
+
+swsusp_call_save:
+	mov	r2, r15		! restore old sp
+	mov	r5, r8		! restore old r8
+	lds	r0, pr		! restore old pr
+	rts
+	 mov	#0, r0
+
+	.align	2
+1:	.long	swsusp_call_save
+2:	.long	0x20000000 ! RB=1
+3:	.long	0xdfffffff ! RB=0
+4:	.long	swsusp_save
+5:	.long	swsusp_arch_regs_cpu0
+6:	.long	SWSUSP_ARCH_REGS_SIZE
+7:	.long	save_low_regs
+8:	.long	save_regs
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index d608557..203b183 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -5,6 +5,7 @@
 obj-y	:= probe.o common.o
 common-y	+= $(addprefix ../sh3/, entry.o ex.o)
 
+obj-$(CONFIG_HIBERNATION)		+= $(addprefix ../sh3/, swsusp.o)
 obj-$(CONFIG_SH_FPU)			+= fpu.o softfloat.o
 obj-$(CONFIG_SH_STORE_QUEUES)		+= sq.o
 
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 2e42572..3d3a3c4 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -129,6 +129,13 @@
 		boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
 					  CPU_HAS_LLSC;
 		break;
+	case 0x4004:
+		boot_cpu_data.type = CPU_SH7786;
+		boot_cpu_data.icache.ways = 4;
+		boot_cpu_data.dcache.ways = 4;
+		boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+			CPU_HAS_LLSC | CPU_HAS_PTEAEX;
+		break;
 	case 0x3008:
 		boot_cpu_data.icache.ways = 4;
 		boot_cpu_data.dcache.ways = 4;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index ec88403..a1c80d9 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -21,17 +21,7 @@
 		.flags	= IORESOURCE_IO,
 	},
 	[1] = {
-		/* Period IRQ */
-		.start	= 21,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		/* Carry IRQ */
-		.start	= 22,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		/* Alarm IRQ */
+		/* Shared Period/Carry/Alarm IRQ */
 		.start	= 20,
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -50,13 +40,13 @@
 		.mapbase	= 0xffe00000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCI,
-		.irqs		= { 23, 24, 25, 0 },
+		.irqs		= { 23, 23, 23, 0 },
 	}, {
 #endif
 		.mapbase	= 0xffe80000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 40, 41, 43, 42 },
+		.irqs		= { 40, 40, 40, 40 },
 	}, {
 		.flags = 0,
 	}
@@ -87,43 +77,27 @@
 
 	/* interrupt sources */
 	IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
-	HUDI, GPIOI,
-	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
-	DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
-	DMAC_DMAE,
+	HUDI, GPIOI, DMAC,
 	PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
 	PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
-	TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
-	RTC_ATI, RTC_PRI, RTC_CUI,
-	SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
-	SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
-	WDT,
-	REF_RCMI, REF_ROVI,
+	TMU3, TMU4, TMU0, TMU1, TMU2, RTC, SCI1, SCIF, WDT, REF,
 
 	/* interrupt groups */
-	DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
+	PCIC1,
 };
 
 static struct intc_vect vectors[] __initdata = {
 	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
-	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
-	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
-	INTC_VECT(RTC_CUI, 0x4c0),
-	INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
-	INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
-	INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
-	INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
+	INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
+	INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+	INTC_VECT(RTC, 0x4c0),
+	INTC_VECT(SCI1, 0x4e0), INTC_VECT(SCI1, 0x500),
+	INTC_VECT(SCI1, 0x520), INTC_VECT(SCI1, 0x540),
+	INTC_VECT(SCIF, 0x700), INTC_VECT(SCIF, 0x720),
+	INTC_VECT(SCIF, 0x740), INTC_VECT(SCIF, 0x760),
 	INTC_VECT(WDT, 0x560),
-	INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
-};
-
-static struct intc_group groups[] __initdata = {
-	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
-	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
-	INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
-	INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
-	INTC_GROUP(REF, REF_RCMI, REF_ROVI),
+	INTC_VECT(REF, 0x580), INTC_VECT(REF, 0x5a0),
 };
 
 static struct intc_prio_reg prio_registers[] __initdata = {
@@ -136,7 +110,7 @@
 						 PCIC1, PCIC0_PCISERR } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7750", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7750", vectors, NULL,
 			 NULL, prio_registers, NULL);
 
 /* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
@@ -145,39 +119,28 @@
 	defined(CONFIG_CPU_SUBTYPE_SH7751) || \
 	defined(CONFIG_CPU_SUBTYPE_SH7091)
 static struct intc_vect vectors_dma4[] __initdata = {
-	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
-	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
-	INTC_VECT(DMAC_DMAE, 0x6c0),
-};
-
-static struct intc_group groups_dma4[] __initdata = {
-	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
-		   DMAC_DMTE3, DMAC_DMAE),
+	INTC_VECT(DMAC, 0x640), INTC_VECT(DMAC, 0x660),
+	INTC_VECT(DMAC, 0x680), INTC_VECT(DMAC, 0x6a0),
+	INTC_VECT(DMAC, 0x6c0),
 };
 
 static DECLARE_INTC_DESC(intc_desc_dma4, "sh7750_dma4",
-			 vectors_dma4, groups_dma4,
+			 vectors_dma4, NULL,
 			 NULL, prio_registers, NULL);
 #endif
 
 /* SH7750R and SH7751R both have 8-channel DMA controllers */
 #if defined(CONFIG_CPU_SUBTYPE_SH7750R) || defined(CONFIG_CPU_SUBTYPE_SH7751R)
 static struct intc_vect vectors_dma8[] __initdata = {
-	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
-	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
-	INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
-	INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
-	INTC_VECT(DMAC_DMAE, 0x6c0),
-};
-
-static struct intc_group groups_dma8[] __initdata = {
-	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
-		   DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
-		   DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
+	INTC_VECT(DMAC, 0x640), INTC_VECT(DMAC, 0x660),
+	INTC_VECT(DMAC, 0x680), INTC_VECT(DMAC, 0x6a0),
+	INTC_VECT(DMAC, 0x780), INTC_VECT(DMAC, 0x7a0),
+	INTC_VECT(DMAC, 0x7c0), INTC_VECT(DMAC, 0x7e0),
+	INTC_VECT(DMAC, 0x6c0),
 };
 
 static DECLARE_INTC_DESC(intc_desc_dma8, "sh7750_dma8",
-			 vectors_dma8, groups_dma8,
+			 vectors_dma8, NULL,
 			 NULL, prio_registers, NULL);
 #endif
 
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index 8e344ec..1a92361 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_CPU_SUBTYPE_SH7770)	+= setup-sh7770.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7780)	+= setup-sh7780.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7785)	+= setup-sh7785.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7786)	+= setup-sh7786.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
@@ -21,6 +22,7 @@
 clock-$(CONFIG_CPU_SUBTYPE_SH7770)	:= clock-sh7770.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7780)	:= clock-sh7780.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7785)	:= clock-sh7785.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7786)	:= clock-sh7786.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7722.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7722.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7723)	:= clock-sh7722.o
@@ -31,6 +33,7 @@
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7722)	:= pinmux-sh7722.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7723)	:= pinmux-sh7723.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7785)	:= pinmux-sh7785.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7786)	:= pinmux-sh7786.o
 
 obj-y			+= $(clock-y)
 obj-$(CONFIG_SMP)	+= $(smp-y)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
new file mode 100644
index 0000000..f84a9c1
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
@@ -0,0 +1,148 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7786.c
+ *
+ * SH7786 support for the clock framework
+ *
+ * Copyright (C) 2008, 2009  Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on SH7785
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int ifc_divisors[] = { 1, 2, 4, 1 };
+static int sfc_divisors[] = { 1, 1, 4, 1 };
+static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 1,
+			     24, 32, 1, 1, 1, 1, 1, 1 };
+static int mfc_divisors[] = { 1, 1, 4, 1 };
+static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 16, 1,
+			      24, 32, 1, 48, 1, 1, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+	clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f];
+}
+
+static struct clk_ops sh7786_master_clk_ops = {
+	.init		= master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+	int idx = (ctrl_inl(FRQMR1) & 0x000f);
+	clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7786_module_clk_ops = {
+	.recalc		= module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
+	clk->rate = clk->parent->rate / bfc_divisors[idx];
+}
+
+static struct clk_ops sh7786_bus_clk_ops = {
+	.recalc		= bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003);
+	clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7786_cpu_clk_ops = {
+	.recalc		= cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7786_clk_ops[] = {
+	&sh7786_master_clk_ops,
+	&sh7786_module_clk_ops,
+	&sh7786_bus_clk_ops,
+	&sh7786_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+	if (idx < ARRAY_SIZE(sh7786_clk_ops))
+		*ops = sh7786_clk_ops[idx];
+}
+
+static void shyway_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
+	clk->rate = clk->parent->rate / sfc_divisors[idx];
+}
+
+static struct clk_ops sh7786_shyway_clk_ops = {
+	.recalc		= shyway_clk_recalc,
+};
+
+static struct clk sh7786_shyway_clk = {
+	.name		= "shyway_clk",
+	.flags		= CLK_ALWAYS_ENABLED,
+	.ops		= &sh7786_shyway_clk_ops,
+};
+
+static void ddr_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
+	clk->rate = clk->parent->rate / mfc_divisors[idx];
+}
+
+static struct clk_ops sh7786_ddr_clk_ops = {
+	.recalc		= ddr_clk_recalc,
+};
+
+static struct clk sh7786_ddr_clk = {
+	.name		= "ddr_clk",
+	.flags		= CLK_ALWAYS_ENABLED,
+	.ops		= &sh7786_ddr_clk_ops,
+};
+
+/*
+ * Additional SH7786-specific on-chip clocks that aren't already part of the
+ * clock framework
+ */
+static struct clk *sh7786_onchip_clocks[] = {
+	&sh7786_shyway_clk,
+	&sh7786_ddr_clk,
+};
+
+static int __init sh7786_clk_init(void)
+{
+	struct clk *clk = clk_get(NULL, "master_clk");
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sh7786_onchip_clocks); i++) {
+		struct clk *clkp = sh7786_onchip_clocks[i];
+
+		clkp->parent = clk;
+		clk_register(clkp);
+		clk_enable(clkp);
+	}
+
+	/*
+	 * Now that we have the rest of the clocks registered, we need to
+	 * force the parent clock to propagate so that these clocks will
+	 * automatically figure out their rate. We cheat by handing the
+	 * parent clock its current rate and forcing child propagation.
+	 */
+	clk_set_rate(clk, clk_get_rate(clk));
+
+	clk_put(clk);
+
+	return 0;
+}
+arch_initcall(sh7786_clk_init);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c
new file mode 100644
index 0000000..373b344
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c
@@ -0,0 +1,950 @@
+/*
+ * SH7786 Pinmux
+ *
+ * Copyright (C) 2008, 2009  Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ *  Based on SH7785 pinmux
+ *
+ *  Copyright (C) 2008  Magnus Damm
+ *
+ * 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/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/sh7786.h>
+
+enum {
+	PINMUX_RESERVED = 0,
+
+	PINMUX_DATA_BEGIN,
+	PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
+	PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
+	PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+	PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA,
+	PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+	PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
+	PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+	PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA,
+	PE7_DATA, PE6_DATA,
+	PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+	PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA,
+	PG7_DATA, PG6_DATA, PG5_DATA,
+	PH7_DATA, PH6_DATA, PH5_DATA, PH4_DATA,
+	PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA,
+	PJ7_DATA, PJ6_DATA, PJ5_DATA, PJ4_DATA,
+	PJ3_DATA, PJ2_DATA, PJ1_DATA,
+	PINMUX_DATA_END,
+
+	PINMUX_INPUT_BEGIN,
+	PA7_IN, PA6_IN, PA5_IN, PA4_IN,
+	PA3_IN, PA2_IN, PA1_IN, PA0_IN,
+	PB7_IN, PB6_IN, PB5_IN, PB4_IN,
+	PB3_IN, PB2_IN, PB1_IN, PB0_IN,
+	PC7_IN, PC6_IN, PC5_IN, PC4_IN,
+	PC3_IN, PC2_IN, PC1_IN, PC0_IN,
+	PD7_IN, PD6_IN, PD5_IN, PD4_IN,
+	PD3_IN, PD2_IN, PD1_IN, PD0_IN,
+	PE7_IN, PE6_IN,
+	PF7_IN, PF6_IN, PF5_IN, PF4_IN,
+	PF3_IN, PF2_IN, PF1_IN, PF0_IN,
+	PG7_IN, PG6_IN, PG5_IN,
+	PH7_IN, PH6_IN, PH5_IN, PH4_IN,
+	PH3_IN, PH2_IN, PH1_IN, PH0_IN,
+	PJ7_IN, PJ6_IN, PJ5_IN, PJ4_IN,
+	PJ3_IN, PJ2_IN, PJ1_IN,
+	PINMUX_INPUT_END,
+
+	PINMUX_INPUT_PULLUP_BEGIN,
+	PA7_IN_PU, PA6_IN_PU, PA5_IN_PU, PA4_IN_PU,
+	PA3_IN_PU, PA2_IN_PU, PA1_IN_PU, PA0_IN_PU,
+	PB7_IN_PU, PB6_IN_PU, PB5_IN_PU, PB4_IN_PU,
+	PB3_IN_PU, PB2_IN_PU, PB1_IN_PU, PB0_IN_PU,
+	PC7_IN_PU, PC6_IN_PU, PC5_IN_PU, PC4_IN_PU,
+	PC3_IN_PU, PC2_IN_PU, PC1_IN_PU, PC0_IN_PU,
+	PD7_IN_PU, PD6_IN_PU, PD5_IN_PU, PD4_IN_PU,
+	PD3_IN_PU, PD2_IN_PU, PD1_IN_PU, PD0_IN_PU,
+	PE7_IN_PU, PE6_IN_PU,
+	PF7_IN_PU, PF6_IN_PU, PF5_IN_PU, PF4_IN_PU,
+	PF3_IN_PU, PF2_IN_PU, PF1_IN_PU, PF0_IN_PU,
+	PG7_IN_PU, PG6_IN_PU, PG5_IN_PU,
+	PH7_IN_PU, PH6_IN_PU, PH5_IN_PU, PH4_IN_PU,
+	PH3_IN_PU, PH2_IN_PU, PH1_IN_PU, PH0_IN_PU,
+	PJ7_IN_PU, PJ6_IN_PU, PJ5_IN_PU, PJ4_IN_PU,
+	PJ3_IN_PU, PJ2_IN_PU, PJ1_IN_PU,
+	PINMUX_INPUT_PULLUP_END,
+
+	PINMUX_OUTPUT_BEGIN,
+	PA7_OUT, PA6_OUT, PA5_OUT, PA4_OUT,
+	PA3_OUT, PA2_OUT, PA1_OUT, PA0_OUT,
+	PB7_OUT, PB6_OUT, PB5_OUT, PB4_OUT,
+	PB3_OUT, PB2_OUT, PB1_OUT, PB0_OUT,
+	PC7_OUT, PC6_OUT, PC5_OUT, PC4_OUT,
+	PC3_OUT, PC2_OUT, PC1_OUT, PC0_OUT,
+	PD7_OUT, PD6_OUT, PD5_OUT, PD4_OUT,
+	PD3_OUT, PD2_OUT, PD1_OUT, PD0_OUT,
+	PE7_OUT, PE6_OUT,
+	PF7_OUT, PF6_OUT, PF5_OUT, PF4_OUT,
+	PF3_OUT, PF2_OUT, PF1_OUT, PF0_OUT,
+	PG7_OUT, PG6_OUT, PG5_OUT,
+	PH7_OUT, PH6_OUT, PH5_OUT, PH4_OUT,
+	PH3_OUT, PH2_OUT, PH1_OUT, PH0_OUT,
+	PJ7_OUT, PJ6_OUT, PJ5_OUT, PJ4_OUT,
+	PJ3_OUT, PJ2_OUT, PJ1_OUT,
+	PINMUX_OUTPUT_END,
+
+	PINMUX_FUNCTION_BEGIN,
+	PA7_FN, PA6_FN, PA5_FN, PA4_FN,
+	PA3_FN, PA2_FN, PA1_FN, PA0_FN,
+	PB7_FN, PB6_FN, PB5_FN, PB4_FN,
+	PB3_FN, PB2_FN, PB1_FN, PB0_FN,
+	PC7_FN, PC6_FN, PC5_FN, PC4_FN,
+	PC3_FN, PC2_FN, PC1_FN, PC0_FN,
+	PD7_FN, PD6_FN, PD5_FN, PD4_FN,
+	PD3_FN, PD2_FN, PD1_FN, PD0_FN,
+	PE7_FN, PE6_FN,
+	PF7_FN, PF6_FN, PF5_FN, PF4_FN,
+	PF3_FN, PF2_FN, PF1_FN, PF0_FN,
+	PG7_FN, PG6_FN, PG5_FN,
+	PH7_FN, PH6_FN, PH5_FN, PH4_FN,
+	PH3_FN, PH2_FN, PH1_FN, PH0_FN,
+	PJ7_FN, PJ6_FN, PJ5_FN, PJ4_FN,
+	PJ3_FN, PJ2_FN, PJ1_FN,
+	P1MSEL14_0, P1MSEL14_1,
+	P1MSEL13_0, P1MSEL13_1,
+	P1MSEL12_0, P1MSEL12_1,
+	P1MSEL11_0, P1MSEL11_1,
+	P1MSEL10_0, P1MSEL10_1,
+	P1MSEL9_0, P1MSEL9_1,
+	P1MSEL8_0, P1MSEL8_1,
+	P1MSEL7_0, P1MSEL7_1,
+	P1MSEL6_0, P1MSEL6_1,
+	P1MSEL5_0, P1MSEL5_1,
+	P1MSEL4_0, P1MSEL4_1,
+	P1MSEL3_0, P1MSEL3_1,
+	P1MSEL2_0, P1MSEL2_1,
+	P1MSEL1_0, P1MSEL1_1,
+	P1MSEL0_0, P1MSEL0_1,
+
+	P2MSEL15_0, P2MSEL15_1,
+	P2MSEL14_0, P2MSEL14_1,
+	P2MSEL13_0, P2MSEL13_1,
+	P2MSEL12_0, P2MSEL12_1,
+	P2MSEL11_0, P2MSEL11_1,
+	P2MSEL10_0, P2MSEL10_1,
+	P2MSEL9_0, P2MSEL9_1,
+	P2MSEL8_0, P2MSEL8_1,
+	P2MSEL7_0, P2MSEL7_1,
+	P2MSEL6_0, P2MSEL6_1,
+	P2MSEL5_0, P2MSEL5_1,
+	P2MSEL4_0, P2MSEL4_1,
+	P2MSEL3_0, P2MSEL3_1,
+	P2MSEL2_0, P2MSEL2_1,
+	P2MSEL1_0, P2MSEL1_1,
+	P2MSEL0_0, P2MSEL0_1,
+	PINMUX_FUNCTION_END,
+
+	PINMUX_MARK_BEGIN,
+	CDE_MARK,
+	ETH_MAGIC_MARK,
+	DISP_MARK,
+	ETH_LINK_MARK,
+	DR5_MARK,
+	ETH_TX_ER_MARK,
+	DR4_MARK,
+	ETH_TX_EN_MARK,
+	DR3_MARK,
+	ETH_TXD3_MARK,
+	DR2_MARK,
+	ETH_TXD2_MARK,
+	DR1_MARK,
+	ETH_TXD1_MARK,
+	DR0_MARK,
+	ETH_TXD0_MARK,
+
+	VSYNC_MARK,
+	HSPI_CLK_MARK,
+	ODDF_MARK,
+	HSPI_CS_MARK,
+	DG5_MARK,
+	ETH_MDIO_MARK,
+	DG4_MARK,
+	ETH_RX_CLK_MARK,
+	DG3_MARK,
+	ETH_MDC_MARK,
+	DG2_MARK,
+	ETH_COL_MARK,
+	DG1_MARK,
+	ETH_TX_CLK_MARK,
+	DG0_MARK,
+	ETH_CRS_MARK,
+
+	DCLKIN_MARK,
+	HSPI_RX_MARK,
+	HSYNC_MARK,
+	HSPI_TX_MARK,
+	DB5_MARK,
+	ETH_RXD3_MARK,
+	DB4_MARK,
+	ETH_RXD2_MARK,
+	DB3_MARK,
+	ETH_RXD1_MARK,
+	DB2_MARK,
+	ETH_RXD0_MARK,
+	DB1_MARK,
+	ETH_RX_DV_MARK,
+	DB0_MARK,
+	ETH_RX_ER_MARK,
+
+	DCLKOUT_MARK,
+	SCIF1_SLK_MARK,
+	SCIF1_RXD_MARK,
+	SCIF1_TXD_MARK,
+	DACK1_MARK,
+	BACK_MARK,
+	FALE_MARK,
+	DACK0_MARK,
+	FCLE_MARK,
+	DREQ1_MARK,
+	BREQ_MARK,
+	USB_OVC1_MARK,
+	DREQ0_MARK,
+	USB_OVC0_MARK,
+
+	USB_PENC1_MARK,
+	USB_PENC0_MARK,
+
+	HAC1_SDOUT_MARK,
+	SSI1_SDATA_MARK,
+	SDIF1CMD_MARK,
+	HAC1_SDIN_MARK,
+	SSI1_SCK_MARK,
+	SDIF1CD_MARK,
+	HAC1_SYNC_MARK,
+	SSI1_WS_MARK,
+	SDIF1WP_MARK,
+	HAC1_BITCLK_MARK,
+	SSI1_CLK_MARK,
+	SDIF1CLK_MARK,
+	HAC0_SDOUT_MARK,
+	SSI0_SDATA_MARK,
+	SDIF1D3_MARK,
+	HAC0_SDIN_MARK,
+	SSI0_SCK_MARK,
+	SDIF1D2_MARK,
+	HAC0_SYNC_MARK,
+	SSI0_WS_MARK,
+	SDIF1D1_MARK,
+	HAC0_BITCLK_MARK,
+	SSI0_CLK_MARK,
+	SDIF1D0_MARK,
+
+	SCIF3_SCK_MARK,
+	SSI2_SDATA_MARK,
+	SCIF3_RXD_MARK,
+	TCLK_MARK,
+	SSI2_SCK_MARK,
+	SCIF3_TXD_MARK,
+	HAC_RES_MARK,
+	SSI2_WS_MARK,
+
+	DACK3_MARK,
+	SDIF0CMD_MARK,
+	DACK2_MARK,
+	SDIF0CD_MARK,
+	DREQ3_MARK,
+	SDIF0WP_MARK,
+	SCIF0_CTS_MARK,
+	DREQ2_MARK,
+	SDIF0CLK_MARK,
+	SCIF0_RTS_MARK,
+	IRL7_MARK,
+	SDIF0D3_MARK,
+	SCIF0_SCK_MARK,
+	IRL6_MARK,
+	SDIF0D2_MARK,
+	SCIF0_RXD_MARK,
+	IRL5_MARK,
+	SDIF0D1_MARK,
+	SCIF0_TXD_MARK,
+	IRL4_MARK,
+	SDIF0D0_MARK,
+
+	SCIF5_SCK_MARK,
+	FRB_MARK,
+	SCIF5_RXD_MARK,
+	IOIS16_MARK,
+	SCIF5_TXD_MARK,
+	CE2B_MARK,
+	DRAK3_MARK,
+	CE2A_MARK,
+	SCIF4_SCK_MARK,
+	DRAK2_MARK,
+	SSI3_WS_MARK,
+	SCIF4_RXD_MARK,
+	DRAK1_MARK,
+	SSI3_SDATA_MARK,
+	FSTATUS_MARK,
+	SCIF4_TXD_MARK,
+	DRAK0_MARK,
+	SSI3_SCK_MARK,
+	FSE_MARK,
+	PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+
+	/* PA GPIO */
+	PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT, PA7_IN_PU),
+	PINMUX_DATA(PA6_DATA, PA6_IN, PA6_OUT, PA6_IN_PU),
+	PINMUX_DATA(PA5_DATA, PA5_IN, PA5_OUT, PA5_IN_PU),
+	PINMUX_DATA(PA4_DATA, PA4_IN, PA4_OUT, PA4_IN_PU),
+	PINMUX_DATA(PA3_DATA, PA3_IN, PA3_OUT, PA3_IN_PU),
+	PINMUX_DATA(PA2_DATA, PA2_IN, PA2_OUT, PA2_IN_PU),
+	PINMUX_DATA(PA1_DATA, PA1_IN, PA1_OUT, PA1_IN_PU),
+	PINMUX_DATA(PA0_DATA, PA0_IN, PA0_OUT, PA0_IN_PU),
+
+	/* PB GPIO */
+	PINMUX_DATA(PB7_DATA, PB7_IN, PB7_OUT, PB7_IN_PU),
+	PINMUX_DATA(PB6_DATA, PB6_IN, PB6_OUT, PB6_IN_PU),
+	PINMUX_DATA(PB5_DATA, PB5_IN, PB5_OUT, PB5_IN_PU),
+	PINMUX_DATA(PB4_DATA, PB4_IN, PB4_OUT, PB4_IN_PU),
+	PINMUX_DATA(PB3_DATA, PB3_IN, PB3_OUT, PB3_IN_PU),
+	PINMUX_DATA(PB2_DATA, PB2_IN, PB2_OUT, PB2_IN_PU),
+	PINMUX_DATA(PB1_DATA, PB1_IN, PB1_OUT, PB1_IN_PU),
+	PINMUX_DATA(PB0_DATA, PB0_IN, PB0_OUT, PB0_IN_PU),
+
+	/* PC GPIO */
+	PINMUX_DATA(PC7_DATA, PC7_IN, PC7_OUT, PC7_IN_PU),
+	PINMUX_DATA(PC6_DATA, PC6_IN, PC6_OUT, PC6_IN_PU),
+	PINMUX_DATA(PC5_DATA, PC5_IN, PC5_OUT, PC5_IN_PU),
+	PINMUX_DATA(PC4_DATA, PC4_IN, PC4_OUT, PC4_IN_PU),
+	PINMUX_DATA(PC3_DATA, PC3_IN, PC3_OUT, PC3_IN_PU),
+	PINMUX_DATA(PC2_DATA, PC2_IN, PC2_OUT, PC2_IN_PU),
+	PINMUX_DATA(PC1_DATA, PC1_IN, PC1_OUT, PC1_IN_PU),
+	PINMUX_DATA(PC0_DATA, PC0_IN, PC0_OUT, PC0_IN_PU),
+
+	/* PD GPIO */
+	PINMUX_DATA(PD7_DATA, PD7_IN, PD7_OUT, PD7_IN_PU),
+	PINMUX_DATA(PD6_DATA, PD6_IN, PD6_OUT, PD6_IN_PU),
+	PINMUX_DATA(PD5_DATA, PD5_IN, PD5_OUT, PD5_IN_PU),
+	PINMUX_DATA(PD4_DATA, PD4_IN, PD4_OUT, PD4_IN_PU),
+	PINMUX_DATA(PD3_DATA, PD3_IN, PD3_OUT, PD3_IN_PU),
+	PINMUX_DATA(PD2_DATA, PD2_IN, PD2_OUT, PD2_IN_PU),
+	PINMUX_DATA(PD1_DATA, PD1_IN, PD1_OUT, PD1_IN_PU),
+	PINMUX_DATA(PD0_DATA, PD0_IN, PD0_OUT, PD0_IN_PU),
+
+	/* PE GPIO */
+	PINMUX_DATA(PE7_DATA, PE7_IN, PE7_OUT, PE7_IN_PU),
+	PINMUX_DATA(PE6_DATA, PE6_IN, PE6_OUT, PE6_IN_PU),
+
+	/* PF GPIO */
+	PINMUX_DATA(PF7_DATA, PF7_IN, PF7_OUT, PF7_IN_PU),
+	PINMUX_DATA(PF6_DATA, PF6_IN, PF6_OUT, PF6_IN_PU),
+	PINMUX_DATA(PF5_DATA, PF5_IN, PF5_OUT, PF5_IN_PU),
+	PINMUX_DATA(PF4_DATA, PF4_IN, PF4_OUT, PF4_IN_PU),
+	PINMUX_DATA(PF3_DATA, PF3_IN, PF3_OUT, PF3_IN_PU),
+	PINMUX_DATA(PF2_DATA, PF2_IN, PF2_OUT, PF2_IN_PU),
+	PINMUX_DATA(PF1_DATA, PF1_IN, PF1_OUT, PF1_IN_PU),
+	PINMUX_DATA(PF0_DATA, PF0_IN, PF0_OUT, PF0_IN_PU),
+
+	/* PG GPIO */
+	PINMUX_DATA(PG7_DATA, PG7_IN, PG7_OUT, PG7_IN_PU),
+	PINMUX_DATA(PG6_DATA, PG6_IN, PG6_OUT, PG6_IN_PU),
+	PINMUX_DATA(PG5_DATA, PG5_IN, PG5_OUT, PG5_IN_PU),
+
+	/* PH GPIO */
+	PINMUX_DATA(PH7_DATA, PH7_IN, PH7_OUT, PH7_IN_PU),
+	PINMUX_DATA(PH6_DATA, PH6_IN, PH6_OUT, PH6_IN_PU),
+	PINMUX_DATA(PH5_DATA, PH5_IN, PH5_OUT, PH5_IN_PU),
+	PINMUX_DATA(PH4_DATA, PH4_IN, PH4_OUT, PH4_IN_PU),
+	PINMUX_DATA(PH3_DATA, PH3_IN, PH3_OUT, PH3_IN_PU),
+	PINMUX_DATA(PH2_DATA, PH2_IN, PH2_OUT, PH2_IN_PU),
+	PINMUX_DATA(PH1_DATA, PH1_IN, PH1_OUT, PH1_IN_PU),
+	PINMUX_DATA(PH0_DATA, PH0_IN, PH0_OUT, PH0_IN_PU),
+
+	/* PJ GPIO */
+	PINMUX_DATA(PJ7_DATA, PJ7_IN, PJ7_OUT, PJ7_IN_PU),
+	PINMUX_DATA(PJ6_DATA, PJ6_IN, PJ6_OUT, PJ6_IN_PU),
+	PINMUX_DATA(PJ5_DATA, PJ5_IN, PJ5_OUT, PJ5_IN_PU),
+	PINMUX_DATA(PJ4_DATA, PJ4_IN, PJ4_OUT, PJ4_IN_PU),
+	PINMUX_DATA(PJ3_DATA, PJ3_IN, PJ3_OUT, PJ3_IN_PU),
+	PINMUX_DATA(PJ2_DATA, PJ2_IN, PJ2_OUT, PJ2_IN_PU),
+	PINMUX_DATA(PJ1_DATA, PJ1_IN, PJ1_OUT, PJ1_IN_PU),
+
+	/* PA FN */
+	PINMUX_MARK_BEGIN,
+	PINMUX_DATA(CDE_MARK,		P1MSEL2_0, PA7_FN),
+	PINMUX_DATA(DISP_MARK,		P1MSEL2_0, PA6_FN),
+	PINMUX_DATA(DR5_MARK,		P1MSEL2_0, PA5_FN),
+	PINMUX_DATA(DR4_MARK,		P1MSEL2_0, PA4_FN),
+	PINMUX_DATA(DR3_MARK,		P1MSEL2_0, PA3_FN),
+	PINMUX_DATA(DR2_MARK,		P1MSEL2_0, PA2_FN),
+	PINMUX_DATA(DR1_MARK,		P1MSEL2_0, PA1_FN),
+	PINMUX_DATA(DR0_MARK,		P1MSEL2_0, PA0_FN),
+	PINMUX_DATA(ETH_MAGIC_MARK,	P1MSEL2_1, PA7_FN),
+	PINMUX_DATA(ETH_LINK_MARK,	P1MSEL2_1, PA6_FN),
+	PINMUX_DATA(ETH_TX_ER_MARK,	P1MSEL2_1, PA5_FN),
+	PINMUX_DATA(ETH_TX_EN_MARK,	P1MSEL2_1, PA4_FN),
+	PINMUX_DATA(ETH_TXD3_MARK,	P1MSEL2_1, PA3_FN),
+	PINMUX_DATA(ETH_TXD2_MARK,	P1MSEL2_1, PA2_FN),
+	PINMUX_DATA(ETH_TXD1_MARK,	P1MSEL2_1, PA1_FN),
+	PINMUX_DATA(ETH_TXD0_MARK,	P1MSEL2_1, PA0_FN),
+
+	/* PB FN */
+	PINMUX_DATA(VSYNC_MARK,		P1MSEL3_0, PB7_FN),
+	PINMUX_DATA(ODDF_MARK,		P1MSEL3_0, PB6_FN),
+	PINMUX_DATA(DG5_MARK,		P1MSEL2_0, PB5_FN),
+	PINMUX_DATA(DG4_MARK,		P1MSEL2_0, PB4_FN),
+	PINMUX_DATA(DG3_MARK,		P1MSEL2_0, PB3_FN),
+	PINMUX_DATA(DG2_MARK,		P1MSEL2_0, PB2_FN),
+	PINMUX_DATA(DG1_MARK,		P1MSEL2_0, PB1_FN),
+	PINMUX_DATA(DG0_MARK,		P1MSEL2_0, PB0_FN),
+	PINMUX_DATA(HSPI_CLK_MARK,	P1MSEL3_1, PB7_FN),
+	PINMUX_DATA(HSPI_CS_MARK,	P1MSEL3_1, PB6_FN),
+	PINMUX_DATA(ETH_MDIO_MARK,	P1MSEL2_1, PB5_FN),
+	PINMUX_DATA(ETH_RX_CLK_MARK,	P1MSEL2_1, PB4_FN),
+	PINMUX_DATA(ETH_MDC_MARK,	P1MSEL2_1, PB3_FN),
+	PINMUX_DATA(ETH_COL_MARK,	P1MSEL2_1, PB2_FN),
+	PINMUX_DATA(ETH_TX_CLK_MARK,	P1MSEL2_1, PB1_FN),
+	PINMUX_DATA(ETH_CRS_MARK,	P1MSEL2_1, PB0_FN),
+
+	/* PC FN */
+	PINMUX_DATA(DCLKIN_MARK,	P1MSEL3_0, PC7_FN),
+	PINMUX_DATA(HSYNC_MARK,		P1MSEL3_0, PC6_FN),
+	PINMUX_DATA(DB5_MARK,		P1MSEL2_0, PC5_FN),
+	PINMUX_DATA(DB4_MARK,		P1MSEL2_0, PC4_FN),
+	PINMUX_DATA(DB3_MARK,		P1MSEL2_0, PC3_FN),
+	PINMUX_DATA(DB2_MARK,		P1MSEL2_0, PC2_FN),
+	PINMUX_DATA(DB1_MARK,		P1MSEL2_0, PC1_FN),
+	PINMUX_DATA(DB0_MARK,		P1MSEL2_0, PC0_FN),
+
+	PINMUX_DATA(HSPI_RX_MARK,	P1MSEL3_1, PC7_FN),
+	PINMUX_DATA(HSPI_TX_MARK,	P1MSEL3_1, PC6_FN),
+	PINMUX_DATA(ETH_RXD3_MARK,	P1MSEL2_1, PC5_FN),
+	PINMUX_DATA(ETH_RXD2_MARK,	P1MSEL2_1, PC4_FN),
+	PINMUX_DATA(ETH_RXD1_MARK,	P1MSEL2_1, PC3_FN),
+	PINMUX_DATA(ETH_RXD0_MARK,	P1MSEL2_1, PC2_FN),
+	PINMUX_DATA(ETH_RX_DV_MARK,	P1MSEL2_1, PC1_FN),
+	PINMUX_DATA(ETH_RX_ER_MARK,	P1MSEL2_1, PC0_FN),
+
+	/* PD FN */
+	PINMUX_DATA(DCLKOUT_MARK,	PD7_FN),
+	PINMUX_DATA(SCIF1_SLK_MARK,	PD6_FN),
+	PINMUX_DATA(SCIF1_RXD_MARK,	PD5_FN),
+	PINMUX_DATA(SCIF1_TXD_MARK,	PD4_FN),
+	PINMUX_DATA(DACK1_MARK,		P1MSEL13_1, P1MSEL12_0, PD3_FN),
+	PINMUX_DATA(BACK_MARK,		P1MSEL13_0, P1MSEL12_1, PD3_FN),
+	PINMUX_DATA(FALE_MARK,		P1MSEL13_0, P1MSEL12_0, PD3_FN),
+	PINMUX_DATA(DACK0_MARK,		P1MSEL14_1, PD2_FN),
+	PINMUX_DATA(FCLE_MARK,		P1MSEL14_0, PD2_FN),
+	PINMUX_DATA(DREQ1_MARK,		P1MSEL10_0, P1MSEL9_1, PD1_FN),
+	PINMUX_DATA(BREQ_MARK,		P1MSEL10_1, P1MSEL9_0, PD1_FN),
+	PINMUX_DATA(USB_OVC1_MARK,	P1MSEL10_0, P1MSEL9_0, PD1_FN),
+	PINMUX_DATA(DREQ0_MARK,		P1MSEL11_1, PD0_FN),
+	PINMUX_DATA(USB_OVC0_MARK,	P1MSEL11_0, PD0_FN),
+
+	/* PE FN */
+	PINMUX_DATA(USB_PENC1_MARK,	PE7_FN),
+	PINMUX_DATA(USB_PENC0_MARK,	PE6_FN),
+
+	/* PF FN */
+	PINMUX_DATA(HAC1_SDOUT_MARK,	P2MSEL15_0, P2MSEL14_0, PF7_FN),
+	PINMUX_DATA(HAC1_SDIN_MARK,	P2MSEL15_0, P2MSEL14_0, PF6_FN),
+	PINMUX_DATA(HAC1_SYNC_MARK,	P2MSEL15_0, P2MSEL14_0, PF5_FN),
+	PINMUX_DATA(HAC1_BITCLK_MARK,	P2MSEL15_0, P2MSEL14_0, PF4_FN),
+	PINMUX_DATA(HAC0_SDOUT_MARK,	P2MSEL13_0, P2MSEL12_0, PF3_FN),
+	PINMUX_DATA(HAC0_SDIN_MARK,	P2MSEL13_0, P2MSEL12_0, PF2_FN),
+	PINMUX_DATA(HAC0_SYNC_MARK,	P2MSEL13_0, P2MSEL12_0, PF1_FN),
+	PINMUX_DATA(HAC0_BITCLK_MARK,	P2MSEL13_0, P2MSEL12_0, PF0_FN),
+	PINMUX_DATA(SSI1_SDATA_MARK,	P2MSEL15_0, P2MSEL14_1, PF7_FN),
+	PINMUX_DATA(SSI1_SCK_MARK,	P2MSEL15_0, P2MSEL14_1, PF6_FN),
+	PINMUX_DATA(SSI1_WS_MARK,	P2MSEL15_0, P2MSEL14_1, PF5_FN),
+	PINMUX_DATA(SSI1_CLK_MARK,	P2MSEL15_0, P2MSEL14_1, PF4_FN),
+	PINMUX_DATA(SSI0_SDATA_MARK,	P2MSEL13_0, P2MSEL12_1, PF3_FN),
+	PINMUX_DATA(SSI0_SCK_MARK,	P2MSEL13_0, P2MSEL12_1, PF2_FN),
+	PINMUX_DATA(SSI0_WS_MARK,	P2MSEL13_0, P2MSEL12_1, PF1_FN),
+	PINMUX_DATA(SSI0_CLK_MARK,	P2MSEL13_0, P2MSEL12_1, PF0_FN),
+	PINMUX_DATA(SDIF1CMD_MARK,	P2MSEL15_1, P2MSEL14_0, PF7_FN),
+	PINMUX_DATA(SDIF1CD_MARK,	P2MSEL15_1, P2MSEL14_0, PF6_FN),
+	PINMUX_DATA(SDIF1WP_MARK,	P2MSEL15_1, P2MSEL14_0, PF5_FN),
+	PINMUX_DATA(SDIF1CLK_MARK,	P2MSEL15_1, P2MSEL14_0, PF4_FN),
+	PINMUX_DATA(SDIF1D3_MARK,	P2MSEL13_1, P2MSEL12_0, PF3_FN),
+	PINMUX_DATA(SDIF1D2_MARK,	P2MSEL13_1, P2MSEL12_0, PF2_FN),
+	PINMUX_DATA(SDIF1D1_MARK,	P2MSEL13_1, P2MSEL12_0, PF1_FN),
+	PINMUX_DATA(SDIF1D0_MARK,	P2MSEL13_1, P2MSEL12_0, PF0_FN),
+
+	/* PG FN */
+	PINMUX_DATA(SCIF3_SCK_MARK,	P1MSEL8_0, PG7_FN),
+	PINMUX_DATA(SSI2_SDATA_MARK,	P1MSEL8_1, PG7_FN),
+	PINMUX_DATA(SCIF3_RXD_MARK,	P1MSEL7_0, P1MSEL6_0, PG6_FN),
+	PINMUX_DATA(SSI2_SCK_MARK,	P1MSEL7_1, P1MSEL6_0, PG6_FN),
+	PINMUX_DATA(TCLK_MARK,		P1MSEL7_0, P1MSEL6_1, PG6_FN),
+	PINMUX_DATA(SCIF3_TXD_MARK,	P1MSEL5_0, P1MSEL4_0, PG5_FN),
+	PINMUX_DATA(SSI2_WS_MARK,	P1MSEL5_1, P1MSEL4_0, PG5_FN),
+	PINMUX_DATA(HAC_RES_MARK,	P1MSEL5_0, P1MSEL4_1, PG5_FN),
+
+	/* PH FN */
+	PINMUX_DATA(DACK3_MARK,		P2MSEL4_0, PH7_FN),
+	PINMUX_DATA(SDIF0CMD_MARK,	P2MSEL4_1, PH7_FN),
+	PINMUX_DATA(DACK2_MARK,		P2MSEL4_0, PH6_FN),
+	PINMUX_DATA(SDIF0CD_MARK,	P2MSEL4_1, PH6_FN),
+	PINMUX_DATA(DREQ3_MARK,		P2MSEL4_0, PH5_FN),
+	PINMUX_DATA(SDIF0WP_MARK,	P2MSEL4_1, PH5_FN),
+	PINMUX_DATA(DREQ2_MARK,		P2MSEL3_0, P2MSEL2_1, PH4_FN),
+	PINMUX_DATA(SDIF0CLK_MARK,	P2MSEL3_1, P2MSEL2_0, PH4_FN),
+	PINMUX_DATA(SCIF0_CTS_MARK,	P2MSEL3_0, P2MSEL2_0, PH4_FN),
+	PINMUX_DATA(SDIF0D3_MARK,	P2MSEL1_1, P2MSEL0_0, PH3_FN),
+	PINMUX_DATA(SCIF0_RTS_MARK,	P2MSEL1_0, P2MSEL0_0, PH3_FN),
+	PINMUX_DATA(IRL7_MARK,		P2MSEL1_0, P2MSEL0_1, PH3_FN),
+	PINMUX_DATA(SDIF0D2_MARK,	P2MSEL1_1, P2MSEL0_0, PH2_FN),
+	PINMUX_DATA(SCIF0_SCK_MARK,	P2MSEL1_0, P2MSEL0_0, PH2_FN),
+	PINMUX_DATA(IRL6_MARK,		P2MSEL1_0, P2MSEL0_1, PH2_FN),
+	PINMUX_DATA(SDIF0D1_MARK,	P2MSEL1_1, P2MSEL0_0, PH1_FN),
+	PINMUX_DATA(SCIF0_RXD_MARK,	P2MSEL1_0, P2MSEL0_0, PH1_FN),
+	PINMUX_DATA(IRL5_MARK,		P2MSEL1_0, P2MSEL0_1, PH1_FN),
+	PINMUX_DATA(SDIF0D0_MARK,	P2MSEL1_1, P2MSEL0_0, PH0_FN),
+	PINMUX_DATA(SCIF0_TXD_MARK,	P2MSEL1_0, P2MSEL0_0, PH0_FN),
+	PINMUX_DATA(IRL4_MARK,		P2MSEL1_0, P2MSEL0_1, PH0_FN),
+
+	/* PJ FN */
+	PINMUX_DATA(SCIF5_SCK_MARK,	P2MSEL11_1, PJ7_FN),
+	PINMUX_DATA(FRB_MARK,		P2MSEL11_0, PJ7_FN),
+	PINMUX_DATA(SCIF5_RXD_MARK,	P2MSEL10_0, PJ6_FN),
+	PINMUX_DATA(IOIS16_MARK,	P2MSEL10_1, PJ6_FN),
+	PINMUX_DATA(SCIF5_TXD_MARK,	P2MSEL10_0, PJ5_FN),
+	PINMUX_DATA(CE2B_MARK,		P2MSEL10_1, PJ5_FN),
+	PINMUX_DATA(DRAK3_MARK,		P2MSEL7_0, PJ4_FN),
+	PINMUX_DATA(CE2A_MARK,		P2MSEL7_1, PJ4_FN),
+	PINMUX_DATA(SCIF4_SCK_MARK,	P2MSEL9_0, P2MSEL8_0, PJ3_FN),
+	PINMUX_DATA(DRAK2_MARK,		P2MSEL9_0, P2MSEL8_1, PJ3_FN),
+	PINMUX_DATA(SSI3_WS_MARK,	P2MSEL9_1, P2MSEL8_0, PJ3_FN),
+	PINMUX_DATA(SCIF4_RXD_MARK,	P2MSEL6_1, P2MSEL5_0, PJ2_FN),
+	PINMUX_DATA(DRAK1_MARK,		P2MSEL6_0, P2MSEL5_1, PJ2_FN),
+	PINMUX_DATA(FSTATUS_MARK,	P2MSEL6_0, P2MSEL5_0, PJ2_FN),
+	PINMUX_DATA(SSI3_SDATA_MARK,	P2MSEL6_1, P2MSEL5_1, PJ2_FN),
+	PINMUX_DATA(SCIF4_TXD_MARK,	P2MSEL6_1, P2MSEL5_0, PJ1_FN),
+	PINMUX_DATA(DRAK0_MARK,		P2MSEL6_0, P2MSEL5_1, PJ1_FN),
+	PINMUX_DATA(FSE_MARK,		P2MSEL6_0, P2MSEL5_0, PJ1_FN),
+	PINMUX_DATA(SSI3_SCK_MARK,	P2MSEL6_1, P2MSEL5_1, PJ1_FN),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+	/* PA */
+	PINMUX_GPIO(GPIO_PA7, PA7_DATA),
+	PINMUX_GPIO(GPIO_PA6, PA6_DATA),
+	PINMUX_GPIO(GPIO_PA5, PA5_DATA),
+	PINMUX_GPIO(GPIO_PA4, PA4_DATA),
+	PINMUX_GPIO(GPIO_PA3, PA3_DATA),
+	PINMUX_GPIO(GPIO_PA2, PA2_DATA),
+	PINMUX_GPIO(GPIO_PA1, PA1_DATA),
+	PINMUX_GPIO(GPIO_PA0, PA0_DATA),
+
+	/* PB */
+	PINMUX_GPIO(GPIO_PB7, PB7_DATA),
+	PINMUX_GPIO(GPIO_PB6, PB6_DATA),
+	PINMUX_GPIO(GPIO_PB5, PB5_DATA),
+	PINMUX_GPIO(GPIO_PB4, PB4_DATA),
+	PINMUX_GPIO(GPIO_PB3, PB3_DATA),
+	PINMUX_GPIO(GPIO_PB2, PB2_DATA),
+	PINMUX_GPIO(GPIO_PB1, PB1_DATA),
+	PINMUX_GPIO(GPIO_PB0, PB0_DATA),
+
+	/* PC */
+	PINMUX_GPIO(GPIO_PC7, PC7_DATA),
+	PINMUX_GPIO(GPIO_PC6, PC6_DATA),
+	PINMUX_GPIO(GPIO_PC5, PC5_DATA),
+	PINMUX_GPIO(GPIO_PC4, PC4_DATA),
+	PINMUX_GPIO(GPIO_PC3, PC3_DATA),
+	PINMUX_GPIO(GPIO_PC2, PC2_DATA),
+	PINMUX_GPIO(GPIO_PC1, PC1_DATA),
+	PINMUX_GPIO(GPIO_PC0, PC0_DATA),
+
+	/* PD */
+	PINMUX_GPIO(GPIO_PD7, PD7_DATA),
+	PINMUX_GPIO(GPIO_PD6, PD6_DATA),
+	PINMUX_GPIO(GPIO_PD5, PD5_DATA),
+	PINMUX_GPIO(GPIO_PD4, PD4_DATA),
+	PINMUX_GPIO(GPIO_PD3, PD3_DATA),
+	PINMUX_GPIO(GPIO_PD2, PD2_DATA),
+	PINMUX_GPIO(GPIO_PD1, PD1_DATA),
+	PINMUX_GPIO(GPIO_PD0, PD0_DATA),
+
+	/* PE */
+	PINMUX_GPIO(GPIO_PE5, PE7_DATA),
+	PINMUX_GPIO(GPIO_PE4, PE6_DATA),
+
+	/* PF */
+	PINMUX_GPIO(GPIO_PF7, PF7_DATA),
+	PINMUX_GPIO(GPIO_PF6, PF6_DATA),
+	PINMUX_GPIO(GPIO_PF5, PF5_DATA),
+	PINMUX_GPIO(GPIO_PF4, PF4_DATA),
+	PINMUX_GPIO(GPIO_PF3, PF3_DATA),
+	PINMUX_GPIO(GPIO_PF2, PF2_DATA),
+	PINMUX_GPIO(GPIO_PF1, PF1_DATA),
+	PINMUX_GPIO(GPIO_PF0, PF0_DATA),
+
+	/* PG */
+	PINMUX_GPIO(GPIO_PG7, PG7_DATA),
+	PINMUX_GPIO(GPIO_PG6, PG6_DATA),
+	PINMUX_GPIO(GPIO_PG5, PG5_DATA),
+
+	/* PH */
+	PINMUX_GPIO(GPIO_PH7, PH7_DATA),
+	PINMUX_GPIO(GPIO_PH6, PH6_DATA),
+	PINMUX_GPIO(GPIO_PH5, PH5_DATA),
+	PINMUX_GPIO(GPIO_PH4, PH4_DATA),
+	PINMUX_GPIO(GPIO_PH3, PH3_DATA),
+	PINMUX_GPIO(GPIO_PH2, PH2_DATA),
+	PINMUX_GPIO(GPIO_PH1, PH1_DATA),
+	PINMUX_GPIO(GPIO_PH0, PH0_DATA),
+
+	/* PJ */
+	PINMUX_GPIO(GPIO_PJ7, PJ7_DATA),
+	PINMUX_GPIO(GPIO_PJ6, PJ6_DATA),
+	PINMUX_GPIO(GPIO_PJ5, PJ5_DATA),
+	PINMUX_GPIO(GPIO_PJ4, PJ4_DATA),
+	PINMUX_GPIO(GPIO_PJ3, PJ3_DATA),
+	PINMUX_GPIO(GPIO_PJ2, PJ2_DATA),
+	PINMUX_GPIO(GPIO_PJ1, PJ1_DATA),
+
+	/* FN */
+	PINMUX_GPIO(GPIO_FN_CDE,		CDE_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_MAGIC,		ETH_MAGIC_MARK),
+	PINMUX_GPIO(GPIO_FN_DISP,		DISP_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_LINK,		ETH_LINK_MARK),
+	PINMUX_GPIO(GPIO_FN_DR5,		DR5_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_TX_ER,		ETH_TX_ER_MARK),
+	PINMUX_GPIO(GPIO_FN_DR4,		DR4_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_TX_EN,		ETH_TX_EN_MARK),
+	PINMUX_GPIO(GPIO_FN_DR3,		DR3_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_TXD3,		ETH_TXD3_MARK),
+	PINMUX_GPIO(GPIO_FN_DR2,		DR2_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_TXD2,		ETH_TXD2_MARK),
+	PINMUX_GPIO(GPIO_FN_DR1,		DR1_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_TXD1,		ETH_TXD1_MARK),
+	PINMUX_GPIO(GPIO_FN_DR0,		DR0_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_TXD0,		ETH_TXD0_MARK),
+	PINMUX_GPIO(GPIO_FN_VSYNC,		VSYNC_MARK),
+	PINMUX_GPIO(GPIO_FN_HSPI_CLK,		HSPI_CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_ODDF,		ODDF_MARK),
+	PINMUX_GPIO(GPIO_FN_HSPI_CS,		HSPI_CS_MARK),
+	PINMUX_GPIO(GPIO_FN_DG5,		DG5_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_MDIO,		ETH_MDIO_MARK),
+	PINMUX_GPIO(GPIO_FN_DG4,		DG4_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_RX_CLK,		ETH_RX_CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_DG3,		DG3_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_MDC,		ETH_MDC_MARK),
+	PINMUX_GPIO(GPIO_FN_DG2,		DG2_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_COL,		ETH_COL_MARK),
+	PINMUX_GPIO(GPIO_FN_DG1,		DG1_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_TX_CLK,		ETH_TX_CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_DG0,		DG0_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_CRS,		ETH_CRS_MARK),
+	PINMUX_GPIO(GPIO_FN_DCLKIN,		DCLKIN_MARK),
+	PINMUX_GPIO(GPIO_FN_HSPI_RX,		HSPI_RX_MARK),
+	PINMUX_GPIO(GPIO_FN_HSYNC,		HSYNC_MARK),
+	PINMUX_GPIO(GPIO_FN_HSPI_TX,		HSPI_TX_MARK),
+	PINMUX_GPIO(GPIO_FN_DB5,		DB5_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_RXD3,		ETH_RXD3_MARK),
+	PINMUX_GPIO(GPIO_FN_DB4,		DB4_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_RXD2,		ETH_RXD2_MARK),
+	PINMUX_GPIO(GPIO_FN_DB3,		DB3_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_RXD1,		ETH_RXD1_MARK),
+	PINMUX_GPIO(GPIO_FN_DB2,		DB2_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_RXD0,		ETH_RXD0_MARK),
+	PINMUX_GPIO(GPIO_FN_DB1,		DB1_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_RX_DV,		ETH_RX_DV_MARK),
+	PINMUX_GPIO(GPIO_FN_DB0,		DB0_MARK),
+	PINMUX_GPIO(GPIO_FN_ETH_RX_ER,		ETH_RX_ER_MARK),
+	PINMUX_GPIO(GPIO_FN_DCLKOUT,		DCLKOUT_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF1_SLK,		SCIF1_SLK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF1_RXD,		SCIF1_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF1_TXD,		SCIF1_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_DACK1,		DACK1_MARK),
+	PINMUX_GPIO(GPIO_FN_BACK,		BACK_MARK),
+	PINMUX_GPIO(GPIO_FN_FALE,		FALE_MARK),
+	PINMUX_GPIO(GPIO_FN_DACK0,		DACK0_MARK),
+	PINMUX_GPIO(GPIO_FN_FCLE,		FCLE_MARK),
+	PINMUX_GPIO(GPIO_FN_DREQ1,		DREQ1_MARK),
+	PINMUX_GPIO(GPIO_FN_BREQ,		BREQ_MARK),
+	PINMUX_GPIO(GPIO_FN_USB_OVC1,		USB_OVC1_MARK),
+	PINMUX_GPIO(GPIO_FN_DREQ0,		DREQ0_MARK),
+	PINMUX_GPIO(GPIO_FN_USB_OVC0,		USB_OVC0_MARK),
+	PINMUX_GPIO(GPIO_FN_USB_PENC1,		USB_PENC1_MARK),
+	PINMUX_GPIO(GPIO_FN_USB_PENC0,		USB_PENC0_MARK),
+	PINMUX_GPIO(GPIO_FN_HAC1_SDOUT,		HAC1_SDOUT_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI1_SDATA,		SSI1_SDATA_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF1CMD,		SDIF1CMD_MARK),
+	PINMUX_GPIO(GPIO_FN_HAC1_SDIN,		HAC1_SDIN_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI1_SCK,		SSI1_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF1CD,		SDIF1CD_MARK),
+	PINMUX_GPIO(GPIO_FN_HAC1_SYNC,		HAC1_SYNC_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI1_WS,		SSI1_WS_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF1WP,		SDIF1WP_MARK),
+	PINMUX_GPIO(GPIO_FN_HAC1_BITCLK,	HAC1_BITCLK_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI1_CLK,		SSI1_CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF1CLK,		SDIF1CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_HAC0_SDOUT,		HAC0_SDOUT_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI0_SDATA,		SSI0_SDATA_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF1D3,		SDIF1D3_MARK),
+	PINMUX_GPIO(GPIO_FN_HAC0_SDIN,		HAC0_SDIN_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI0_SCK,		SSI0_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF1D2,		SDIF1D2_MARK),
+	PINMUX_GPIO(GPIO_FN_HAC0_SYNC,		HAC0_SYNC_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI0_WS,		SSI0_WS_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF1D1,		SDIF1D1_MARK),
+	PINMUX_GPIO(GPIO_FN_HAC0_BITCLK,	HAC0_BITCLK_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI0_CLK,		SSI0_CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF1D0,		SDIF1D0_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_SCK,		SCIF3_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI2_SDATA,		SSI2_SDATA_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_RXD,		SCIF3_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_TCLK,		TCLK_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI2_SCK,		SSI2_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_TXD,		SCIF3_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_HAC_RES,		HAC_RES_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI2_WS,		SSI2_WS_MARK),
+	PINMUX_GPIO(GPIO_FN_DACK3,		DACK3_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF0CMD,		SDIF0CMD_MARK),
+	PINMUX_GPIO(GPIO_FN_DACK2,		DACK2_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF0CD,		SDIF0CD_MARK),
+	PINMUX_GPIO(GPIO_FN_DREQ3,		DREQ3_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF0WP,		SDIF0WP_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF0_CTS,		SCIF0_CTS_MARK),
+	PINMUX_GPIO(GPIO_FN_DREQ2,		DREQ2_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF0CLK,		SDIF0CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF0_RTS,		SCIF0_RTS_MARK),
+	PINMUX_GPIO(GPIO_FN_IRL7,		IRL7_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF0D3,		SDIF0D3_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF0_SCK,		SCIF0_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_IRL6,		IRL6_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF0D2,		SDIF0D2_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF0_RXD,		SCIF0_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_IRL5,		IRL5_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF0D1,		SDIF0D1_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF0_TXD,		SCIF0_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_IRL4,		IRL4_MARK),
+	PINMUX_GPIO(GPIO_FN_SDIF0D0,		SDIF0D0_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF5_SCK,		SCIF5_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_FRB,		FRB_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF5_RXD,		SCIF5_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_IOIS16,		IOIS16_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF5_TXD,		SCIF5_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_CE2B,		CE2B_MARK),
+	PINMUX_GPIO(GPIO_FN_DRAK3,		DRAK3_MARK),
+	PINMUX_GPIO(GPIO_FN_CE2A,		CE2A_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF4_SCK,		SCIF4_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_DRAK2,		DRAK2_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI3_WS,		SSI3_WS_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF4_RXD,		SCIF4_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_DRAK1,		DRAK1_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI3_SDATA,		SSI3_SDATA_MARK),
+	PINMUX_GPIO(GPIO_FN_FSTATUS,		FSTATUS_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF4_TXD,		SCIF4_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_DRAK0,		DRAK0_MARK),
+	PINMUX_GPIO(GPIO_FN_SSI3_SCK,		SSI3_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_FSE,		FSE_MARK),
+};
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+	{ PINMUX_CFG_REG("PACR", 0xffcc0000, 16, 2) {
+		PA7_FN, PA7_OUT, PA7_IN, PA7_IN_PU,
+		PA6_FN, PA6_OUT, PA6_IN, PA6_IN_PU,
+		PA5_FN, PA5_OUT, PA5_IN, PA5_IN_PU,
+		PA4_FN, PA4_OUT, PA4_IN, PA4_IN_PU,
+		PA3_FN, PA3_OUT, PA3_IN, PA3_IN_PU,
+		PA2_FN, PA2_OUT, PA2_IN, PA2_IN_PU,
+		PA1_FN, PA1_OUT, PA1_IN, PA1_IN_PU,
+		PA0_FN, PA0_OUT, PA0_IN, PA0_IN_PU }
+	},
+	{ PINMUX_CFG_REG("PBCR", 0xffcc0002, 16, 2) {
+		PB7_FN, PB7_OUT, PB7_IN, PB7_IN_PU,
+		PB6_FN, PB6_OUT, PB6_IN, PB6_IN_PU,
+		PB5_FN, PB5_OUT, PB5_IN, PB5_IN_PU,
+		PB4_FN, PB4_OUT, PB4_IN, PB4_IN_PU,
+		PB3_FN, PB3_OUT, PB3_IN, PB3_IN_PU,
+		PB2_FN, PB2_OUT, PB2_IN, PB2_IN_PU,
+		PB1_FN, PB1_OUT, PB1_IN, PB1_IN_PU,
+		PB0_FN, PB0_OUT, PB0_IN, PB0_IN_PU }
+	},
+	{ PINMUX_CFG_REG("PCCR", 0xffcc0004, 16, 2) {
+		PC7_FN, PC7_OUT, PC7_IN, PC7_IN_PU,
+		PC6_FN, PC6_OUT, PC6_IN, PC6_IN_PU,
+		PC5_FN, PC5_OUT, PC5_IN, PC5_IN_PU,
+		PC4_FN, PC4_OUT, PC4_IN, PC4_IN_PU,
+		PC3_FN, PC3_OUT, PC3_IN, PC3_IN_PU,
+		PC2_FN, PC2_OUT, PC2_IN, PC2_IN_PU,
+		PC1_FN, PC1_OUT, PC1_IN, PC1_IN_PU,
+		PC0_FN, PC0_OUT, PC0_IN, PC0_IN_PU }
+	},
+	{ PINMUX_CFG_REG("PDCR", 0xffcc0006, 16, 2) {
+		PD7_FN, PD7_OUT, PD7_IN, PD7_IN_PU,
+		PD6_FN, PD6_OUT, PD6_IN, PD6_IN_PU,
+		PD5_FN, PD5_OUT, PD5_IN, PD5_IN_PU,
+		PD4_FN, PD4_OUT, PD4_IN, PD4_IN_PU,
+		PD3_FN, PD3_OUT, PD3_IN, PD3_IN_PU,
+		PD2_FN, PD2_OUT, PD2_IN, PD2_IN_PU,
+		PD1_FN, PD1_OUT, PD1_IN, PD1_IN_PU,
+		PD0_FN, PD0_OUT, PD0_IN, PD0_IN_PU }
+	},
+	{ PINMUX_CFG_REG("PECR", 0xffcc0008, 16, 2) {
+		PE7_FN, PE7_OUT, PE7_IN, PE7_IN_PU,
+		PE6_FN, PE6_OUT, PE6_IN, PE6_IN_PU,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0, }
+	},
+	{ PINMUX_CFG_REG("PFCR", 0xffcc000a, 16, 2) {
+		PF7_FN, PF7_OUT, PF7_IN, PF7_IN_PU,
+		PF6_FN, PF6_OUT, PF6_IN, PF6_IN_PU,
+		PF5_FN, PF5_OUT, PF5_IN, PF5_IN_PU,
+		PF4_FN, PF4_OUT, PF4_IN, PF4_IN_PU,
+		PF3_FN, PF3_OUT, PF3_IN, PF3_IN_PU,
+		PF2_FN, PF2_OUT, PF2_IN, PF2_IN_PU,
+		PF1_FN, PF1_OUT, PF1_IN, PF1_IN_PU,
+		PF0_FN, PF0_OUT, PF0_IN, PF0_IN_PU }
+	},
+	{ PINMUX_CFG_REG("PGCR", 0xffcc000c, 16, 2) {
+		PG7_FN, PG7_OUT, PG7_IN, PG7_IN_PU,
+		PG6_FN, PG6_OUT, PG6_IN, PG6_IN_PU,
+		PG5_FN, PG5_OUT, PG5_IN, PG5_IN_PU,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0, }
+	},
+	{ PINMUX_CFG_REG("PHCR", 0xffcc000e, 16, 2) {
+		PH7_FN, PH7_OUT, PH7_IN, PH7_IN_PU,
+		PH6_FN, PH6_OUT, PH6_IN, PH6_IN_PU,
+		PH5_FN, PH5_OUT, PH5_IN, PH5_IN_PU,
+		PH4_FN, PH4_OUT, PH4_IN, PH4_IN_PU,
+		PH3_FN, PH3_OUT, PH3_IN, PH3_IN_PU,
+		PH2_FN, PH2_OUT, PH2_IN, PH2_IN_PU,
+		PH1_FN, PH1_OUT, PH1_IN, PH1_IN_PU,
+		PH0_FN, PH0_OUT, PH0_IN, PH0_IN_PU }
+	},
+	{ PINMUX_CFG_REG("PJCR", 0xffcc0010, 16, 2) {
+		PJ7_FN, PJ7_OUT, PJ7_IN, PJ7_IN_PU,
+		PJ6_FN, PJ6_OUT, PJ6_IN, PJ6_IN_PU,
+		PJ5_FN, PJ5_OUT, PJ5_IN, PJ5_IN_PU,
+		PJ4_FN, PJ4_OUT, PJ4_IN, PJ4_IN_PU,
+		PJ3_FN, PJ3_OUT, PJ3_IN, PJ3_IN_PU,
+		PJ2_FN, PJ2_OUT, PJ2_IN, PJ2_IN_PU,
+		PJ1_FN, PJ1_OUT, PJ1_IN, PJ1_IN_PU,
+		0, 0, 0, 0, }
+	},
+	{ PINMUX_CFG_REG("P1MSELR", 0xffcc0080, 16, 1) {
+		0, 0,
+		P1MSEL14_0, P1MSEL14_1,
+		P1MSEL13_0, P1MSEL13_1,
+		P1MSEL12_0, P1MSEL12_1,
+		P1MSEL11_0, P1MSEL11_1,
+		P1MSEL10_0, P1MSEL10_1,
+		P1MSEL9_0,  P1MSEL9_1,
+		P1MSEL8_0,  P1MSEL8_1,
+		P1MSEL7_0,  P1MSEL7_1,
+		P1MSEL6_0,  P1MSEL6_1,
+		P1MSEL5_0,  P1MSEL5_1,
+		P1MSEL4_0,  P1MSEL4_1,
+		P1MSEL3_0,  P1MSEL3_1,
+		P1MSEL2_0,  P1MSEL2_1,
+		P1MSEL1_0,  P1MSEL1_1,
+		P1MSEL0_0,  P1MSEL0_1 }
+	},
+	{ PINMUX_CFG_REG("P2MSELR", 0xffcc0082, 16, 1) {
+		P2MSEL15_0, P2MSEL15_1,
+		P2MSEL14_0, P2MSEL14_1,
+		P2MSEL13_0, P2MSEL13_1,
+		P2MSEL12_0, P2MSEL12_1,
+		P2MSEL11_0, P2MSEL11_1,
+		P2MSEL10_0, P2MSEL10_1,
+		P2MSEL9_0,  P2MSEL9_1,
+		P2MSEL8_0,  P2MSEL8_1,
+		P2MSEL7_0,  P2MSEL7_1,
+		P2MSEL6_0,  P2MSEL6_1,
+		P2MSEL5_0,  P2MSEL5_1,
+		P2MSEL4_0,  P2MSEL4_1,
+		P2MSEL3_0,  P2MSEL3_1,
+		P2MSEL2_0,  P2MSEL2_1,
+		P2MSEL1_0,  P2MSEL1_1,
+		P2MSEL0_0,  P2MSEL0_1 }
+	},
+	{}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+	{ PINMUX_DATA_REG("PADR", 0xffcc0020, 8) {
+		PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
+		PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA }
+	},
+	{ PINMUX_DATA_REG("PBDR", 0xffcc0022, 8) {
+		PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+		PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA }
+	},
+	{ PINMUX_DATA_REG("PCDR", 0xffcc0024, 8) {
+		PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+		PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA }
+	},
+	{ PINMUX_DATA_REG("PDDR", 0xffcc0026, 8) {
+		PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+		PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA }
+	},
+	{ PINMUX_DATA_REG("PEDR", 0xffcc0028, 8) {
+		PE7_DATA, PE6_DATA,
+		0, 0, 0, 0, 0, 0 }
+	},
+	{ PINMUX_DATA_REG("PFDR", 0xffcc002a, 8) {
+		PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+		PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA }
+	},
+	{ PINMUX_DATA_REG("PGDR", 0xffcc002c, 8) {
+		PG7_DATA, PG6_DATA, PG5_DATA, 0,
+		0, 0, 0, 0 }
+	},
+	{ PINMUX_DATA_REG("PHDR", 0xffcc002e, 8) {
+		PH7_DATA, PH6_DATA, PH5_DATA, PH4_DATA,
+		PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA }
+	},
+	{ PINMUX_DATA_REG("PJDR", 0xffcc0030, 8) {
+		PJ7_DATA, PJ6_DATA, PJ5_DATA, PJ4_DATA,
+		PJ3_DATA, PJ2_DATA, PJ1_DATA, 0 }
+	},
+	{ },
+};
+
+static struct pinmux_info sh7786_pinmux_info = {
+	.name = "sh7786_pfc",
+	.reserved_id = PINMUX_RESERVED,
+	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
+	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+	.first_gpio = GPIO_PA7,
+	.last_gpio = GPIO_FN_FSE,
+
+	.gpios = pinmux_gpios,
+	.cfg_regs = pinmux_config_regs,
+	.data_regs = pinmux_data_regs,
+
+	.gpio_data = pinmux_data,
+	.gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+	return register_pinmux(&sh7786_pinmux_info);
+}
+
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index 4ff4dc6..c154938 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -12,6 +12,7 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/uio_driver.h>
+#include <linux/sh_cmt.h>
 #include <asm/clock.h>
 
 static struct resource iic0_resources[] = {
@@ -140,6 +141,38 @@
 	.num_resources	= ARRAY_SIZE(jpu_resources),
 };
 
+static struct sh_cmt_config cmt_platform_data = {
+	.name = "CMT",
+	.channel_offset = 0x60,
+	.timer_bit = 5,
+	.clk = "cmt0",
+	.clockevent_rating = 125,
+	.clocksource_rating = 200,
+};
+
+static struct resource cmt_resources[] = {
+	[0] = {
+		.name	= "CMT",
+		.start	= 0x044a0060,
+		.end	= 0x044a006b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt_device = {
+	.name		= "sh_cmt",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &cmt_platform_data,
+	},
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xffe00000,
@@ -175,6 +208,7 @@
 };
 
 static struct platform_device *sh7343_devices[] __initdata = {
+	&cmt_device,
 	&iic0_device,
 	&iic1_device,
 	&sci_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 839ae97..93ecf8e 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -14,6 +14,7 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/uio_driver.h>
+#include <linux/sh_cmt.h>
 #include <asm/clock.h>
 
 static struct resource iic_resources[] = {
@@ -147,6 +148,38 @@
 	.num_resources	= ARRAY_SIZE(veu1_resources),
 };
 
+static struct sh_cmt_config cmt_platform_data = {
+	.name = "CMT",
+	.channel_offset = 0x60,
+	.timer_bit = 5,
+	.clk = "cmt0",
+	.clockevent_rating = 125,
+	.clocksource_rating = 200,
+};
+
+static struct resource cmt_resources[] = {
+	[0] = {
+		.name	= "CMT",
+		.start	= 0x044a0060,
+		.end	= 0x044a006b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt_device = {
+	.name		= "sh_cmt",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &cmt_platform_data,
+	},
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xffe00000,
@@ -167,6 +200,7 @@
 };
 
 static struct platform_device *sh7366_devices[] __initdata = {
+	&cmt_device,
 	&iic_device,
 	&sci_device,
 	&usb_host_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 5146afc..0e5d204 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -13,6 +13,7 @@
 #include <linux/serial_sci.h>
 #include <linux/mm.h>
 #include <linux/uio_driver.h>
+#include <linux/sh_cmt.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
 
@@ -176,6 +177,38 @@
 	.num_resources	= ARRAY_SIZE(jpu_resources),
 };
 
+static struct sh_cmt_config cmt_platform_data = {
+	.name = "CMT",
+	.channel_offset = 0x60,
+	.timer_bit = 5,
+	.clk = "cmt0",
+	.clockevent_rating = 125,
+	.clocksource_rating = 200,
+};
+
+static struct resource cmt_resources[] = {
+	[0] = {
+		.name	= "CMT",
+		.start	= 0x044a0060,
+		.end	= 0x044a006b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt_device = {
+	.name		= "sh_cmt",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &cmt_platform_data,
+	},
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xffe00000,
@@ -209,6 +242,7 @@
 };
 
 static struct platform_device *sh7722_devices[] __initdata = {
+	&cmt_device,
 	&rtc_device,
 	&usbf_device,
 	&iic_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index 849770d..5338dac 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -13,6 +13,7 @@
 #include <linux/mm.h>
 #include <linux/serial_sci.h>
 #include <linux/uio_driver.h>
+#include <linux/sh_cmt.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
 
@@ -100,6 +101,38 @@
 	.num_resources	= ARRAY_SIZE(veu1_resources),
 };
 
+static struct sh_cmt_config cmt_platform_data = {
+	.name = "CMT",
+	.channel_offset = 0x60,
+	.timer_bit = 5,
+	.clk = "cmt0",
+	.clockevent_rating = 125,
+	.clocksource_rating = 200,
+};
+
+static struct resource cmt_resources[] = {
+	[0] = {
+		.name	= "CMT",
+		.start	= 0x044a0060,
+		.end	= 0x044a006b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt_device = {
+	.name		= "sh_cmt",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &cmt_platform_data,
+	},
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase        = 0xffe00000,
@@ -221,6 +254,7 @@
 };
 
 static struct platform_device *sh7723_devices[] __initdata = {
+	&cmt_device,
 	&sci_device,
 	&rtc_device,
 	&iic_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
index 3c5b629..bdf0f61 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2006  Paul Mundt
  *  Copyright (C) 2007  Yoshihiro Shimoda
- *  Copyright (C) 2008  Nobuhiro Iwamatsu
+ *  Copyright (C) 2008, 2009  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
@@ -22,18 +22,8 @@
 		.flags	= IORESOURCE_IO,
 	},
 	[1] = {
-		/* Period IRQ */
-		.start	= 21,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		/* Carry IRQ */
-		.start	= 22,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		/* Alarm IRQ */
-		.start	= 20,
+		/* Shared Period/Carry/Alarm IRQ */
+		.start  = 20,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -50,17 +40,17 @@
 		.mapbase	= 0xffe00000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 40, 41, 43, 42 },
+		.irqs		= { 40, 40, 40, 40 },
 	}, {
 		.mapbase	= 0xffe08000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 76, 77, 79, 78 },
+		.irqs		= { 76, 76, 76, 76 },
 	}, {
 		.mapbase	= 0xffe10000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 104, 105, 107, 106 },
+		.irqs		= { 104, 104, 104, 104 },
 	}, {
 		.flags = 0,
 	}
@@ -148,93 +138,65 @@
 	IRL_HHLL, IRL_HHLH, IRL_HHHL,
 
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
-	RTC_ATI, RTC_PRI, RTC_CUI,
-	WDT, TMU0, TMU1, TMU2, TMU2_TICPI,
-	HUDI, LCDC,
-	DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3, DMAC0_DMAE,
-	SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
-	DMAC0_DMINT4, DMAC0_DMINT5,
-	IIC0, IIC1,
-	CMT,
-	GEINT0, GEINT1, GEINT2,
-	HAC,
-	PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD,
-	PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0,
-	STIF0, STIF1,
-	SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
-	SIOF0, SIOF1, SIOF2,
-	USBH, USBFI0, USBFI1,
-	TPU, PCC,
-	MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY,
-	SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEND,
+	RTC, WDT, TMU0, TMU1, TMU2, TMU2_TICPI,
+	HUDI, LCDC, DMAC, SCIF0, IIC0, IIC1, CMT, GETHER, HAC,
+	PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD, PCIC5,
+	STIF0, STIF1, SCIF1, SIOF0, SIOF1, SIOF2,
+	USBH, USBF, TPU, PCC, MMCIF, SIM,
 	TMU3, TMU4, TMU5, ADC, SSI0, SSI1, SSI2, SSI3,
-	SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI,
-	GPIO_CH0, GPIO_CH1, GPIO_CH2, GPIO_CH3,
+	SCIF2, GPIO,
 
 	/* interrupt groups */
 
-	TMU012, TMU345, RTC, DMAC, SCIF0, GETHER, PCIC5,
-	SCIF1, USBF, MMCIF, SIM, SCIF2, GPIO,
+	TMU012, TMU345,
 };
 
 static struct intc_vect vectors[] __initdata = {
-	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
-	INTC_VECT(RTC_CUI, 0x4c0),
+	INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+	INTC_VECT(RTC, 0x4c0),
 	INTC_VECT(WDT, 0x560), INTC_VECT(TMU0, 0x580),
 	INTC_VECT(TMU1, 0x5a0), INTC_VECT(TMU2, 0x5c0),
 	INTC_VECT(TMU2_TICPI, 0x5e0), INTC_VECT(HUDI, 0x600),
 	INTC_VECT(LCDC, 0x620),
-	INTC_VECT(DMAC0_DMINT0, 0x640), INTC_VECT(DMAC0_DMINT1, 0x660),
-	INTC_VECT(DMAC0_DMINT2, 0x680), INTC_VECT(DMAC0_DMINT3, 0x6a0),
-	INTC_VECT(DMAC0_DMAE, 0x6c0),
-	INTC_VECT(SCIF0_ERI, 0x700), INTC_VECT(SCIF0_RXI, 0x720),
-	INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760),
-	INTC_VECT(DMAC0_DMINT4, 0x780), INTC_VECT(DMAC0_DMINT5, 0x7a0),
+	INTC_VECT(DMAC, 0x640), INTC_VECT(DMAC, 0x660),
+	INTC_VECT(DMAC, 0x680), INTC_VECT(DMAC, 0x6a0),
+	INTC_VECT(DMAC, 0x6c0),
+	INTC_VECT(SCIF0, 0x700), INTC_VECT(SCIF0, 0x720),
+	INTC_VECT(SCIF0, 0x740), INTC_VECT(SCIF0, 0x760),
+	INTC_VECT(DMAC, 0x780), INTC_VECT(DMAC, 0x7a0),
 	INTC_VECT(IIC0, 0x8A0), INTC_VECT(IIC1, 0x8C0),
-	INTC_VECT(CMT, 0x900), INTC_VECT(GEINT0, 0x920),
-	INTC_VECT(GEINT1, 0x940), INTC_VECT(GEINT2, 0x960),
+	INTC_VECT(CMT, 0x900), INTC_VECT(GETHER, 0x920),
+	INTC_VECT(GETHER, 0x940), INTC_VECT(GETHER, 0x960),
 	INTC_VECT(HAC, 0x980),
 	INTC_VECT(PCISERR, 0xa00), INTC_VECT(PCIINTA, 0xa20),
 	INTC_VECT(PCIINTB, 0xa40), INTC_VECT(PCIINTC, 0xa60),
-	INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIERR, 0xaa0),
-	INTC_VECT(PCIPWD3, 0xac0), INTC_VECT(PCIPWD2, 0xae0),
-	INTC_VECT(PCIPWD1, 0xb00), INTC_VECT(PCIPWD0, 0xb20),
+	INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIC5, 0xaa0),
+	INTC_VECT(PCIC5, 0xac0), INTC_VECT(PCIC5, 0xae0),
+	INTC_VECT(PCIC5, 0xb00), INTC_VECT(PCIC5, 0xb20),
 	INTC_VECT(STIF0, 0xb40), INTC_VECT(STIF1, 0xb60),
-	INTC_VECT(SCIF1_ERI, 0xb80), INTC_VECT(SCIF1_RXI, 0xba0),
-	INTC_VECT(SCIF1_BRI, 0xbc0), INTC_VECT(SCIF1_TXI, 0xbe0),
+	INTC_VECT(SCIF1, 0xb80), INTC_VECT(SCIF1, 0xba0),
+	INTC_VECT(SCIF1, 0xbc0), INTC_VECT(SCIF1, 0xbe0),
 	INTC_VECT(SIOF0, 0xc00), INTC_VECT(SIOF1, 0xc20),
-	INTC_VECT(USBH, 0xc60), INTC_VECT(USBFI0, 0xc80),
-	INTC_VECT(USBFI1, 0xca0),
+	INTC_VECT(USBH, 0xc60), INTC_VECT(USBF, 0xc80),
+	INTC_VECT(USBF, 0xca0),
 	INTC_VECT(TPU, 0xcc0), INTC_VECT(PCC, 0xce0),
-	INTC_VECT(MMCIF_FSTAT, 0xd00), INTC_VECT(MMCIF_TRAN, 0xd20),
-	INTC_VECT(MMCIF_ERR, 0xd40), INTC_VECT(MMCIF_FRDY, 0xd60),
-	INTC_VECT(SIM_ERI, 0xd80), INTC_VECT(SIM_RXI, 0xda0),
-	INTC_VECT(SIM_TXI, 0xdc0), INTC_VECT(SIM_TEND, 0xde0),
+	INTC_VECT(MMCIF, 0xd00), INTC_VECT(MMCIF, 0xd20),
+	INTC_VECT(MMCIF, 0xd40), INTC_VECT(MMCIF, 0xd60),
+	INTC_VECT(SIM, 0xd80), INTC_VECT(SIM, 0xda0),
+	INTC_VECT(SIM, 0xdc0), INTC_VECT(SIM, 0xde0),
 	INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
 	INTC_VECT(TMU5, 0xe40), INTC_VECT(ADC, 0xe60),
 	INTC_VECT(SSI0, 0xe80), INTC_VECT(SSI1, 0xea0),
 	INTC_VECT(SSI2, 0xec0), INTC_VECT(SSI3, 0xee0),
-	INTC_VECT(SCIF2_ERI, 0xf00), INTC_VECT(SCIF2_RXI, 0xf20),
-	INTC_VECT(SCIF2_BRI, 0xf40), INTC_VECT(SCIF2_TXI, 0xf60),
-	INTC_VECT(GPIO_CH0, 0xf80), INTC_VECT(GPIO_CH1, 0xfa0),
-	INTC_VECT(GPIO_CH2, 0xfc0), INTC_VECT(GPIO_CH3, 0xfe0),
+	INTC_VECT(SCIF2, 0xf00), INTC_VECT(SCIF2, 0xf20),
+	INTC_VECT(SCIF2, 0xf40), INTC_VECT(SCIF2, 0xf60),
+	INTC_VECT(GPIO, 0xf80), INTC_VECT(GPIO, 0xfa0),
+	INTC_VECT(GPIO, 0xfc0), INTC_VECT(GPIO, 0xfe0),
 };
 
 static struct intc_group groups[] __initdata = {
 	INTC_GROUP(TMU012, TMU0, TMU1, TMU2, TMU2_TICPI),
 	INTC_GROUP(TMU345, TMU3, TMU4, TMU5),
-	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
-	INTC_GROUP(DMAC, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
-		   DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE),
-	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
-	INTC_GROUP(GETHER, GEINT0, GEINT1, GEINT2),
-	INTC_GROUP(PCIC5, PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0),
-	INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
-	INTC_GROUP(USBF, USBFI0, USBFI1),
-	INTC_GROUP(MMCIF, MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY),
-	INTC_GROUP(SIM, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEND),
-	INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
-	INTC_GROUP(GPIO, GPIO_CH0, GPIO_CH1, GPIO_CH2, GPIO_CH3),
 };
 
 static struct intc_mask_reg mask_registers[] __initdata = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index fb8200c..6f7227c 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -20,17 +20,7 @@
 		.flags	= IORESOURCE_IO,
 	},
 	[1] = {
-		/* Period IRQ */
-		.start	= 21,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		/* Carry IRQ */
-		.start	= 22,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		/* Alarm IRQ */
+		/* Shared Period/Carry/Alarm IRQ */
 		.start	= 20,
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -48,12 +38,12 @@
 		.mapbase	= 0xffe00000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 40, 41, 43, 42 },
+		.irqs		= { 40, 40, 40, 40 },
 	}, {
 		.mapbase	= 0xffe10000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 76, 77, 79, 78 },
+		.irqs		= { 76, 76, 76, 76 },
 	}, {
 		.flags = 0,
 	}
@@ -90,82 +80,55 @@
 	IRL_HHLL, IRL_HHLH, IRL_HHHL,
 
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
-	RTC_ATI, RTC_PRI, RTC_CUI,
-	WDT,
-	TMU0, TMU1, TMU2, TMU2_TICPI,
-	HUDI,
-	DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3, DMAC0_DMAE,
-	SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
-	DMAC0_DMINT4, DMAC0_DMINT5, DMAC1_DMINT6, DMAC1_DMINT7,
-	CMT, HAC,
-	PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD,
-	PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0,
-	SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
-	SIOF, HSPI,
-	MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY,
-	DMAC1_DMINT8, DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11,
-	TMU3, TMU4, TMU5,
-	SSI,
-	FLCTL_FLSTE, FLCTL_FLEND, FLCTL_FLTRQ0, FLCTL_FLTRQ1,
-	GPIOI0, GPIOI1, GPIOI2, GPIOI3,
+	RTC, WDT, TMU0, TMU1, TMU2, TMU2_TICPI,
+	HUDI, DMAC0, SCIF0, DMAC1, CMT, HAC,
+	PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD, PCIC5,
+	SCIF1, SIOF, HSPI, MMCIF, TMU3, TMU4, TMU5, SSI, FLCTL,	GPIO,
 
 	/* interrupt groups */
 
-	RTC, TMU012, DMAC0, SCIF0, DMAC45, DMAC1,
-	PCIC5, SCIF1, MMCIF, TMU345, FLCTL, GPIO,
+	TMU012,	TMU345,
 };
 
 static struct intc_vect vectors[] __initdata = {
-	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
-	INTC_VECT(RTC_CUI, 0x4c0),
+	INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+	INTC_VECT(RTC, 0x4c0),
 	INTC_VECT(WDT, 0x560),
 	INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0),
 	INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0),
 	INTC_VECT(HUDI, 0x600),
-	INTC_VECT(DMAC0_DMINT0, 0x640), INTC_VECT(DMAC0_DMINT1, 0x660),
-	INTC_VECT(DMAC0_DMINT2, 0x680), INTC_VECT(DMAC0_DMINT3, 0x6a0),
-	INTC_VECT(DMAC0_DMAE, 0x6c0),
-	INTC_VECT(SCIF0_ERI, 0x700), INTC_VECT(SCIF0_RXI, 0x720),
-	INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760),
-	INTC_VECT(DMAC0_DMINT4, 0x780), INTC_VECT(DMAC0_DMINT5, 0x7a0),
-	INTC_VECT(DMAC1_DMINT6, 0x7c0), INTC_VECT(DMAC1_DMINT7, 0x7e0),
+	INTC_VECT(DMAC0, 0x640), INTC_VECT(DMAC0, 0x660),
+	INTC_VECT(DMAC0, 0x680), INTC_VECT(DMAC0, 0x6a0),
+	INTC_VECT(DMAC0, 0x6c0),
+	INTC_VECT(SCIF0, 0x700), INTC_VECT(SCIF0, 0x720),
+	INTC_VECT(SCIF0, 0x740), INTC_VECT(SCIF0, 0x760),
+	INTC_VECT(DMAC0, 0x780), INTC_VECT(DMAC0, 0x7a0),
+	INTC_VECT(DMAC1, 0x7c0), INTC_VECT(DMAC1, 0x7e0),
 	INTC_VECT(CMT, 0x900), INTC_VECT(HAC, 0x980),
 	INTC_VECT(PCISERR, 0xa00), INTC_VECT(PCIINTA, 0xa20),
 	INTC_VECT(PCIINTB, 0xa40), INTC_VECT(PCIINTC, 0xa60),
-	INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIERR, 0xaa0),
-	INTC_VECT(PCIPWD3, 0xac0), INTC_VECT(PCIPWD2, 0xae0),
-	INTC_VECT(PCIPWD1, 0xb00), INTC_VECT(PCIPWD0, 0xb20),
-	INTC_VECT(SCIF1_ERI, 0xb80), INTC_VECT(SCIF1_RXI, 0xba0),
-	INTC_VECT(SCIF1_BRI, 0xbc0), INTC_VECT(SCIF1_TXI, 0xbe0),
+	INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIC5, 0xaa0),
+	INTC_VECT(PCIC5, 0xac0), INTC_VECT(PCIC5, 0xae0),
+	INTC_VECT(PCIC5, 0xb00), INTC_VECT(PCIC5, 0xb20),
+	INTC_VECT(SCIF1, 0xb80), INTC_VECT(SCIF1, 0xba0),
+	INTC_VECT(SCIF1, 0xbc0), INTC_VECT(SCIF1, 0xbe0),
 	INTC_VECT(SIOF, 0xc00), INTC_VECT(HSPI, 0xc80),
-	INTC_VECT(MMCIF_FSTAT, 0xd00), INTC_VECT(MMCIF_TRAN, 0xd20),
-	INTC_VECT(MMCIF_ERR, 0xd40), INTC_VECT(MMCIF_FRDY, 0xd60),
-	INTC_VECT(DMAC1_DMINT8, 0xd80), INTC_VECT(DMAC1_DMINT9, 0xda0),
-	INTC_VECT(DMAC1_DMINT10, 0xdc0), INTC_VECT(DMAC1_DMINT11, 0xde0),
+	INTC_VECT(MMCIF, 0xd00), INTC_VECT(MMCIF, 0xd20),
+	INTC_VECT(MMCIF, 0xd40), INTC_VECT(MMCIF, 0xd60),
+	INTC_VECT(DMAC1, 0xd80), INTC_VECT(DMAC1, 0xda0),
+	INTC_VECT(DMAC1, 0xdc0), INTC_VECT(DMAC1, 0xde0),
 	INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
 	INTC_VECT(TMU5, 0xe40),
 	INTC_VECT(SSI, 0xe80),
-	INTC_VECT(FLCTL_FLSTE, 0xf00), INTC_VECT(FLCTL_FLEND, 0xf20),
-	INTC_VECT(FLCTL_FLTRQ0, 0xf40), INTC_VECT(FLCTL_FLTRQ1, 0xf60),
-	INTC_VECT(GPIOI0, 0xf80), INTC_VECT(GPIOI1, 0xfa0),
-	INTC_VECT(GPIOI2, 0xfc0), INTC_VECT(GPIOI3, 0xfe0),
+	INTC_VECT(FLCTL, 0xf00), INTC_VECT(FLCTL, 0xf20),
+	INTC_VECT(FLCTL, 0xf40), INTC_VECT(FLCTL, 0xf60),
+	INTC_VECT(GPIO, 0xf80), INTC_VECT(GPIO, 0xfa0),
+	INTC_VECT(GPIO, 0xfc0), INTC_VECT(GPIO, 0xfe0),
 };
 
 static struct intc_group groups[] __initdata = {
-	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
 	INTC_GROUP(TMU012, TMU0, TMU1, TMU2, TMU2_TICPI),
-	INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
-		   DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE),
-	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
-	INTC_GROUP(DMAC1, DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8,
-		   DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11),
-	INTC_GROUP(PCIC5, PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0),
-	INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
-	INTC_GROUP(MMCIF, MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY),
 	INTC_GROUP(TMU345, TMU3, TMU4, TMU5),
-	INTC_GROUP(FLCTL, FLCTL_FLSTE, FLCTL_FLEND,
-		   FLCTL_FLTRQ0, FLCTL_FLTRQ1),
-	INTC_GROUP(GPIO, GPIOI0, GPIOI1, GPIOI2, GPIOI3),
 };
 
 static struct intc_mask_reg mask_registers[] __initdata = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 30baa63..d80802a 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -20,18 +20,13 @@
 		.mapbase	= 0xffea0000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 40, 41, 43, 42 },
+		.irqs		= { 40, 40, 40, 40 },
 	}, {
 		.mapbase	= 0xffeb0000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 44, 45, 47, 46 },
-	},
-
-	/*
-	 * The rest of these all have multiplexed IRQs
-	 */
-	{
+		.irqs		= { 44, 44, 44, 44 },
+	}, {
 		.mapbase	= 0xffec0000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
@@ -91,33 +86,19 @@
 	IRL4_HHLL, IRL4_HHLH, IRL4_HHHL,
 
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
-	WDT,
-	TMU0, TMU1, TMU2, TMU2_TICPI,
-	HUDI,
-	DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3,
-	DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE,
-	SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
-	SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
-	DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8, DMAC1_DMINT9,
-	DMAC1_DMINT10, DMAC1_DMINT11, DMAC1_DMAE,
-	HSPI,
+	WDT, TMU0, TMU1, TMU2, TMU2_TICPI,
+	HUDI, DMAC0, SCIF0, SCIF1, DMAC1, HSPI,
 	SCIF2, SCIF3, SCIF4, SCIF5,
-	PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD,
-	PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0,
-	SIOF,
-	MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY,
-	DU,
-	GDTA_GACLI, GDTA_GAMCI, GDTA_GAERI,
+	PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD, PCIC5,
+	SIOF, MMCIF, DU, GDTA,
 	TMU3, TMU4, TMU5,
 	SSI0, SSI1,
 	HAC0, HAC1,
-	FLCTL_FLSTE, FLCTL_FLEND, FLCTL_FLTRQ0, FLCTL_FLTRQ1,
-	GPIOI0, GPIOI1, GPIOI2, GPIOI3,
+	FLCTL, GPIO,
 
 	/* interrupt groups */
 
-	TMU012, DMAC0, SCIF0, SCIF1, DMAC1,
-	PCIC5, MMCIF, GDTA, TMU345, FLCTL, GPIO
+	TMU012,	TMU345
 };
 
 static struct intc_vect vectors[] __initdata = {
@@ -125,57 +106,45 @@
 	INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0),
 	INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0),
 	INTC_VECT(HUDI, 0x600),
-	INTC_VECT(DMAC0_DMINT0, 0x620), INTC_VECT(DMAC0_DMINT1, 0x640),
-	INTC_VECT(DMAC0_DMINT2, 0x660), INTC_VECT(DMAC0_DMINT3, 0x680),
-	INTC_VECT(DMAC0_DMINT4, 0x6a0), INTC_VECT(DMAC0_DMINT5, 0x6c0),
-	INTC_VECT(DMAC0_DMAE, 0x6e0),
-	INTC_VECT(SCIF0_ERI, 0x700), INTC_VECT(SCIF0_RXI, 0x720),
-	INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760),
-	INTC_VECT(SCIF1_ERI, 0x780), INTC_VECT(SCIF1_RXI, 0x7a0),
-	INTC_VECT(SCIF1_BRI, 0x7c0), INTC_VECT(SCIF1_TXI, 0x7e0),
-	INTC_VECT(DMAC1_DMINT6, 0x880), INTC_VECT(DMAC1_DMINT7, 0x8a0),
-	INTC_VECT(DMAC1_DMINT8, 0x8c0), INTC_VECT(DMAC1_DMINT9, 0x8e0),
-	INTC_VECT(DMAC1_DMINT10, 0x900), INTC_VECT(DMAC1_DMINT11, 0x920),
-	INTC_VECT(DMAC1_DMAE, 0x940),
+	INTC_VECT(DMAC0, 0x620), INTC_VECT(DMAC0, 0x640),
+	INTC_VECT(DMAC0, 0x660), INTC_VECT(DMAC0, 0x680),
+	INTC_VECT(DMAC0, 0x6a0), INTC_VECT(DMAC0, 0x6c0),
+	INTC_VECT(DMAC0, 0x6e0),
+	INTC_VECT(SCIF0, 0x700), INTC_VECT(SCIF0, 0x720),
+	INTC_VECT(SCIF0, 0x740), INTC_VECT(SCIF0, 0x760),
+	INTC_VECT(SCIF1, 0x780), INTC_VECT(SCIF1, 0x7a0),
+	INTC_VECT(SCIF1, 0x7c0), INTC_VECT(SCIF1, 0x7e0),
+	INTC_VECT(DMAC1, 0x880), INTC_VECT(DMAC1, 0x8a0),
+	INTC_VECT(DMAC1, 0x8c0), INTC_VECT(DMAC1, 0x8e0),
+	INTC_VECT(DMAC1, 0x900), INTC_VECT(DMAC1, 0x920),
+	INTC_VECT(DMAC1, 0x940),
 	INTC_VECT(HSPI, 0x960),
 	INTC_VECT(SCIF2, 0x980), INTC_VECT(SCIF3, 0x9a0),
 	INTC_VECT(SCIF4, 0x9c0), INTC_VECT(SCIF5, 0x9e0),
 	INTC_VECT(PCISERR, 0xa00), INTC_VECT(PCIINTA, 0xa20),
 	INTC_VECT(PCIINTB, 0xa40), INTC_VECT(PCIINTC, 0xa60),
-	INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIERR, 0xaa0),
-	INTC_VECT(PCIPWD3, 0xac0), INTC_VECT(PCIPWD2, 0xae0),
-	INTC_VECT(PCIPWD1, 0xb00), INTC_VECT(PCIPWD0, 0xb20),
+	INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIC5, 0xaa0),
+	INTC_VECT(PCIC5, 0xac0), INTC_VECT(PCIC5, 0xae0),
+	INTC_VECT(PCIC5, 0xb00), INTC_VECT(PCIC5, 0xb20),
 	INTC_VECT(SIOF, 0xc00),
-	INTC_VECT(MMCIF_FSTAT, 0xd00), INTC_VECT(MMCIF_TRAN, 0xd20),
-	INTC_VECT(MMCIF_ERR, 0xd40), INTC_VECT(MMCIF_FRDY, 0xd60),
+	INTC_VECT(MMCIF, 0xd00), INTC_VECT(MMCIF, 0xd20),
+	INTC_VECT(MMCIF, 0xd40), INTC_VECT(MMCIF, 0xd60),
 	INTC_VECT(DU, 0xd80),
-	INTC_VECT(GDTA_GACLI, 0xda0), INTC_VECT(GDTA_GAMCI, 0xdc0),
-	INTC_VECT(GDTA_GAERI, 0xde0),
+	INTC_VECT(GDTA, 0xda0), INTC_VECT(GDTA, 0xdc0),
+	INTC_VECT(GDTA, 0xde0),
 	INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
 	INTC_VECT(TMU5, 0xe40),
 	INTC_VECT(SSI0, 0xe80), INTC_VECT(SSI1, 0xea0),
 	INTC_VECT(HAC0, 0xec0), INTC_VECT(HAC1, 0xee0),
-	INTC_VECT(FLCTL_FLSTE, 0xf00), INTC_VECT(FLCTL_FLEND, 0xf20),
-	INTC_VECT(FLCTL_FLTRQ0, 0xf40), INTC_VECT(FLCTL_FLTRQ1, 0xf60),
-	INTC_VECT(GPIOI0, 0xf80), INTC_VECT(GPIOI1, 0xfa0),
-	INTC_VECT(GPIOI2, 0xfc0), INTC_VECT(GPIOI3, 0xfe0),
+	INTC_VECT(FLCTL, 0xf00), INTC_VECT(FLCTL, 0xf20),
+	INTC_VECT(FLCTL, 0xf40), INTC_VECT(FLCTL, 0xf60),
+	INTC_VECT(GPIO, 0xf80), INTC_VECT(GPIO, 0xfa0),
+	INTC_VECT(GPIO, 0xfc0), INTC_VECT(GPIO, 0xfe0),
 };
 
 static struct intc_group groups[] __initdata = {
 	INTC_GROUP(TMU012, TMU0, TMU1, TMU2, TMU2_TICPI),
-	INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
-		   DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE),
-	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
-	INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
-	INTC_GROUP(DMAC1, DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8,
-		   DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11, DMAC1_DMAE),
-	INTC_GROUP(PCIC5, PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0),
-	INTC_GROUP(MMCIF, MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY),
-	INTC_GROUP(GDTA, GDTA_GACLI, GDTA_GAMCI, GDTA_GAERI),
 	INTC_GROUP(TMU345, TMU3, TMU4, TMU5),
-	INTC_GROUP(FLCTL, FLCTL_FLSTE, FLCTL_FLEND,
-		   FLCTL_FLTRQ0, FLCTL_FLTRQ1),
-	INTC_GROUP(GPIO, GPIOI0, GPIOI1, GPIOI2, GPIOI3),
 };
 
 static struct intc_mask_reg mask_registers[] __initdata = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
new file mode 100644
index 0000000..5a47e1c
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -0,0 +1,490 @@
+/*
+ * SH7786 Setup
+ *
+ * Copyright (C) 2009  Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on SH7785 Setup
+ *
+ *  Copyright (C) 2007  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>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <asm/mmzone.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+	{
+		.mapbase	= 0xffea0000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 40, 41, 43, 42 },
+	},
+	/*
+	 * The rest of these all have multiplexed IRQs
+	 */
+	{
+		.mapbase	= 0xffeb0000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 44, 44, 44, 44 },
+	}, {
+		.mapbase	= 0xffec0000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 50, 50, 50, 50 },
+	}, {
+		.mapbase	= 0xffed0000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 51, 51, 51, 51 },
+	}, {
+		.mapbase	= 0xffee0000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 52, 52, 52, 52 },
+	}, {
+		.mapbase	= 0xffef0000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 53, 53, 53, 53 },
+	}, {
+		.flags = 0,
+	}
+};
+
+static struct platform_device sci_device = {
+	.name		= "sh-sci",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= sci_platform_data,
+	},
+};
+
+static struct resource usb_ohci_resources[] = {
+	[0] = {
+		.start	= 0xffe70400,
+		.end	= 0xffe704ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 77,
+		.end	= 77,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 usb_ohci_dma_mask = DMA_BIT_MASK(32);
+static struct platform_device usb_ohci_device = {
+	.name		= "sh_ohci",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &usb_ohci_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(usb_ohci_resources),
+	.resource	= usb_ohci_resources,
+};
+
+static struct platform_device *sh7786_devices[] __initdata = {
+	&sci_device,
+	&usb_ohci_device,
+};
+
+
+/*
+ * Please call this function if your platform board
+ * use external clock for USB
+ * */
+#define USBCTL0		0xffe70858
+#define CLOCK_MODE_MASK 0xffffff7f
+#define EXT_CLOCK_MODE  0x00000080
+void __init sh7786_usb_use_exclock(void)
+{
+	u32 val = __raw_readl(USBCTL0) & CLOCK_MODE_MASK;
+	__raw_writel(val | EXT_CLOCK_MODE, USBCTL0);
+}
+
+#define USBINITREG1	0xffe70094
+#define USBINITREG2	0xffe7009c
+#define USBINITVAL1	0x00ff0040
+#define USBINITVAL2	0x00000001
+
+#define USBPCTL1	0xffe70804
+#define USBST		0xffe70808
+#define PHY_ENB		0x00000001
+#define PLL_ENB		0x00000002
+#define PHY_RST		0x00000004
+#define ACT_PLL_STATUS	0xc0000000
+static void __init sh7786_usb_setup(void)
+{
+	int i = 1000000;
+
+	/*
+	 * USB initial settings
+	 *
+	 * The following settings are necessary
+	 * for using the USB modules.
+	 *
+	 * see "USB Inital Settings" for detail
+	 */
+	__raw_writel(USBINITVAL1, USBINITREG1);
+	__raw_writel(USBINITVAL2, USBINITREG2);
+
+	/*
+	 * Set the PHY and PLL enable bit
+	 */
+	__raw_writel(PHY_ENB | PLL_ENB, USBPCTL1);
+	while (i-- &&
+	       ((__raw_readl(USBST) & ACT_PLL_STATUS) != ACT_PLL_STATUS))
+		cpu_relax();
+
+	if (i) {
+		/* Set the PHY RST bit */
+		__raw_writel(PHY_ENB | PLL_ENB | PHY_RST, USBPCTL1);
+		printk(KERN_INFO "sh7786 usb setup done\n");
+	}
+}
+
+static int __init sh7786_devices_setup(void)
+{
+	sh7786_usb_setup();
+	return platform_add_devices(sh7786_devices,
+				    ARRAY_SIZE(sh7786_devices));
+}
+device_initcall(sh7786_devices_setup);
+
+enum {
+	UNUSED = 0,
+
+	/* interrupt sources */
+
+	IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+	IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+	IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+	IRL0_HHLL, IRL0_HHLH, IRL0_HHHL,
+
+	IRL4_LLLL, IRL4_LLLH, IRL4_LLHL, IRL4_LLHH,
+	IRL4_LHLL, IRL4_LHLH, IRL4_LHHL, IRL4_LHHH,
+	IRL4_HLLL, IRL4_HLLH, IRL4_HLHL, IRL4_HLHH,
+	IRL4_HHLL, IRL4_HHLH, IRL4_HHHL,
+
+	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+	WDT,
+	TMU0_0, TMU0_1, TMU0_2, TMU0_3,
+	TMU1_0, TMU1_1, TMU1_2,
+	DMAC0_0, DMAC0_1, DMAC0_2, DMAC0_3, DMAC0_4, DMAC0_5, DMAC0_6,
+	HUDI1, HUDI0,
+	DMAC1_0, DMAC1_1, DMAC1_2, DMAC1_3,
+	HPB_0, HPB_1, HPB_2,
+	SCIF0_0, SCIF0_1, SCIF0_2, SCIF0_3,
+	SCIF1,
+	TMU2, TMU3,
+	SCIF2, SCIF3, SCIF4, SCIF5,
+	Eth_0, Eth_1,
+	PCIeC0_0, PCIeC0_1, PCIeC0_2,
+	PCIeC1_0, PCIeC1_1, PCIeC1_2,
+	USB,
+	I2C0, I2C1,
+	DU,
+	SSI0, SSI1, SSI2, SSI3,
+	PCIeC2_0, PCIeC2_1, PCIeC2_2,
+	HAC0, HAC1,
+	FLCTL,
+	HSPI,
+	GPIO0, GPIO1,
+	Thermal,
+	INTC0, INTC1, INTC2, INTC3, INTC4, INTC5, INTC6, INTC7,
+
+	/* interrupt groups */
+};
+
+static struct intc_vect vectors[] __initdata = {
+	INTC_VECT(WDT, 0x3e0),
+	INTC_VECT(TMU0_0, 0x400), INTC_VECT(TMU0_1, 0x420),
+	INTC_VECT(TMU0_2, 0x440), INTC_VECT(TMU0_3, 0x460),
+	INTC_VECT(TMU1_0, 0x480), INTC_VECT(TMU1_1, 0x4a0),
+	INTC_VECT(TMU1_2, 0x4c0),
+	INTC_VECT(DMAC0_0, 0x500), INTC_VECT(DMAC0_1, 0x520),
+	INTC_VECT(DMAC0_2, 0x540), INTC_VECT(DMAC0_3, 0x560),
+	INTC_VECT(DMAC0_4, 0x580), INTC_VECT(DMAC0_5, 0x5a0),
+	INTC_VECT(DMAC0_6, 0x5c0),
+	INTC_VECT(HUDI1, 0x5e0), INTC_VECT(HUDI0, 0x600),
+	INTC_VECT(DMAC1_0, 0x620), INTC_VECT(DMAC1_1, 0x640),
+	INTC_VECT(DMAC1_2, 0x660), INTC_VECT(DMAC1_3, 0x680),
+	INTC_VECT(HPB_0, 0x6a0), INTC_VECT(HPB_1, 0x6c0),
+	INTC_VECT(HPB_2, 0x6e0),
+	INTC_VECT(SCIF0_0, 0x700), INTC_VECT(SCIF0_1, 0x720),
+	INTC_VECT(SCIF0_2, 0x740), INTC_VECT(SCIF0_3, 0x760),
+	INTC_VECT(SCIF1, 0x780),
+	INTC_VECT(TMU2, 0x7a0), INTC_VECT(TMU3, 0x7c0),
+	INTC_VECT(SCIF2, 0x840), INTC_VECT(SCIF3, 0x860),
+	INTC_VECT(SCIF4, 0x880), INTC_VECT(SCIF5, 0x8a0),
+	INTC_VECT(Eth_0, 0x8c0), INTC_VECT(Eth_1, 0x8e0),
+	INTC_VECT(PCIeC0_0, 0xae0), INTC_VECT(PCIeC0_1, 0xb00),
+	INTC_VECT(PCIeC0_2, 0xb20),
+	INTC_VECT(PCIeC1_0, 0xb40), INTC_VECT(PCIeC1_1, 0xb60),
+	INTC_VECT(PCIeC1_2, 0xb80),
+	INTC_VECT(USB, 0xba0),
+	INTC_VECT(I2C0, 0xcc0), INTC_VECT(I2C1, 0xce0),
+	INTC_VECT(DU, 0xd00),
+	INTC_VECT(SSI0, 0xd20), INTC_VECT(SSI1, 0xd40),
+	INTC_VECT(SSI2, 0xd60), INTC_VECT(SSI3, 0xd80),
+	INTC_VECT(PCIeC2_0, 0xda0), INTC_VECT(PCIeC2_1, 0xdc0),
+	INTC_VECT(PCIeC2_2, 0xde0),
+	INTC_VECT(HAC0, 0xe00), INTC_VECT(HAC1, 0xe20),
+	INTC_VECT(FLCTL, 0xe40),
+	INTC_VECT(HSPI, 0xe80),
+	INTC_VECT(GPIO0, 0xea0), INTC_VECT(GPIO1, 0xec0),
+	INTC_VECT(Thermal, 0xee0),
+};
+
+/* FIXME: Main CPU support only now */
+#if 1 /* Main CPU */
+#define CnINTMSK0	0xfe410030
+#define CnINTMSK1	0xfe410040
+#define CnINTMSKCLR0	0xfe410050
+#define CnINTMSKCLR1	0xfe410060
+#define CnINT2MSKR0	0xfe410a20
+#define CnINT2MSKR1	0xfe410a24
+#define CnINT2MSKR2	0xfe410a28
+#define CnINT2MSKR3	0xfe410a2c
+#define CnINT2MSKCR0	0xfe410a30
+#define CnINT2MSKCR1	0xfe410a34
+#define CnINT2MSKCR2	0xfe410a38
+#define CnINT2MSKCR3	0xfe410a3c
+#else /* Sub CPU */
+#define CnINTMSK0	0xfe410034
+#define CnINTMSK1	0xfe410044
+#define CnINTMSKCLR0	0xfe410054
+#define CnINTMSKCLR1	0xfe410064
+#define CnINT2MSKR0	0xfe410b20
+#define CnINT2MSKR1	0xfe410b24
+#define CnINT2MSKR2	0xfe410b28
+#define CnINT2MSKR3	0xfe410b2c
+#define CnINT2MSKCR0	0xfe410b30
+#define CnINT2MSKCR1	0xfe410b34
+#define CnINT2MSKCR2	0xfe410b38
+#define CnINT2MSKCR3	0xfe410b3c
+#endif
+
+#define INTMSK2		0xfe410068
+#define INTMSKCLR2	0xfe41006c
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+	{ CnINTMSK0, CnINTMSKCLR0, 32,
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+	{ INTMSK2, INTMSKCLR2, 32,
+	  { IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+	    IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+	    IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+	    IRL0_HHLL, IRL0_HHLH, IRL0_HHHL, 0,
+	    IRL4_LLLL, IRL4_LLLH, IRL4_LLHL, IRL4_LLHH,
+	    IRL4_LHLL, IRL4_LHLH, IRL4_LHHL, IRL4_LHHH,
+	    IRL4_HLLL, IRL4_HLLH, IRL4_HLHL, IRL4_HLHH,
+	    IRL4_HHLL, IRL4_HHLH, IRL4_HHHL, 0, } },
+	{ CnINT2MSKR0, CnINT2MSKCR0 , 32,
+	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WDT } },
+	{ CnINT2MSKR1, CnINT2MSKCR1, 32,
+	  { TMU0_0, TMU0_1, TMU0_2, TMU0_3, TMU1_0, TMU1_1, TMU1_2, 0,
+	    DMAC0_0, DMAC0_1, DMAC0_2, DMAC0_3, DMAC0_4, DMAC0_5, DMAC0_6,
+	    HUDI1, HUDI0,
+	    DMAC1_0, DMAC1_1, DMAC1_2, DMAC1_3,
+	    HPB_0, HPB_1, HPB_2,
+	    SCIF0_0, SCIF0_1, SCIF0_2, SCIF0_3,
+	    SCIF1,
+	    TMU2, TMU3, 0, } },
+	{ CnINT2MSKR2, CnINT2MSKCR2, 32,
+	  { 0, 0, SCIF2, SCIF3, SCIF4, SCIF5,
+	    Eth_0, Eth_1,
+	    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    PCIeC0_0, PCIeC0_1, PCIeC0_2,
+	    PCIeC1_0, PCIeC1_1, PCIeC1_2,
+	    USB, 0, 0 } },
+	{ CnINT2MSKR3, CnINT2MSKCR3, 32,
+	  { 0, 0, 0, 0, 0, 0,
+	    I2C0, I2C1,
+	    DU, SSI0, SSI1, SSI2, SSI3,
+	    PCIeC2_0, PCIeC2_1, PCIeC2_2,
+	    HAC0, HAC1,
+	    FLCTL, 0,
+	    HSPI, GPIO0, GPIO1, Thermal,
+	    0, 0, 0, 0, 0, 0, 0, 0 } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+	{ 0xfe410010, 0, 32, 4, /* INTPRI */   { IRQ0, IRQ1, IRQ2, IRQ3,
+						 IRQ4, IRQ5, IRQ6, IRQ7 } },
+	{ 0xfe410800, 0, 32, 8, /* INT2PRI0 */ { 0, 0, 0, WDT } },
+	{ 0xfe410804, 0, 32, 8, /* INT2PRI1 */ { TMU0_0, TMU0_1,
+						 TMU0_2, TMU0_3 } },
+	{ 0xfe410808, 0, 32, 8, /* INT2PRI2 */ { TMU1_0, TMU1_1,
+						 TMU1_2, 0 } },
+	{ 0xfe41080c, 0, 32, 8, /* INT2PRI3 */ { DMAC0_0, DMAC0_1,
+						 DMAC0_2, DMAC0_3 } },
+	{ 0xfe410810, 0, 32, 8, /* INT2PRI4 */ { DMAC0_4, DMAC0_5,
+						 DMAC0_6, HUDI1 } },
+	{ 0xfe410814, 0, 32, 8, /* INT2PRI5 */ { HUDI0, DMAC1_0,
+						 DMAC1_1, DMAC1_2 } },
+	{ 0xfe410818, 0, 32, 8, /* INT2PRI6 */ { DMAC1_3, HPB_0,
+						 HPB_1, HPB_2 } },
+	{ 0xfe41081c, 0, 32, 8, /* INT2PRI7 */ { SCIF0_0, SCIF0_1,
+						 SCIF0_2, SCIF0_3 } },
+	{ 0xfe410820, 0, 32, 8, /* INT2PRI8 */ { SCIF1, TMU2, TMU3, 0 } },
+	{ 0xfe410824, 0, 32, 8, /* INT2PRI9 */ { 0, 0, SCIF2, SCIF3 } },
+	{ 0xfe410828, 0, 32, 8, /* INT2PRI10 */ { SCIF4, SCIF5,
+						  Eth_0, Eth_1 } },
+	{ 0xfe41082c, 0, 32, 8, /* INT2PRI11 */ { 0, 0, 0, 0 } },
+	{ 0xfe410830, 0, 32, 8, /* INT2PRI12 */ { 0, 0, 0, 0 } },
+	{ 0xfe410834, 0, 32, 8, /* INT2PRI13 */ { 0, 0, 0, 0 } },
+	{ 0xfe410838, 0, 32, 8, /* INT2PRI14 */ { 0, 0, 0, PCIeC0_0 } },
+	{ 0xfe41083c, 0, 32, 8, /* INT2PRI15 */ { PCIeC0_1, PCIeC0_2,
+						  PCIeC1_0, PCIeC1_1 } },
+	{ 0xfe410840, 0, 32, 8, /* INT2PRI16 */ { PCIeC1_2, USB, 0, 0 } },
+	{ 0xfe410844, 0, 32, 8, /* INT2PRI17 */ { 0, 0, 0, 0 } },
+	{ 0xfe410848, 0, 32, 8, /* INT2PRI18 */ { 0, 0, I2C0, I2C1 } },
+	{ 0xfe41084c, 0, 32, 8, /* INT2PRI19 */ { DU, SSI0, SSI1, SSI2 } },
+	{ 0xfe410850, 0, 32, 8, /* INT2PRI20 */ { SSI3, PCIeC2_0,
+						  PCIeC2_1, PCIeC2_2 } },
+	{ 0xfe410854, 0, 32, 8, /* INT2PRI21 */ { HAC0, HAC1, FLCTL, 0 } },
+	{ 0xfe410858, 0, 32, 8, /* INT2PRI22 */ { HSPI, GPIO0,
+						  GPIO1, Thermal } },
+	{ 0xfe41085c, 0, 32, 8, /* INT2PRI23 */ { 0, 0, 0, 0 } },
+	{ 0xfe410860, 0, 32, 8, /* INT2PRI24 */ { 0, 0, 0, 0 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7786", vectors, NULL,
+			 mask_registers, prio_registers, NULL);
+
+/* Support for external interrupt pins in IRQ mode */
+
+static struct intc_vect vectors_irq0123[] __initdata = {
+	INTC_VECT(IRQ0, 0x200), INTC_VECT(IRQ1, 0x240),
+	INTC_VECT(IRQ2, 0x280), INTC_VECT(IRQ3, 0x2c0),
+};
+
+static struct intc_vect vectors_irq4567[] __initdata = {
+	INTC_VECT(IRQ4, 0x300), INTC_VECT(IRQ5, 0x340),
+	INTC_VECT(IRQ6, 0x380), INTC_VECT(IRQ7, 0x3c0),
+};
+
+static struct intc_sense_reg sense_registers[] __initdata = {
+	{ 0xfe41001c, 32, 2, /* ICR1 */   { IRQ0, IRQ1, IRQ2, IRQ3,
+					    IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_mask_reg ack_registers[] __initdata = {
+	{ 0xfe410024, 0, 32, /* INTREQ */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh7786-irq0123",
+			     vectors_irq0123, NULL, mask_registers,
+			     prio_registers, sense_registers, ack_registers);
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq4567, "sh7786-irq4567",
+			     vectors_irq4567, NULL, mask_registers,
+			     prio_registers, sense_registers, ack_registers);
+
+/* External interrupt pins in IRL mode */
+
+static struct intc_vect vectors_irl0123[] __initdata = {
+	INTC_VECT(IRL0_LLLL, 0x200), INTC_VECT(IRL0_LLLH, 0x220),
+	INTC_VECT(IRL0_LLHL, 0x240), INTC_VECT(IRL0_LLHH, 0x260),
+	INTC_VECT(IRL0_LHLL, 0x280), INTC_VECT(IRL0_LHLH, 0x2a0),
+	INTC_VECT(IRL0_LHHL, 0x2c0), INTC_VECT(IRL0_LHHH, 0x2e0),
+	INTC_VECT(IRL0_HLLL, 0x300), INTC_VECT(IRL0_HLLH, 0x320),
+	INTC_VECT(IRL0_HLHL, 0x340), INTC_VECT(IRL0_HLHH, 0x360),
+	INTC_VECT(IRL0_HHLL, 0x380), INTC_VECT(IRL0_HHLH, 0x3a0),
+	INTC_VECT(IRL0_HHHL, 0x3c0),
+};
+
+static struct intc_vect vectors_irl4567[] __initdata = {
+	INTC_VECT(IRL4_LLLL, 0x900), INTC_VECT(IRL4_LLLH, 0x920),
+	INTC_VECT(IRL4_LLHL, 0x940), INTC_VECT(IRL4_LLHH, 0x960),
+	INTC_VECT(IRL4_LHLL, 0x980), INTC_VECT(IRL4_LHLH, 0x9a0),
+	INTC_VECT(IRL4_LHHL, 0x9c0), INTC_VECT(IRL4_LHHH, 0x9e0),
+	INTC_VECT(IRL4_HLLL, 0xa00), INTC_VECT(IRL4_HLLH, 0xa20),
+	INTC_VECT(IRL4_HLHL, 0xa40), INTC_VECT(IRL4_HLHH, 0xa60),
+	INTC_VECT(IRL4_HHLL, 0xa80), INTC_VECT(IRL4_HHLH, 0xaa0),
+	INTC_VECT(IRL4_HHHL, 0xac0),
+};
+
+static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7786-irl0123", vectors_irl0123,
+			 NULL, mask_registers, NULL, NULL);
+
+static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567,
+			 NULL, mask_registers, NULL, NULL);
+
+#define INTC_ICR0	0xfe410000
+#define INTC_INTMSK0	CnINTMSK0
+#define INTC_INTMSK1	CnINTMSK1
+#define INTC_INTMSK2	INTMSK2
+#define INTC_INTMSKCLR1	CnINTMSKCLR1
+#define INTC_INTMSKCLR2	INTMSKCLR2
+
+void __init plat_irq_setup(void)
+{
+	/* disable IRQ3-0 + IRQ7-4 */
+	ctrl_outl(0xff000000, INTC_INTMSK0);
+
+	/* disable IRL3-0 + IRL7-4 */
+	ctrl_outl(0xc0000000, INTC_INTMSK1);
+	ctrl_outl(0xfffefffe, INTC_INTMSK2);
+
+	/* select IRL mode for IRL3-0 + IRL7-4 */
+	ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+
+	register_intc_controller(&intc_desc);
+}
+
+void __init plat_irq_setup_pins(int mode)
+{
+	switch (mode) {
+	case IRQ_MODE_IRQ7654:
+		/* select IRQ mode for IRL7-4 */
+		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0);
+		register_intc_controller(&intc_desc_irq4567);
+		break;
+	case IRQ_MODE_IRQ3210:
+		/* select IRQ mode for IRL3-0 */
+		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+		register_intc_controller(&intc_desc_irq0123);
+		break;
+	case IRQ_MODE_IRL7654:
+		/* enable IRL7-4 but don't provide any masking */
+		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+		break;
+	case IRQ_MODE_IRL3210:
+		/* enable IRL0-3 but don't provide any masking */
+		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+		break;
+	case IRQ_MODE_IRL7654_MASK:
+		/* enable IRL7-4 and mask using cpu intc controller */
+		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		register_intc_controller(&intc_desc_irl4567);
+		break;
+	case IRQ_MODE_IRL3210_MASK:
+		/* enable IRL0-3 and mask using cpu intc controller */
+		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		register_intc_controller(&intc_desc_irl0123);
+		break;
+	default:
+		BUG();
+	}
+}
+
+void __init plat_mem_setup(void)
+{
+}
diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile
new file mode 100644
index 0000000..08bfa7c
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Linux/SuperH SH-Mobile backends.
+#
+
+# Power Management & Sleep mode
+obj-$(CONFIG_PM)	+= pm.o sleep.o
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
new file mode 100644
index 0000000..8c067ad
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -0,0 +1,92 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c
+ *
+ * Power management support code for SuperH Mobile
+ *
+ *  Copyright (C) 2009 Magnus Damm
+ *
+ * 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/kernel.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+#include <asm/suspend.h>
+#include <asm/uaccess.h>
+
+/*
+ * Sleep modes available on SuperH Mobile:
+ *
+ * Sleep mode is just plain "sleep" instruction
+ * Sleep Self-Refresh mode is above plus RAM put in Self-Refresh
+ * Standby Self-Refresh mode is above plus stopped clocks
+ */
+#define SUSP_MODE_SLEEP		(SUSP_SH_SLEEP)
+#define SUSP_MODE_SLEEP_SF	(SUSP_SH_SLEEP | SUSP_SH_SF)
+#define SUSP_MODE_STANDBY_SF	(SUSP_SH_STANDBY | SUSP_SH_SF)
+
+/*
+ * The following modes are not there yet:
+ *
+ * R-standby mode is unsupported, but will be added in the future
+ * U-standby mode is low priority since it needs bootloader hacks
+ *
+ * All modes should be tied in with cpuidle. But before that can
+ * happen we need to keep track of enabled hardware blocks so we
+ * can avoid entering sleep modes that stop clocks to hardware
+ * blocks that are in use even though the cpu core is idle.
+ */
+
+extern const unsigned char sh_mobile_standby[];
+extern const unsigned int sh_mobile_standby_size;
+
+static void sh_mobile_call_standby(unsigned long mode)
+{
+	extern void *vbr_base;
+	void *onchip_mem = (void *)0xe5200000; /* ILRAM */
+	void (*standby_onchip_mem)(unsigned long) = onchip_mem;
+
+	/* Note: Wake up from sleep may generate exceptions!
+	 * Setup VBR to point to on-chip ram if self-refresh is
+	 * going to be used.
+	 */
+	if (mode & SUSP_SH_SF)
+		asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory");
+
+	/* Copy the assembly snippet to the otherwise ununsed ILRAM */
+	memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
+	wmb();
+	ctrl_barrier();
+
+	/* Let assembly snippet in on-chip memory handle the rest */
+	standby_onchip_mem(mode);
+
+	/* Put VBR back in System RAM again */
+	if (mode & SUSP_SH_SF)
+		asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory");
+}
+
+static int sh_pm_enter(suspend_state_t state)
+{
+	local_irq_disable();
+	set_bl_bit();
+	sh_mobile_call_standby(SUSP_MODE_STANDBY_SF);
+	local_irq_disable();
+	clear_bl_bit();
+	return 0;
+}
+
+static struct platform_suspend_ops sh_pm_ops = {
+	.enter          = sh_pm_enter,
+	.valid          = suspend_valid_only_mem,
+};
+
+static int __init sh_pm_init(void)
+{
+	suspend_set_ops(&sh_pm_ops);
+	return 0;
+}
+
+late_initcall(sh_pm_init);
diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S
new file mode 100644
index 0000000..5d888ef
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/sleep.S
@@ -0,0 +1,125 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
+ *
+ * Sleep mode and Standby modes support for SuperH Mobile
+ *
+ *  Copyright (C) 2009 Magnus Damm
+ *
+ * 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/sys.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/suspend.h>
+
+/* manage self-refresh and enter standby mode.
+ * this code will be copied to on-chip memory and executed from there.
+ */
+
+	.balign 	4096,0,4096
+ENTRY(sh_mobile_standby)
+	mov	r4, r0
+
+	tst	#SUSP_SH_SF, r0
+	bt	skip_set_sf
+
+	/* SDRAM: disable power down and put in self-refresh mode */
+	mov.l	1f, r4
+	mov.l	2f, r1
+	mov.l	@r4, r2
+	or	r1, r2
+	mov.l   3f, r3
+	and	r3, r2
+	mov.l	r2, @r4
+
+skip_set_sf:
+	tst	#SUSP_SH_SLEEP, r0
+	bt	test_standby
+
+	/* set mode to "sleep mode" */
+	bra	do_sleep
+	 mov	#0x00, r1
+
+test_standby:
+	tst	#SUSP_SH_STANDBY, r0
+	bt	test_rstandby
+
+	/* set mode to "software standby mode" */
+	bra	do_sleep
+	 mov	#0x80, r1
+
+test_rstandby:
+	tst	#SUSP_SH_RSTANDBY, r0
+	bt	test_ustandby
+
+	/* set mode to "r-standby mode" */
+	bra	do_sleep
+	 mov	#0x20, r1
+
+test_ustandby:
+	tst	#SUSP_SH_USTANDBY, r0
+	bt	done_sleep
+
+	/* set mode to "u-standby mode" */
+	mov	#0x10, r1
+
+	/* fall-through */
+
+do_sleep:
+	/* setup and enter selected standby mode */
+	mov.l	5f, r4
+	mov.l	r1, @r4
+	sleep
+
+done_sleep:
+	/* reset standby mode to sleep mode */
+	mov.l	5f, r4
+	mov	#0x00, r1
+	mov.l	r1, @r4
+
+	tst	#SUSP_SH_SF, r0
+	bt	skip_restore_sf
+
+	/* SDRAM: set auto-refresh mode */
+	mov.l	1f, r4
+	mov.l	@r4, r2
+	mov.l   4f, r3
+	and	r3, r2
+	mov.l	r2, @r4
+	mov.l	6f, r4
+	mov.l	7f, r1
+	mov.l	8f, r2
+	mov.l	@r4, r3
+	mov	#-1, r4
+	add	r4, r3
+	or	r2, r3
+	mov.l	r3, @r1
+skip_restore_sf:
+	rts
+	 nop
+
+	.balign 4
+1:	.long	0xfe400008 /* SDCR0 */
+2:	.long	0x00000400
+3:	.long	0xffff7fff
+4:	.long	0xfffffbff
+5:	.long	0xa4150020 /* STBCR */
+6:	.long   0xfe40001c /* RTCOR */
+7:	.long   0xfe400018 /* RTCNT */
+8:	.long   0xa55a0000
+
+/* interrupt vector @ 0x600 */
+	.balign 	0x400,0,0x400
+	.long	0xdeadbeef
+	.balign 	0x200,0,0x200
+	/* sh7722 will end up here in sleep mode */
+	rte
+	 nop
+sh_mobile_standby_end:
+
+ENTRY(sh_mobile_standby_size)
+	.long sh_mobile_standby_end - sh_mobile_standby
diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c
index d371653..d22e5af 100644
--- a/arch/sh/kernel/gpio.c
+++ b/arch/sh/kernel/gpio.c
@@ -19,22 +19,6 @@
 #include <linux/bitops.h>
 #include <linux/gpio.h>
 
-static struct pinmux_info *registered_gpio;
-
-static struct pinmux_info *gpio_controller(unsigned gpio)
-{
-	if (!registered_gpio)
-		return NULL;
-
-	if (gpio < registered_gpio->first_gpio)
-		return NULL;
-
-	if (gpio > registered_gpio->last_gpio)
-		return NULL;
-
-	return registered_gpio;
-}
-
 static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
 {
 	if (enum_id < r->begin)
@@ -46,9 +30,64 @@
 	return 1;
 }
 
-static int read_write_reg(unsigned long reg, unsigned long reg_width,
-			  unsigned long field_width, unsigned long in_pos,
-			  unsigned long value, int do_write)
+static unsigned long gpio_read_raw_reg(unsigned long reg,
+				       unsigned long reg_width)
+{
+	switch (reg_width) {
+	case 8:
+		return ctrl_inb(reg);
+	case 16:
+		return ctrl_inw(reg);
+	case 32:
+		return ctrl_inl(reg);
+	}
+
+	BUG();
+	return 0;
+}
+
+static void gpio_write_raw_reg(unsigned long reg,
+			       unsigned long reg_width,
+			       unsigned long data)
+{
+	switch (reg_width) {
+	case 8:
+		ctrl_outb(data, reg);
+		return;
+	case 16:
+		ctrl_outw(data, reg);
+		return;
+	case 32:
+		ctrl_outl(data, reg);
+		return;
+	}
+
+	BUG();
+}
+
+static void gpio_write_bit(struct pinmux_data_reg *dr,
+			   unsigned long in_pos, unsigned long value)
+{
+	unsigned long pos;
+
+	pos = dr->reg_width - (in_pos + 1);
+
+#ifdef DEBUG
+	pr_info("write_bit addr = %lx, value = %ld, pos = %ld, "
+		"r_width = %ld\n",
+		dr->reg, !!value, pos, dr->reg_width);
+#endif
+
+	if (value)
+		set_bit(pos, &dr->reg_shadow);
+	else
+		clear_bit(pos, &dr->reg_shadow);
+
+	gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow);
+}
+
+static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
+			 unsigned long field_width, unsigned long in_pos)
 {
 	unsigned long data, mask, pos;
 
@@ -57,52 +96,53 @@
 	pos = reg_width - ((in_pos + 1) * field_width);
 
 #ifdef DEBUG
-	pr_info("%s, addr = %lx, value = %ld, pos = %ld, "
+	pr_info("read_reg: addr = %lx, pos = %ld, "
 		"r_width = %ld, f_width = %ld\n",
-		do_write ? "write" : "read", reg, value, pos,
-		reg_width, field_width);
+		reg, pos, reg_width, field_width);
 #endif
 
-	switch (reg_width) {
-	case 8:
-		data = ctrl_inb(reg);
-		break;
-	case 16:
-		data = ctrl_inw(reg);
-		break;
-	case 32:
-		data = ctrl_inl(reg);
-		break;
-	}
-
-	if (!do_write)
-		return (data >> pos) & mask;
-
-	data &= ~(mask << pos);
-	data |= value << pos;
-
-	switch (reg_width) {
-	case 8:
-		ctrl_outb(data, reg);
-		break;
-	case 16:
-		ctrl_outw(data, reg);
-		break;
-	case 32:
-		ctrl_outl(data, reg);
-		break;
-	}
-	return 0;
+	data = gpio_read_raw_reg(reg, reg_width);
+	return (data >> pos) & mask;
 }
 
-static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
-			struct pinmux_data_reg **drp, int *bitp)
+static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
+			   unsigned long field_width, unsigned long in_pos,
+			   unsigned long value)
 {
-	pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id;
+	unsigned long mask, pos;
+
+	mask = (1 << field_width) - 1;
+	pos = reg_width - ((in_pos + 1) * field_width);
+
+#ifdef DEBUG
+	pr_info("write_reg addr = %lx, value = %ld, pos = %ld, "
+		"r_width = %ld, f_width = %ld\n",
+		reg, value, pos, reg_width, field_width);
+#endif
+
+	mask = ~(mask << pos);
+	value = value << pos;
+
+	switch (reg_width) {
+	case 8:
+		ctrl_outb((ctrl_inb(reg) & mask) | value, reg);
+		break;
+	case 16:
+		ctrl_outw((ctrl_inw(reg) & mask) | value, reg);
+		break;
+	case 32:
+		ctrl_outl((ctrl_inl(reg) & mask) | value, reg);
+		break;
+	}
+}
+
+static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
+{
+	struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
 	struct pinmux_data_reg *data_reg;
 	int k, n;
 
-	if (!enum_in_range(enum_id, &gpioc->data))
+	if (!enum_in_range(gpiop->enum_id, &gpioc->data))
 		return -1;
 
 	k = 0;
@@ -113,19 +153,58 @@
 			break;
 
 		for (n = 0; n < data_reg->reg_width; n++) {
-			if (data_reg->enum_ids[n] == enum_id) {
-				*drp = data_reg;
-				*bitp = n;
+			if (data_reg->enum_ids[n] == gpiop->enum_id) {
+				gpiop->flags &= ~PINMUX_FLAG_DREG;
+				gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
+				gpiop->flags &= ~PINMUX_FLAG_DBIT;
+				gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
 				return 0;
-
 			}
 		}
 		k++;
 	}
 
+	BUG();
+
 	return -1;
 }
 
+static void setup_data_regs(struct pinmux_info *gpioc)
+{
+	struct pinmux_data_reg *drp;
+	int k;
+
+	for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++)
+		setup_data_reg(gpioc, k);
+
+	k = 0;
+	while (1) {
+		drp = gpioc->data_regs + k;
+
+		if (!drp->reg_width)
+			break;
+
+		drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width);
+		k++;
+	}
+}
+
+static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
+			struct pinmux_data_reg **drp, int *bitp)
+{
+	struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
+	int k, n;
+
+	if (!enum_in_range(gpiop->enum_id, &gpioc->data))
+		return -1;
+
+	k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
+	n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
+	*drp = gpioc->data_regs + k;
+	*bitp = n;
+	return 0;
+}
+
 static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
 			  struct pinmux_cfg_reg **crp, int *indexp,
 			  unsigned long **cntp)
@@ -187,9 +266,9 @@
 	return -1;
 }
 
-static int write_config_reg(struct pinmux_info *gpioc,
-			    struct pinmux_cfg_reg *crp,
-			    int index)
+static void write_config_reg(struct pinmux_info *gpioc,
+			     struct pinmux_cfg_reg *crp,
+			     int index)
 {
 	unsigned long ncomb, pos, value;
 
@@ -197,8 +276,7 @@
 	pos = index / ncomb;
 	value = index % ncomb;
 
-	return read_write_reg(crp->reg, crp->reg_width,
-			      crp->field_width, pos, value, 1);
+	gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value);
 }
 
 static int check_config_reg(struct pinmux_info *gpioc,
@@ -211,8 +289,8 @@
 	pos = index / ncomb;
 	value = index % ncomb;
 
-	if (read_write_reg(crp->reg, crp->reg_width,
-			   crp->field_width, pos, 0, 0) == value)
+	if (gpio_read_reg(crp->reg, crp->reg_width,
+			  crp->field_width, pos) == value)
 		return 0;
 
 	return -1;
@@ -220,8 +298,8 @@
 
 enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
 
-int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
-		       int pinmux_type, int cfg_mode)
+static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
+			      int pinmux_type, int cfg_mode)
 {
 	struct pinmux_cfg_reg *cr = NULL;
 	pinmux_enum_t enum_id;
@@ -287,8 +365,7 @@
 			break;
 
 		case GPIO_CFG_REQ:
-			if (write_config_reg(gpioc, cr, index) != 0)
-				goto out_err;
+			write_config_reg(gpioc, cr, index);
 			*cntp = *cntp + 1;
 			break;
 
@@ -305,9 +382,14 @@
 
 static DEFINE_SPINLOCK(gpio_lock);
 
-int __gpio_request(unsigned gpio)
+static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip)
 {
-	struct pinmux_info *gpioc = gpio_controller(gpio);
+	return container_of(chip, struct pinmux_info, chip);
+}
+
+static int sh_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct pinmux_info *gpioc = chip_to_pinmux(chip);
 	struct pinmux_data_reg *dummy;
 	unsigned long flags;
 	int i, ret, pinmux_type;
@@ -319,29 +401,30 @@
 
 	spin_lock_irqsave(&gpio_lock, flags);
 
-	if ((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
+	if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
 		goto err_unlock;
 
 	/* setup pin function here if no data is associated with pin */
 
-	if (get_data_reg(gpioc, gpio, &dummy, &i) != 0)
+	if (get_data_reg(gpioc, offset, &dummy, &i) != 0)
 		pinmux_type = PINMUX_TYPE_FUNCTION;
 	else
 		pinmux_type = PINMUX_TYPE_GPIO;
 
 	if (pinmux_type == PINMUX_TYPE_FUNCTION) {
-		if (pinmux_config_gpio(gpioc, gpio,
+		if (pinmux_config_gpio(gpioc, offset,
 				       pinmux_type,
 				       GPIO_CFG_DRYRUN) != 0)
 			goto err_unlock;
 
-		if (pinmux_config_gpio(gpioc, gpio,
+		if (pinmux_config_gpio(gpioc, offset,
 				       pinmux_type,
 				       GPIO_CFG_REQ) != 0)
 			BUG();
 	}
 
-	gpioc->gpios[gpio].flags = pinmux_type;
+	gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
+	gpioc->gpios[offset].flags |= pinmux_type;
 
 	ret = 0;
  err_unlock:
@@ -349,11 +432,10 @@
  err_out:
 	return ret;
 }
-EXPORT_SYMBOL(__gpio_request);
 
-void gpio_free(unsigned gpio)
+static void sh_gpio_free(struct gpio_chip *chip, unsigned offset)
 {
-	struct pinmux_info *gpioc = gpio_controller(gpio);
+	struct pinmux_info *gpioc = chip_to_pinmux(chip);
 	unsigned long flags;
 	int pinmux_type;
 
@@ -362,20 +444,23 @@
 
 	spin_lock_irqsave(&gpio_lock, flags);
 
-	pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
-	pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
-	gpioc->gpios[gpio].flags = PINMUX_TYPE_NONE;
+	pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE;
+	pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE);
+	gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
+	gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE;
 
 	spin_unlock_irqrestore(&gpio_lock, flags);
 }
-EXPORT_SYMBOL(gpio_free);
 
 static int pinmux_direction(struct pinmux_info *gpioc,
 			    unsigned gpio, int new_pinmux_type)
 {
-	int ret, pinmux_type;
+	int pinmux_type;
+	int ret = -EINVAL;
 
-	ret = -EINVAL;
+	if (!gpioc)
+		goto err_out;
+
 	pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
 
 	switch (pinmux_type) {
@@ -401,102 +486,99 @@
 			       GPIO_CFG_REQ) != 0)
 		BUG();
 
-	gpioc->gpios[gpio].flags = new_pinmux_type;
+	gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
+	gpioc->gpios[gpio].flags |= new_pinmux_type;
 
 	ret = 0;
  err_out:
 	return ret;
 }
 
-int gpio_direction_input(unsigned gpio)
+static int sh_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
-	struct pinmux_info *gpioc = gpio_controller(gpio);
+	struct pinmux_info *gpioc = chip_to_pinmux(chip);
 	unsigned long flags;
-	int ret = -EINVAL;
-
-	if (!gpioc)
-		goto err_out;
+	int ret;
 
 	spin_lock_irqsave(&gpio_lock, flags);
-	ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_INPUT);
+	ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT);
 	spin_unlock_irqrestore(&gpio_lock, flags);
- err_out:
+
 	return ret;
 }
-EXPORT_SYMBOL(gpio_direction_input);
 
-static int __gpio_get_set_value(struct pinmux_info *gpioc,
-				unsigned gpio, int value,
-				int do_write)
+static void sh_gpio_set_value(struct pinmux_info *gpioc,
+			     unsigned gpio, int value)
 {
 	struct pinmux_data_reg *dr = NULL;
 	int bit = 0;
 
-	if (get_data_reg(gpioc, gpio, &dr, &bit) != 0)
+	if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
 		BUG();
 	else
-		value = read_write_reg(dr->reg, dr->reg_width,
-				       1, bit, !!value, do_write);
-
-	return value;
+		gpio_write_bit(dr, bit, value);
 }
 
-int gpio_direction_output(unsigned gpio, int value)
+static int sh_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				    int value)
 {
-	struct pinmux_info *gpioc = gpio_controller(gpio);
+	struct pinmux_info *gpioc = chip_to_pinmux(chip);
 	unsigned long flags;
-	int ret = -EINVAL;
+	int ret;
 
-	if (!gpioc)
-		goto err_out;
-
+	sh_gpio_set_value(gpioc, offset, value);
 	spin_lock_irqsave(&gpio_lock, flags);
-	__gpio_get_set_value(gpioc, gpio, value, 1);
-	ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_OUTPUT);
+	ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT);
 	spin_unlock_irqrestore(&gpio_lock, flags);
- err_out:
+
 	return ret;
 }
-EXPORT_SYMBOL(gpio_direction_output);
 
-int gpio_get_value(unsigned gpio)
+static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
 {
-	struct pinmux_info *gpioc = gpio_controller(gpio);
-	unsigned long flags;
-	int value = 0;
+	struct pinmux_data_reg *dr = NULL;
+	int bit = 0;
 
-	if (!gpioc)
+	if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) {
 		BUG();
-	else {
-		spin_lock_irqsave(&gpio_lock, flags);
-		value = __gpio_get_set_value(gpioc, gpio, 0, 0);
-		spin_unlock_irqrestore(&gpio_lock, flags);
+		return 0;
 	}
 
-	return value;
+	return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
 }
-EXPORT_SYMBOL(gpio_get_value);
 
-void gpio_set_value(unsigned gpio, int value)
+static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	struct pinmux_info *gpioc = gpio_controller(gpio);
-	unsigned long flags;
-
-	if (!gpioc)
-		BUG();
-	else {
-		spin_lock_irqsave(&gpio_lock, flags);
-		__gpio_get_set_value(gpioc, gpio, value, 1);
-		spin_unlock_irqrestore(&gpio_lock, flags);
-	}
+	return sh_gpio_get_value(chip_to_pinmux(chip), offset);
 }
-EXPORT_SYMBOL(gpio_set_value);
+
+static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	sh_gpio_set_value(chip_to_pinmux(chip), offset, value);
+}
 
 int register_pinmux(struct pinmux_info *pip)
 {
-	registered_gpio = pip;
-	pr_info("pinmux: %s handling gpio %d -> %d\n",
+	struct gpio_chip *chip = &pip->chip;
+
+	pr_info("sh pinmux: %s handling gpio %d -> %d\n",
 		pip->name, pip->first_gpio, pip->last_gpio);
 
-	return 0;
+	setup_data_regs(pip);
+
+	chip->request = sh_gpio_request;
+	chip->free = sh_gpio_free;
+	chip->direction_input = sh_gpio_direction_input;
+	chip->get = sh_gpio_get;
+	chip->direction_output = sh_gpio_direction_output;
+	chip->set = sh_gpio_set;
+
+	WARN_ON(pip->first_gpio != 0); /* needs testing */
+
+	chip->label = pip->name;
+	chip->owner = THIS_MODULE;
+	chip->base = pip->first_gpio;
+	chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1;
+
+	return gpiochip_add(chip);
 }
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 64b7690..90d63ae 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -106,7 +106,7 @@
 	}
 #endif
 
-	irq = irq_demux(evt2irq(irq));
+	irq = irq_demux(intc_evt2irq(irq));
 
 #ifdef CONFIG_IRQSTACKS
 	curctx = (union irq_ctx *)current_thread_info();
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index 94df56b..7ea2704 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -14,21 +14,22 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/numa.h>
+#include <linux/ftrace.h>
+#include <linux/suspend.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
-typedef NORET_TYPE void (*relocate_new_kernel_t)(
-				unsigned long indirection_page,
-				unsigned long reboot_code_buffer,
-				unsigned long start_address,
-				unsigned long vbr_reg) ATTRIB_NORET;
+typedef void (*relocate_new_kernel_t)(unsigned long indirection_page,
+				      unsigned long reboot_code_buffer,
+				      unsigned long start_address);
 
 extern const unsigned char relocate_new_kernel[];
 extern const unsigned int relocate_new_kernel_size;
 extern void *gdb_vbr_vector;
+extern void *vbr_base;
 
 void machine_shutdown(void)
 {
@@ -45,6 +46,12 @@
  */
 int machine_kexec_prepare(struct kimage *image)
 {
+	/* older versions of kexec-tools are passing
+	 * the zImage entry point as a virtual address.
+	 */
+	if (image->start != PHYSADDR(image->start))
+		return -EINVAL; /* upgrade your kexec-tools */
+
 	return 0;
 }
 
@@ -73,17 +80,33 @@
  */
 void machine_kexec(struct kimage *image)
 {
-
 	unsigned long page_list;
 	unsigned long reboot_code_buffer;
-	unsigned long vbr_reg;
 	relocate_new_kernel_t rnk;
+	unsigned long entry;
+	unsigned long *ptr;
+	int save_ftrace_enabled;
 
-#if defined(CONFIG_SH_STANDARD_BIOS)
-	vbr_reg = ((unsigned long )gdb_vbr_vector) - 0x100;
-#else
-	vbr_reg = 0x80000000;  // dummy
+	/*
+	 * Nicked from the mips version of machine_kexec():
+	 * The generic kexec code builds a page list with physical
+	 * addresses. Use phys_to_virt() to convert them to virtual.
+	 */
+	for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
+	     ptr = (entry & IND_INDIRECTION) ?
+	       phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
+		if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
+		    *ptr & IND_DESTINATION)
+			*ptr = (unsigned long) phys_to_virt(*ptr);
+	}
+
+#ifdef CONFIG_KEXEC_JUMP
+	if (image->preserve_context)
+		save_processor_state();
 #endif
+
+	save_ftrace_enabled = __ftrace_enabled_save();
+
 	/* Interrupts aren't acceptable while we reboot */
 	local_irq_disable();
 
@@ -97,12 +120,37 @@
 	memcpy((void *)reboot_code_buffer, relocate_new_kernel,
 						relocate_new_kernel_size);
 
-        kexec_info(image);
+	kexec_info(image);
 	flush_cache_all();
 
+#if defined(CONFIG_SH_STANDARD_BIOS)
+	asm volatile("ldc %0, vbr" :
+		     : "r" (((unsigned long) gdb_vbr_vector) - 0x100)
+		     : "memory");
+#endif
+
 	/* now call it */
 	rnk = (relocate_new_kernel_t) reboot_code_buffer;
-	(*rnk)(page_list, reboot_code_buffer, P2SEGADDR(image->start), vbr_reg);
+	(*rnk)(page_list, reboot_code_buffer,
+	       (unsigned long)phys_to_virt(image->start));
+
+#ifdef CONFIG_KEXEC_JUMP
+	asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory");
+
+	if (image->preserve_context)
+		restore_processor_state();
+
+	/* Convert page list back to physical addresses, what a mess. */
+	for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
+	     ptr = (*ptr & IND_INDIRECTION) ?
+	       phys_to_virt(*ptr & PAGE_MASK) : ptr + 1) {
+		if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
+		    *ptr & IND_DESTINATION)
+			*ptr = virt_to_phys(*ptr);
+	}
+#endif
+
+	__ftrace_enabled_restore(save_ftrace_enabled);
 }
 
 void arch_crash_save_vmcoreinfo(void)
diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S
index c66cb32..fcc9934 100644
--- a/arch/sh/kernel/relocate_kernel.S
+++ b/arch/sh/kernel/relocate_kernel.S
@@ -4,6 +4,8 @@
  *
  * LANDISK/sh4 is supported. Maybe, SH archtecture works well.
  *
+ * 2009-03-18 Magnus Damm - Added Kexec Jump support
+ *
  * This source code is licensed under the GNU General Public License,
  * Version 2.  See the file COPYING for more details.
  */
@@ -16,23 +18,141 @@
 	/* r4 = indirection_page   */
 	/* r5 = reboot_code_buffer */
 	/* r6 = start_address      */
-	/* r7 = vbr_reg            */
 
-	mov.l	10f,r8	  /* PAGE_SIZE */
-	mov.l	11f,r9    /* P2SEG */
+	mov.l	10f, r0		/* PAGE_SIZE */
+	add	r5, r0		/* setup new stack at end of control page */
 
-	/*  stack setting */
-	add	r8,r5
-	mov	r5,r15
+	/* save r15->r8 to new stack */
+	mov.l	r15, @-r0
+	mov	r0, r15
+	mov.l	r14, @-r15
+	mov.l	r13, @-r15
+	mov.l	r12, @-r15
+	mov.l	r11, @-r15
+	mov.l	r10, @-r15
+	mov.l	r9, @-r15
+	mov.l	r8, @-r15
 
+	/* save other random registers */
+	sts.l	macl, @-r15
+	sts.l	mach, @-r15
+	stc.l	gbr, @-r15
+	stc.l	ssr, @-r15
+	stc.l	sr, @-r15
+	sts.l	pr, @-r15
+	stc.l	spc, @-r15
+
+	/* switch to bank1 and save r7->r0 */
+	mov.l	12f, r9
+	stc	sr, r8
+	or	r9, r8
+	ldc	r8, sr
+	mov.l	r7, @-r15
+	mov.l	r6, @-r15
+	mov.l	r5, @-r15
+	mov.l	r4, @-r15
+	mov.l	r3, @-r15
+	mov.l	r2, @-r15
+	mov.l	r1, @-r15
+	mov.l	r0, @-r15
+
+	/* switch to bank0 and save r7->r0 */
+	mov.l	12f, r9
+	not	r9, r9
+	stc	sr, r8
+	and	r9, r8
+	ldc	r8, sr
+	mov.l	r7, @-r15
+	mov.l	r6, @-r15
+	mov.l	r5, @-r15
+	mov.l	r4, @-r15
+	mov.l	r3, @-r15
+	mov.l	r2, @-r15
+	mov.l	r1, @-r15
+	mov.l	r0, @-r15
+
+	mov.l	r4, @-r15	/* save indirection page again */
+
+	bsr	swap_pages	/* swap pages before jumping to new kernel */
+	 nop
+
+	mova	11f, r0
+	mov.l	r15, @r0	/* save pointer to stack */
+
+	jsr	@r6		/* hand over control to new kernel */
+	 nop
+
+	mov.l	11f, r15	/* get pointer to stack */
+	mov.l	@r15+, r4	/* restore r4 to get indirection page */
+
+	bsr	swap_pages	/* swap pages back to previous state */
+	 nop
+
+	/* make sure bank0 is active and restore r0->r7 */
+	mov.l	12f, r9
+	not	r9, r9
+	stc	sr, r8
+	and	r9, r8
+	ldc	r8, sr
+	mov.l	@r15+, r0
+	mov.l	@r15+, r1
+	mov.l	@r15+, r2
+	mov.l	@r15+, r3
+	mov.l	@r15+, r4
+	mov.l	@r15+, r5
+	mov.l	@r15+, r6
+	mov.l	@r15+, r7
+
+	/* switch to bank1 and restore r0->r7 */
+	mov.l	12f, r9
+	stc	sr, r8
+	or	r9, r8
+	ldc	r8, sr
+	mov.l	@r15+, r0
+	mov.l	@r15+, r1
+	mov.l	@r15+, r2
+	mov.l	@r15+, r3
+	mov.l	@r15+, r4
+	mov.l	@r15+, r5
+	mov.l	@r15+, r6
+	mov.l	@r15+, r7
+
+	/* switch back to bank0 */
+	mov.l	12f, r9
+	not	r9, r9
+	stc	sr, r8
+	and	r9, r8
+	ldc	r8, sr
+
+	/* restore other random registers */
+	ldc.l	@r15+, spc
+	lds.l	@r15+, pr
+	ldc.l	@r15+, sr
+	ldc.l	@r15+, ssr
+	ldc.l	@r15+, gbr
+	lds.l	@r15+, mach
+	lds.l	@r15+, macl
+
+	/* restore r8->r15 */
+	mov.l	@r15+, r8
+	mov.l	@r15+, r9
+	mov.l	@r15+, r10
+	mov.l	@r15+, r11
+	mov.l	@r15+, r12
+	mov.l	@r15+, r13
+	mov.l	@r15+, r14
+	mov.l	@r15+, r15
+	rts
+	 nop
+
+swap_pages:
 	bra	1f
-	mov	r4,r0	  /* cmd = indirection_page */
+	 mov	r4,r0	  /* cmd = indirection_page */
 0:
 	mov.l	@r4+,r0	  /* cmd = *ind++ */
 
-1:	/* addr = (cmd | P2SEG) & 0xfffffff0 */
+1:	/* addr = cmd & 0xfffffff0 */
 	mov	r0,r2
-	or	r9,r2
 	mov	#-16,r1
 	and	r1,r2
 
@@ -40,57 +160,70 @@
 	tst	#1,r0
 	bt	2f
 	bra	0b
-	mov	r2,r5
+	 mov	r2,r5
 
 2:	/* else if(cmd & IND_INDIRECTION) ind = addr  */
 	tst	#2,r0
 	bt	3f
 	bra	0b
-	mov	r2,r4
+	 mov	r2,r4
 
-3:	/* else if(cmd & IND_DONE) goto 6  */
+3:	/* else if(cmd & IND_DONE) return */
 	tst	#4,r0
 	bt	4f
-	bra	6f
-	nop
+	rts
+	 nop
 
 4:	/* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */
 	tst	#8,r0
 	bt	0b
 
-	mov	r8,r3
+	mov.l	10f,r3	  /* PAGE_SIZE */
 	shlr2	r3
 	shlr2	r3
 5:
 	dt	r3
-	mov.l	@r2+,r1   /*  16n+0 */
-	mov.l	r1,@r5
-	add	#4,r5
-	mov.l	@r2+,r1	  /*  16n+4 */
-	mov.l	r1,@r5
-	add	#4,r5
-	mov.l	@r2+,r1   /*  16n+8 */
-	mov.l	r1,@r5
-	add	#4,r5
-	mov.l	@r2+,r1   /*  16n+12 */
-	mov.l	r1,@r5
-	add	#4,r5
+
+	/* regular kexec just overwrites the destination page
+	 * with the contents of the source page.
+	 * for the kexec jump case we need to swap the contents
+	 * of the pages.
+	 * to keep it simple swap the contents for both cases.
+	 */
+	mov.l	@(0, r2), r8
+	mov.l	@(0, r5), r1
+	mov.l	r8, @(0, r5)
+	mov.l	r1, @(0, r2)
+
+	mov.l	@(4, r2), r8
+	mov.l	@(4, r5), r1
+	mov.l	r8, @(4, r5)
+	mov.l	r1, @(4, r2)
+
+	mov.l	@(8, r2), r8
+	mov.l	@(8, r5), r1
+	mov.l	r8, @(8, r5)
+	mov.l	r1, @(8, r2)
+
+	mov.l	@(12, r2), r8
+	mov.l	@(12, r5), r1
+	mov.l	r8, @(12, r5)
+	mov.l	r1, @(12, r2)
+
+	add	#16,r5
+	add	#16,r2
 	bf	5b
 
 	bra	0b
-	nop
-6:
-#ifdef CONFIG_SH_STANDARD_BIOS
-	ldc   r7, vbr
-#endif
-	jmp @r6
-	nop
+	 nop
 
 	.align 2
 10:
 	.long	PAGE_SIZE
 11:
-	.long	P2SEG
+	.long	0
+12:
+	.long	0x20000000 ! RB=1
 
 relocate_new_kernel_end:
 
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 370d2cf..24c6025 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -432,6 +432,7 @@
 	[CPU_SH7763]	= "SH7763",	[CPU_SH7770]	= "SH7770",
 	[CPU_SH7780]	= "SH7780",	[CPU_SH7781]	= "SH7781",
 	[CPU_SH7343]	= "SH7343",	[CPU_SH7785]	= "SH7785",
+	[CPU_SH7786]	= "SH7786",
 	[CPU_SH7722]	= "SH7722",	[CPU_SHX3]	= "SH-X3",
 	[CPU_SH5_101]	= "SH5-101",	[CPU_SH5_103]	= "SH5-103",
 	[CPU_MXG]	= "MX-G",	[CPU_SH7723]	= "SH7723",
@@ -448,7 +449,7 @@
 /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
 static const char *cpu_flags[] = {
 	"none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
-	"ptea", "llsc", "l2", "op32", NULL
+	"ptea", "llsc", "l2", "op32", "pteaex", NULL
 };
 
 static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
diff --git a/arch/sh/kernel/swsusp.c b/arch/sh/kernel/swsusp.c
new file mode 100644
index 0000000..12b64a0
--- /dev/null
+++ b/arch/sh/kernel/swsusp.c
@@ -0,0 +1,38 @@
+/*
+ * swsusp.c - SuperH hibernation support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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/mm.h>
+#include <linux/sched.h>
+#include <linux/suspend.h>
+#include <asm/suspend.h>
+#include <asm/sections.h>
+#include <asm/tlbflush.h>
+#include <asm/page.h>
+#include <asm/fpu.h>
+
+struct swsusp_arch_regs swsusp_arch_regs_cpu0;
+
+int pfn_is_nosave(unsigned long pfn)
+{
+	unsigned long begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
+	unsigned long end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
+
+	return (pfn >= begin_pfn) && (pfn < end_pfn);
+}
+
+void save_processor_state(void)
+{
+	init_fpu(current);
+}
+
+void restore_processor_state(void)
+{
+	local_flush_tlb_all();
+}
diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c
index 8457f83..c34e1e0 100644
--- a/arch/sh/kernel/time_32.c
+++ b/arch/sh/kernel/time_32.c
@@ -41,14 +41,6 @@
 	return 0;
 }
 
-/*
- * Null high precision timer functions for systems lacking one.
- */
-static cycle_t null_hpt_read(void)
-{
-	return 0;
-}
-
 void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
 int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
 
@@ -112,7 +104,6 @@
 EXPORT_SYMBOL(do_settimeofday);
 #endif /* !CONFIG_GENERIC_TIME */
 
-#ifndef CONFIG_GENERIC_CLOCKEVENTS
 /* last time the RTC clock got updated */
 static long last_rtc_update;
 
@@ -156,7 +147,6 @@
 	update_process_times(user_mode(get_irq_regs()));
 #endif
 }
-#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_PM
 int timer_suspend(struct sys_device *dev, pm_message_t state)
@@ -189,7 +179,12 @@
 
 static int __init timer_init_sysfs(void)
 {
-	int ret = sysdev_class_register(&timer_sysclass);
+	int ret;
+
+	if (!sys_timer)
+		return 0;
+
+	ret = sysdev_class_register(&timer_sysclass);
 	if (ret != 0)
 		return ret;
 
@@ -200,42 +195,21 @@
 
 void (*board_time_init)(void);
 
-/*
- * Shamelessly based on the MIPS and Sparc64 work.
- */
-static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
-unsigned long sh_hpt_frequency = 0;
-
-#define NSEC_PER_CYC_SHIFT	10
-
-static struct clocksource clocksource_sh = {
+struct clocksource clocksource_sh = {
 	.name		= "SuperH",
-	.rating		= 200,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.read		= null_hpt_read,
-	.shift		= 16,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static void __init init_sh_clocksource(void)
-{
-	if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read)
-		return;
-
-	clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency,
-						  clocksource_sh.shift);
-
-	timer_ticks_per_nsec_quotient =
-		clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT);
-
-	clocksource_register(&clocksource_sh);
-}
-
 #ifdef CONFIG_GENERIC_TIME
 unsigned long long sched_clock(void)
 {
-	unsigned long long ticks = clocksource_sh.read();
-	return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT;
+	unsigned long long cycles;
+
+	/* jiffies based sched_clock if no clocksource is installed */
+	if (!clocksource_sh.rating)
+		return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ);
+
+	cycles = clocksource_sh.read();
+	return cyc2ns(&clocksource_sh, cycles);
 }
 #endif
 
@@ -259,17 +233,8 @@
 	 * initialized for us.
 	 */
 	sys_timer = get_sys_timer();
+	if (unlikely(!sys_timer))
+		panic("System timer missing.\n");
+
 	printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
-
-
-	if (sys_timer->ops->read)
-		clocksource_sh.read = sys_timer->ops->read;
-
-	init_sh_clocksource();
-
-	if (sh_hpt_frequency)
-		printk("Using %lu.%03lu MHz high precision timer.\n",
-		       ((sh_hpt_frequency + 500) / 1000) / 1000,
-		       ((sh_hpt_frequency + 500) / 1000) % 1000);
-
 }
diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c
index c3d237e..9a77ae8 100644
--- a/arch/sh/kernel/timers/timer-mtu2.c
+++ b/arch/sh/kernel/timers/timer-mtu2.c
@@ -35,7 +35,8 @@
 #define MTU2_TSR_1	0xfffe4385
 #define MTU2_TCNT_1	0xfffe4386	/* 16-bit counter */
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7201)
+#if defined(CONFIG_CPU_SUBTYPE_SH7201) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7203)
 #define MTU2_TGRA_1	0xfffe4388
 #else
 #define MTU2_TGRA_1	0xfffe438a
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index 0db3f95..10b5a6f 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -146,7 +146,14 @@
 	_tmu_clear_status(TMU0);
 	_tmu_set_irq(TMU0,tmu0_clockevent.mode != CLOCK_EVT_MODE_ONESHOT);
 
-	evt->event_handler(evt);
+	switch (tmu0_clockevent.mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_PERIODIC:
+		evt->event_handler(evt);
+		break;
+	default:
+		break;
+	}
 
 	return IRQ_HANDLED;
 }
@@ -237,6 +244,7 @@
     !defined(CONFIG_CPU_SUBTYPE_SH7721) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7785) && \
+    !defined(CONFIG_CPU_SUBTYPE_SH7786) && \
     !defined(CONFIG_CPU_SUBTYPE_SHX3)
 	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
 #endif
@@ -254,7 +262,14 @@
 
 	_tmu_start(TMU1);
 
-	sh_hpt_frequency = clk_get_rate(&tmu1_clk);
+	clocksource_sh.rating = 200;
+	clocksource_sh.mask = CLOCKSOURCE_MASK(32);
+	clocksource_sh.read = tmu_timer_read;
+	clocksource_sh.shift = 10;
+	clocksource_sh.mult = clocksource_hz2mult(clk_get_rate(&tmu1_clk),
+						  clocksource_sh.shift);
+	clocksource_sh.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+	clocksource_register(&clocksource_sh);
 
 	tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC,
 				      tmu0_clockevent.shift);
@@ -264,6 +279,7 @@
 			clockevent_delta2ns(1, &tmu0_clockevent);
 
 	tmu0_clockevent.cpumask = cpumask_of(0);
+	tmu0_clockevent.rating = 100;
 
 	clockevents_register_device(&tmu0_clockevent);
 
@@ -274,7 +290,6 @@
 	.init		= tmu_timer_init,
 	.start		= tmu_timer_start,
 	.stop		= tmu_timer_stop,
-	.read		= tmu_timer_read,
 };
 
 struct sys_timer tmu_timer = {
diff --git a/arch/sh/kernel/vmlinux_32.lds.S b/arch/sh/kernel/vmlinux_32.lds.S
index 7b4b82bd..d0b2a71 100644
--- a/arch/sh/kernel/vmlinux_32.lds.S
+++ b/arch/sh/kernel/vmlinux_32.lds.S
@@ -15,7 +15,10 @@
 ENTRY(_start)
 SECTIONS
 {
-#ifdef CONFIG_32BIT
+#ifdef CONFIG_PMB_FIXED
+	. = CONFIG_PAGE_OFFSET + (CONFIG_MEMORY_START & 0x1fffffff) +
+	    CONFIG_ZERO_PAGE_OFFSET;
+#elif defined(CONFIG_32BIT)
 	. = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
 #else
 	. = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 555ec97..10c2435 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -57,7 +57,7 @@
 	bool
 	default y if CPU_SH5
 
-config PMB
+config PMB_ENABLE
 	bool "Support 32-bit physical addressing through PMB"
 	depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
 	select 32BIT
@@ -67,6 +67,33 @@
 	  32-bits through the SH-4A PMB. If this is not set, legacy
 	  29-bit physical addressing will be used.
 
+choice
+	prompt "PMB handling type"
+	depends on PMB_ENABLE
+	default PMB_FIXED
+
+config PMB
+	bool "PMB"
+	depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
+	select 32BIT
+	help
+	  If you say Y here, physical addressing will be extended to
+	  32-bits through the SH-4A PMB. If this is not set, legacy
+	  29-bit physical addressing will be used.
+
+config PMB_FIXED
+	bool "fixed PMB"
+	depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || \
+					   CPU_SUBTYPE_SH7785)
+	select 32BIT
+	help
+	  If this option is enabled, fixed PMB mappings are inherited
+	  from the boot loader, and the kernel does not attempt dynamic
+	  management. This is the closest to legacy 29-bit physical mode,
+	  and allows systems to support up to 512MiB of system memory.
+
+endchoice
+
 config X2TLB
 	bool "Enable extended TLB mode"
 	depends on (CPU_SHX2 || CPU_SHX3) && MMU && EXPERIMENTAL
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32
index cb2f3f2..986a1e0 100644
--- a/arch/sh/mm/Makefile_32
+++ b/arch/sh/mm/Makefile_32
@@ -25,8 +25,10 @@
 endif
 
 ifdef CONFIG_MMU
-obj-$(CONFIG_CPU_SH3)	+= tlb-sh3.o
-obj-$(CONFIG_CPU_SH4)	+= tlb-sh4.o
+tlb-$(CONFIG_CPU_SH3)		:= tlb-sh3.o
+tlb-$(CONFIG_CPU_SH4)		:= tlb-sh4.o
+tlb-$(CONFIG_CPU_HAS_PTEAEX)	:= tlb-pteaex.o
+obj-y				+= $(tlb-y)
 ifndef CONFIG_CACHE_OFF
 obj-$(CONFIG_CPU_SH4)		+= pg-sh4.o
 obj-$(CONFIG_SH7705_CACHE_32KB)	+= pg-sh7705.o
@@ -35,6 +37,7 @@
 
 obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
 obj-$(CONFIG_PMB)		+= pmb.o
+obj-$(CONFIG_PMB_FIXED)		+= pmb-fixed.o
 obj-$(CONFIG_NUMA)		+= numa.o
 
 EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/mm/asids-debugfs.c b/arch/sh/mm/asids-debugfs.c
index 8e912a1..cd8c3bf3 100644
--- a/arch/sh/mm/asids-debugfs.c
+++ b/arch/sh/mm/asids-debugfs.c
@@ -37,10 +37,8 @@
 			continue;
 
 		if (p->mm)
-			seq_printf(file, "%5d : %02lx\n", pid,
+			seq_printf(file, "%5d : %04lx\n", pid,
 				   cpu_asid(smp_processor_id(), p->mm));
-		else
-			seq_printf(file, "%5d : (none)\n", pid);
 	}
 
 	read_unlock(&tasklist_lock);
diff --git a/arch/sh/mm/ioremap_32.c b/arch/sh/mm/ioremap_32.c
index 32946fb..60cc486 100644
--- a/arch/sh/mm/ioremap_32.c
+++ b/arch/sh/mm/ioremap_32.c
@@ -59,11 +59,13 @@
 	if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr))
 		return (void __iomem *)phys_addr;
 
+#if !defined(CONFIG_PMB_FIXED)
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..
 	 */
 	if (phys_addr < virt_to_phys(high_memory))
 		return NULL;
+#endif
 
 	/*
 	 * Mappings have to be page-aligned
@@ -81,7 +83,7 @@
 	area->phys_addr = phys_addr;
 	orig_addr = addr = (unsigned long)area->addr;
 
-#ifdef CONFIG_32BIT
+#ifdef CONFIG_PMB
 	/*
 	 * First try to remap through the PMB once a valid VMA has been
 	 * established. Smaller allocations (or the rest of the size
@@ -119,10 +121,10 @@
 	unsigned long seg = PXSEG(vaddr);
 	struct vm_struct *p;
 
-	if (seg < P3SEG || seg >= P3_ADDR_MAX || is_pci_memaddr(vaddr))
+	if (seg < P3SEG || vaddr >= P3_ADDR_MAX || is_pci_memaddr(vaddr))
 		return;
 
-#ifdef CONFIG_32BIT
+#ifdef CONFIG_PMB
 	/*
 	 * Purge any PMB entries that may have been established for this
 	 * mapping, then proceed with conventional VMA teardown.
diff --git a/arch/sh/mm/pmb-fixed.c b/arch/sh/mm/pmb-fixed.c
new file mode 100644
index 0000000..43c8eac
--- /dev/null
+++ b/arch/sh/mm/pmb-fixed.c
@@ -0,0 +1,45 @@
+/*
+ * arch/sh/mm/fixed_pmb.c
+ *
+ * Copyright (C) 2009  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/mm.h>
+#include <linux/io.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+
+static int __uses_jump_to_uncached fixed_pmb_init(void)
+{
+	int i;
+	unsigned long addr, data;
+
+	jump_to_uncached();
+
+	for (i = 0; i < PMB_ENTRY_MAX; i++) {
+		addr = PMB_DATA + (i << PMB_E_SHIFT);
+		data = ctrl_inl(addr);
+		if (!(data & PMB_V))
+			continue;
+
+		if (data & PMB_C) {
+#if defined(CONFIG_CACHE_WRITETHROUGH)
+			data |= PMB_WT;
+#elif defined(CONFIG_CACHE_WRITEBACK)
+			data &= ~PMB_WT;
+#else
+			data &= ~(PMB_C | PMB_WT);
+#endif
+		}
+		ctrl_outl(data, addr);
+	}
+
+	back_to_cached();
+
+	return 0;
+}
+arch_initcall(fixed_pmb_init);
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 8424167..b1a714a 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -15,6 +15,8 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
@@ -402,3 +404,39 @@
 	return 0;
 }
 postcore_initcall(pmb_debugfs_init);
+
+#ifdef CONFIG_PM
+static int pmb_sysdev_suspend(struct sys_device *dev, pm_message_t state)
+{
+	static pm_message_t prev_state;
+
+	/* Restore the PMB after a resume from hibernation */
+	if (state.event == PM_EVENT_ON &&
+	    prev_state.event == PM_EVENT_FREEZE) {
+		struct pmb_entry *pmbe;
+		spin_lock_irq(&pmb_list_lock);
+		for (pmbe = pmb_list; pmbe; pmbe = pmbe->next)
+			set_pmb_entry(pmbe);
+		spin_unlock_irq(&pmb_list_lock);
+	}
+	prev_state = state;
+	return 0;
+}
+
+static int pmb_sysdev_resume(struct sys_device *dev)
+{
+	return pmb_sysdev_suspend(dev, PMSG_ON);
+}
+
+static struct sysdev_driver pmb_sysdev_driver = {
+	.suspend = pmb_sysdev_suspend,
+	.resume = pmb_sysdev_resume,
+};
+
+static int __init pmb_sysdev_init(void)
+{
+	return sysdev_driver_register(&cpu_sysdev_class, &pmb_sysdev_driver);
+}
+
+subsys_initcall(pmb_sysdev_init);
+#endif
diff --git a/arch/sh/mm/tlb-pteaex.c b/arch/sh/mm/tlb-pteaex.c
new file mode 100644
index 0000000..2aab3ea
--- /dev/null
+++ b/arch/sh/mm/tlb-pteaex.c
@@ -0,0 +1,96 @@
+/*
+ * arch/sh/mm/tlb-pteaex.c
+ *
+ * TLB operations for SH-X3 CPUs featuring PTE ASID Extensions.
+ *
+ * Copyright (C) 2009 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/kernel.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+void update_mmu_cache(struct vm_area_struct * vma,
+		      unsigned long address, pte_t pte)
+{
+	unsigned long flags;
+	unsigned long pteval;
+	unsigned long vpn;
+
+	/* Ptrace may call this routine. */
+	if (vma && current->active_mm != vma->vm_mm)
+		return;
+
+#ifndef CONFIG_CACHE_OFF
+	{
+		unsigned long pfn = pte_pfn(pte);
+
+		if (pfn_valid(pfn)) {
+			struct page *page = pfn_to_page(pfn);
+
+			if (!test_bit(PG_mapped, &page->flags)) {
+				unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+				__flush_wback_region((void *)P1SEGADDR(phys),
+						     PAGE_SIZE);
+				__set_bit(PG_mapped, &page->flags);
+			}
+		}
+	}
+#endif
+
+	local_irq_save(flags);
+
+	/* Set PTEH register */
+	vpn = address & MMU_VPN_MASK;
+	__raw_writel(vpn, MMU_PTEH);
+
+	/* Set PTEAEX */
+	__raw_writel(get_asid(), MMU_PTEAEX);
+
+	pteval = pte.pte_low;
+
+	/* Set PTEA register */
+#ifdef CONFIG_X2TLB
+	/*
+	 * For the extended mode TLB this is trivial, only the ESZ and
+	 * EPR bits need to be written out to PTEA, with the remainder of
+	 * the protection bits (with the exception of the compat-mode SZ
+	 * and PR bits, which are cleared) being written out in PTEL.
+	 */
+	__raw_writel(pte.pte_high, MMU_PTEA);
+#endif
+
+	/* Set PTEL register */
+	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+#ifdef CONFIG_CACHE_WRITETHROUGH
+	pteval |= _PAGE_WT;
+#endif
+	/* conveniently, we want all the software flags to be 0 anyway */
+	__raw_writel(pteval, MMU_PTEL);
+
+	/* Load the TLB */
+	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+	local_irq_restore(flags);
+}
+
+/*
+ * While SH-X2 extended TLB mode splits out the memory-mapped I/UTLB
+ * data arrays, SH-X3 cores with PTEAEX split out the memory-mapped
+ * address arrays. In compat mode the second array is inaccessible, while
+ * in extended mode, the legacy 8-bit ASID field in address array 1 has
+ * undefined behaviour.
+ */
+void __uses_jump_to_uncached local_flush_tlb_one(unsigned long asid,
+						 unsigned long page)
+{
+	jump_to_uncached();
+	__raw_writel(page, MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT);
+	__raw_writel(asid, MMU_UTLB_ADDRESS_ARRAY2 | MMU_PAGE_ASSOC_BIT);
+	back_to_cached();
+}
diff --git a/arch/sh/oprofile/common.c b/arch/sh/oprofile/common.c
index 1d97d64..1b9d430 100644
--- a/arch/sh/oprofile/common.c
+++ b/arch/sh/oprofile/common.c
@@ -107,6 +107,7 @@
 	case CPU_SH7780:
 	case CPU_SH7781:
 	case CPU_SH7785:
+	case CPU_SH7786:
 	case CPU_SH7723:
 	case CPU_SHX3:
 		lmodel = &op_model_sh4a_ops;
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index 284b7e8..8477b5d 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -52,3 +52,6 @@
 AP325RXA		SH_AP325RXA
 SH7763RDP		SH_SH7763RDP
 SH7785LCR		SH_SH7785LCR
+URQUELL			SH_URQUELL
+ESPT			SH_ESPT
+POLARIS			SH_POLARIS
diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h
index 32a7efe..26693703 100644
--- a/arch/sparc/include/asm/pil.h
+++ b/arch/sparc/include/asm/pil.h
@@ -24,6 +24,7 @@
 #define PIL_DEVICE_IRQ		5
 #define PIL_SMP_CALL_FUNC_SNGL	6
 #define PIL_DEFERRED_PCR_WORK	7
+#define PIL_KGDB_CAPTURE	8
 #define PIL_NORMAL_MAX		14
 #define PIL_NMI			15
 
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index e289376..1c378d8 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -323,17 +323,25 @@
 	sun4u_irq_enable(virt_irq);
 }
 
+/* Don't do anything.  The desc->status check for IRQ_DISABLED in
+ * handler_irq() will skip the handler call and that will leave the
+ * interrupt in the sent state.  The next ->enable() call will hit the
+ * ICLR register to reset the state machine.
+ *
+ * This scheme is necessary, instead of clearing the Valid bit in the
+ * IMAP register, to handle the case of IMAP registers being shared by
+ * multiple INOs (and thus ICLR registers).  Since we use a different
+ * virtual IRQ for each shared IMAP instance, the generic code thinks
+ * there is only one user so it prematurely calls ->disable() on
+ * free_irq().
+ *
+ * We have to provide an explicit ->disable() method instead of using
+ * NULL to get the default.  The reason is that if the generic code
+ * sees that, it also hooks up a default ->shutdown method which
+ * invokes ->mask() which we do not want.  See irq_chip_set_defaults().
+ */
 static void sun4u_irq_disable(unsigned int virt_irq)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-
-	if (likely(data)) {
-		unsigned long imap = data->imap;
-		unsigned long tmp = upa_readq(imap);
-
-		tmp &= ~IMAP_VALID;
-		upa_writeq(tmp, imap);
-	}
 }
 
 static void sun4u_irq_eoi(unsigned int virt_irq)
@@ -746,7 +754,8 @@
 
 		desc = irq_desc + virt_irq;
 
-		desc->handle_irq(virt_irq, desc);
+		if (!(desc->status & IRQ_DISABLED))
+			desc->handle_irq(virt_irq, desc);
 
 		bucket_pa = next_pa;
 	}
diff --git a/arch/sparc/kernel/kgdb_64.c b/arch/sparc/kernel/kgdb_64.c
index fefbe6d..f5a0fd4 100644
--- a/arch/sparc/kernel/kgdb_64.c
+++ b/arch/sparc/kernel/kgdb_64.c
@@ -108,7 +108,7 @@
 }
 
 #ifdef CONFIG_SMP
-void smp_kgdb_capture_client(struct pt_regs *regs)
+void smp_kgdb_capture_client(int irq, struct pt_regs *regs)
 {
 	unsigned long flags;
 
diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c
index 64e6edf..b775658 100644
--- a/arch/sparc/kernel/pci_common.c
+++ b/arch/sparc/kernel/pci_common.c
@@ -368,7 +368,7 @@
 	const u32 *vdma = of_get_property(pbm->op->node, "virtual-dma", NULL);
 
 	if (vdma) {
-		struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL);
+		struct resource *rp = kzalloc(sizeof(*rp), GFP_KERNEL);
 
 		if (!rp) {
 			prom_printf("Cannot allocate IOMMU resource.\n");
diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable.S
index d9bdfb9..76d837f 100644
--- a/arch/sparc/kernel/ttable.S
+++ b/arch/sparc/kernel/ttable.S
@@ -64,7 +64,12 @@
 tl0_irq6:	BTRAP(0x46)
 #endif
 tl0_irq7:	TRAP_IRQ(deferred_pcr_work_irq, 7)
-tl0_irq8:	BTRAP(0x48) BTRAP(0x49)
+#ifdef CONFIG_KGDB
+tl0_irq8:	TRAP_IRQ(smp_kgdb_capture_client, 8)
+#else
+tl0_irq8:	BTRAP(0x48)
+#endif
+tl0_irq9:	BTRAP(0x49)
 tl0_irq10:	BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
 tl0_irq14:	TRAP_IRQ(timer_interrupt, 14)
 tl0_irq15:	TRAP_NMI_IRQ(perfctr_irq, 15)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 80c788e..b57a594 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -679,28 +679,8 @@
 #ifdef CONFIG_KGDB
 	.globl		xcall_kgdb_capture
 xcall_kgdb_capture:
-661:	rdpr		%pstate, %g2
-	wrpr		%g2, PSTATE_IG | PSTATE_AG, %pstate
-	.section	.sun4v_2insn_patch, "ax"
-	.word		661b
-	nop
-	nop
-	.previous
-
-	rdpr		%pil, %g2
-	wrpr		%g0, PIL_NORMAL_MAX, %pil
-	sethi		%hi(109f), %g7
-	ba,pt		%xcc, etrap_irq
-109:	 or		%g7, %lo(109b), %g7
-#ifdef CONFIG_TRACE_IRQFLAGS
-	call		trace_hardirqs_off
-	 nop
-#endif
-	call		smp_kgdb_capture_client
-	 add		%sp, PTREGS_OFF, %o0
-	/* Has to be a non-v9 branch due to the large distance. */
-	ba		rtrap_xcall
-	 ldx		[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
+	wr		%g0, (1 << PIL_KGDB_CAPTURE), %set_softint
+	retry
 #endif
 
 #endif /* CONFIG_SMP */
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 15e8b7c..8e3d69e 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -64,6 +64,11 @@
 		ret = poke_user(child, addr, data);
 		break;
 
+	case PTRACE_SYSEMU:
+	case PTRACE_SYSEMU_SINGLESTEP:
+		ret = -EIO;
+		break;
+
 	/* continue and stop at next (return from) syscall */
 	case PTRACE_SYSCALL:
 	/* restart after signal. */
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 74f49bb..89b48a1 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -14,7 +14,6 @@
 #undef memset
 
 extern size_t strlen(const char *);
-extern void *memcpy(void *, const void *, size_t);
 extern void *memmove(void *, const void *, size_t);
 extern void *memset(void *, int, size_t);
 extern int printf(const char *, ...);
@@ -24,7 +23,11 @@
 EXPORT_SYMBOL(strstr);
 #endif
 
+#ifndef __x86_64__
+extern void *memcpy(void *, const void *, size_t);
 EXPORT_SYMBOL(memcpy);
+#endif
+
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(printf);
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index 903de4a..ebe7dee 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
 obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
+obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o
 
 obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
 
@@ -19,3 +20,5 @@
 aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
 twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
 salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
+
+aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o
diff --git a/arch/x86/crypto/aes-i586-asm_32.S b/arch/x86/crypto/aes-i586-asm_32.S
index e41b147..b949ec2 100644
--- a/arch/x86/crypto/aes-i586-asm_32.S
+++ b/arch/x86/crypto/aes-i586-asm_32.S
@@ -41,14 +41,14 @@
 #define tlen 1024   // length of each of 4 'xor' arrays (256 32-bit words)
 
 /* offsets to parameters with one register pushed onto stack */
-#define tfm 8
+#define ctx 8
 #define out_blk 12
 #define in_blk 16
 
-/* offsets in crypto_tfm structure */
-#define klen (crypto_tfm_ctx_offset + 0)
-#define ekey (crypto_tfm_ctx_offset + 4)
-#define dkey (crypto_tfm_ctx_offset + 244)
+/* offsets in crypto_aes_ctx structure */
+#define klen (480)
+#define ekey (0)
+#define dkey (240)
 
 // register mapping for encrypt and decrypt subroutines
 
@@ -217,7 +217,7 @@
 	do_col (table, r5,r0,r1,r4, r2,r3);		/* idx=r5 */
 
 // AES (Rijndael) Encryption Subroutine
-/* void aes_enc_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */
+/* void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out_blk, const u8 *in_blk) */
 
 .global  aes_enc_blk
 
@@ -228,7 +228,7 @@
 
 aes_enc_blk:
 	push    %ebp
-	mov     tfm(%esp),%ebp
+	mov     ctx(%esp),%ebp
 
 // CAUTION: the order and the values used in these assigns 
 // rely on the register mappings
@@ -292,7 +292,7 @@
 	ret
 
 // AES (Rijndael) Decryption Subroutine
-/* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */
+/* void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out_blk, const u8 *in_blk) */
 
 .global  aes_dec_blk
 
@@ -303,7 +303,7 @@
 
 aes_dec_blk:
 	push    %ebp
-	mov     tfm(%esp),%ebp
+	mov     ctx(%esp),%ebp
 
 // CAUTION: the order and the values used in these assigns 
 // rely on the register mappings
diff --git a/arch/x86/crypto/aes-x86_64-asm_64.S b/arch/x86/crypto/aes-x86_64-asm_64.S
index a120f52..5b577d5 100644
--- a/arch/x86/crypto/aes-x86_64-asm_64.S
+++ b/arch/x86/crypto/aes-x86_64-asm_64.S
@@ -17,8 +17,6 @@
 
 #include <asm/asm-offsets.h>
 
-#define BASE crypto_tfm_ctx_offset
-
 #define R1	%rax
 #define R1E	%eax
 #define R1X	%ax
@@ -56,13 +54,13 @@
 	.align	8;			\
 FUNC:	movq	r1,r2;			\
 	movq	r3,r4;			\
-	leaq	BASE+KEY+48+4(r8),r9;	\
+	leaq	KEY+48(r8),r9;		\
 	movq	r10,r11;		\
 	movl	(r7),r5 ## E;		\
 	movl	4(r7),r1 ## E;		\
 	movl	8(r7),r6 ## E;		\
 	movl	12(r7),r7 ## E;		\
-	movl	BASE+0(r8),r10 ## E;	\
+	movl	480(r8),r10 ## E;	\
 	xorl	-48(r9),r5 ## E;	\
 	xorl	-44(r9),r1 ## E;	\
 	xorl	-40(r9),r6 ## E;	\
diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c
index 71f4578..49ae9fe 100644
--- a/arch/x86/crypto/aes_glue.c
+++ b/arch/x86/crypto/aes_glue.c
@@ -5,17 +5,29 @@
 
 #include <crypto/aes.h>
 
-asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
-asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
+asmlinkage void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
+asmlinkage void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
+
+void crypto_aes_encrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
+{
+	aes_enc_blk(ctx, dst, src);
+}
+EXPORT_SYMBOL_GPL(crypto_aes_encrypt_x86);
+
+void crypto_aes_decrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
+{
+	aes_dec_blk(ctx, dst, src);
+}
+EXPORT_SYMBOL_GPL(crypto_aes_decrypt_x86);
 
 static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	aes_enc_blk(tfm, dst, src);
+	aes_enc_blk(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	aes_dec_blk(tfm, dst, src);
+	aes_dec_blk(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static struct crypto_alg aes_alg = {
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S
new file mode 100644
index 0000000..caba996
--- /dev/null
+++ b/arch/x86/crypto/aesni-intel_asm.S
@@ -0,0 +1,896 @@
+/*
+ * Implement AES algorithm in Intel AES-NI instructions.
+ *
+ * The white paper of AES-NI instructions can be downloaded from:
+ *   http://softwarecommunity.intel.com/isn/downloads/intelavx/AES-Instructions-Set_WP.pdf
+ *
+ * Copyright (C) 2008, Intel Corp.
+ *    Author: Huang Ying <ying.huang@intel.com>
+ *            Vinodh Gopal <vinodh.gopal@intel.com>
+ *            Kahraman Akdemir
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/linkage.h>
+
+.text
+
+#define STATE1	%xmm0
+#define STATE2	%xmm4
+#define STATE3	%xmm5
+#define STATE4	%xmm6
+#define STATE	STATE1
+#define IN1	%xmm1
+#define IN2	%xmm7
+#define IN3	%xmm8
+#define IN4	%xmm9
+#define IN	IN1
+#define KEY	%xmm2
+#define IV	%xmm3
+
+#define KEYP	%rdi
+#define OUTP	%rsi
+#define INP	%rdx
+#define LEN	%rcx
+#define IVP	%r8
+#define KLEN	%r9d
+#define T1	%r10
+#define TKEYP	T1
+#define T2	%r11
+
+_key_expansion_128:
+_key_expansion_256a:
+	pshufd $0b11111111, %xmm1, %xmm1
+	shufps $0b00010000, %xmm0, %xmm4
+	pxor %xmm4, %xmm0
+	shufps $0b10001100, %xmm0, %xmm4
+	pxor %xmm4, %xmm0
+	pxor %xmm1, %xmm0
+	movaps %xmm0, (%rcx)
+	add $0x10, %rcx
+	ret
+
+_key_expansion_192a:
+	pshufd $0b01010101, %xmm1, %xmm1
+	shufps $0b00010000, %xmm0, %xmm4
+	pxor %xmm4, %xmm0
+	shufps $0b10001100, %xmm0, %xmm4
+	pxor %xmm4, %xmm0
+	pxor %xmm1, %xmm0
+
+	movaps %xmm2, %xmm5
+	movaps %xmm2, %xmm6
+	pslldq $4, %xmm5
+	pshufd $0b11111111, %xmm0, %xmm3
+	pxor %xmm3, %xmm2
+	pxor %xmm5, %xmm2
+
+	movaps %xmm0, %xmm1
+	shufps $0b01000100, %xmm0, %xmm6
+	movaps %xmm6, (%rcx)
+	shufps $0b01001110, %xmm2, %xmm1
+	movaps %xmm1, 16(%rcx)
+	add $0x20, %rcx
+	ret
+
+_key_expansion_192b:
+	pshufd $0b01010101, %xmm1, %xmm1
+	shufps $0b00010000, %xmm0, %xmm4
+	pxor %xmm4, %xmm0
+	shufps $0b10001100, %xmm0, %xmm4
+	pxor %xmm4, %xmm0
+	pxor %xmm1, %xmm0
+
+	movaps %xmm2, %xmm5
+	pslldq $4, %xmm5
+	pshufd $0b11111111, %xmm0, %xmm3
+	pxor %xmm3, %xmm2
+	pxor %xmm5, %xmm2
+
+	movaps %xmm0, (%rcx)
+	add $0x10, %rcx
+	ret
+
+_key_expansion_256b:
+	pshufd $0b10101010, %xmm1, %xmm1
+	shufps $0b00010000, %xmm2, %xmm4
+	pxor %xmm4, %xmm2
+	shufps $0b10001100, %xmm2, %xmm4
+	pxor %xmm4, %xmm2
+	pxor %xmm1, %xmm2
+	movaps %xmm2, (%rcx)
+	add $0x10, %rcx
+	ret
+
+/*
+ * int aesni_set_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
+ *                   unsigned int key_len)
+ */
+ENTRY(aesni_set_key)
+	movups (%rsi), %xmm0		# user key (first 16 bytes)
+	movaps %xmm0, (%rdi)
+	lea 0x10(%rdi), %rcx		# key addr
+	movl %edx, 480(%rdi)
+	pxor %xmm4, %xmm4		# xmm4 is assumed 0 in _key_expansion_x
+	cmp $24, %dl
+	jb .Lenc_key128
+	je .Lenc_key192
+	movups 0x10(%rsi), %xmm2	# other user key
+	movaps %xmm2, (%rcx)
+	add $0x10, %rcx
+	# aeskeygenassist $0x1, %xmm2, %xmm1	# round 1
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x01
+	call _key_expansion_256a
+	# aeskeygenassist $0x1, %xmm0, %xmm1
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x01
+	call _key_expansion_256b
+	# aeskeygenassist $0x2, %xmm2, %xmm1	# round 2
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x02
+	call _key_expansion_256a
+	# aeskeygenassist $0x2, %xmm0, %xmm1
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x02
+	call _key_expansion_256b
+	# aeskeygenassist $0x4, %xmm2, %xmm1	# round 3
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x04
+	call _key_expansion_256a
+	# aeskeygenassist $0x4, %xmm0, %xmm1
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x04
+	call _key_expansion_256b
+	# aeskeygenassist $0x8, %xmm2, %xmm1	# round 4
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x08
+	call _key_expansion_256a
+	# aeskeygenassist $0x8, %xmm0, %xmm1
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x08
+	call _key_expansion_256b
+	# aeskeygenassist $0x10, %xmm2, %xmm1	# round 5
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x10
+	call _key_expansion_256a
+	# aeskeygenassist $0x10, %xmm0, %xmm1
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x10
+	call _key_expansion_256b
+	# aeskeygenassist $0x20, %xmm2, %xmm1	# round 6
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x20
+	call _key_expansion_256a
+	# aeskeygenassist $0x20, %xmm0, %xmm1
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x20
+	call _key_expansion_256b
+	# aeskeygenassist $0x40, %xmm2, %xmm1	# round 7
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x40
+	call _key_expansion_256a
+	jmp .Ldec_key
+.Lenc_key192:
+	movq 0x10(%rsi), %xmm2		# other user key
+	# aeskeygenassist $0x1, %xmm2, %xmm1	# round 1
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x01
+	call _key_expansion_192a
+	# aeskeygenassist $0x2, %xmm2, %xmm1	# round 2
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x02
+	call _key_expansion_192b
+	# aeskeygenassist $0x4, %xmm2, %xmm1	# round 3
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x04
+	call _key_expansion_192a
+	# aeskeygenassist $0x8, %xmm2, %xmm1	# round 4
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x08
+	call _key_expansion_192b
+	# aeskeygenassist $0x10, %xmm2, %xmm1	# round 5
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x10
+	call _key_expansion_192a
+	# aeskeygenassist $0x20, %xmm2, %xmm1	# round 6
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x20
+	call _key_expansion_192b
+	# aeskeygenassist $0x40, %xmm2, %xmm1	# round 7
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x40
+	call _key_expansion_192a
+	# aeskeygenassist $0x80, %xmm2, %xmm1	# round 8
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xca, 0x80
+	call _key_expansion_192b
+	jmp .Ldec_key
+.Lenc_key128:
+	# aeskeygenassist $0x1, %xmm0, %xmm1	# round 1
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x01
+	call _key_expansion_128
+	# aeskeygenassist $0x2, %xmm0, %xmm1	# round 2
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x02
+	call _key_expansion_128
+	# aeskeygenassist $0x4, %xmm0, %xmm1	# round 3
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x04
+	call _key_expansion_128
+	# aeskeygenassist $0x8, %xmm0, %xmm1	# round 4
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x08
+	call _key_expansion_128
+	# aeskeygenassist $0x10, %xmm0, %xmm1	# round 5
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x10
+	call _key_expansion_128
+	# aeskeygenassist $0x20, %xmm0, %xmm1	# round 6
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x20
+	call _key_expansion_128
+	# aeskeygenassist $0x40, %xmm0, %xmm1	# round 7
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x40
+	call _key_expansion_128
+	# aeskeygenassist $0x80, %xmm0, %xmm1	# round 8
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x80
+	call _key_expansion_128
+	# aeskeygenassist $0x1b, %xmm0, %xmm1	# round 9
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x1b
+	call _key_expansion_128
+	# aeskeygenassist $0x36, %xmm0, %xmm1	# round 10
+	.byte 0x66, 0x0f, 0x3a, 0xdf, 0xc8, 0x36
+	call _key_expansion_128
+.Ldec_key:
+	sub $0x10, %rcx
+	movaps (%rdi), %xmm0
+	movaps (%rcx), %xmm1
+	movaps %xmm0, 240(%rcx)
+	movaps %xmm1, 240(%rdi)
+	add $0x10, %rdi
+	lea 240-16(%rcx), %rsi
+.align 4
+.Ldec_key_loop:
+	movaps (%rdi), %xmm0
+	# aesimc %xmm0, %xmm1
+	.byte 0x66, 0x0f, 0x38, 0xdb, 0xc8
+	movaps %xmm1, (%rsi)
+	add $0x10, %rdi
+	sub $0x10, %rsi
+	cmp %rcx, %rdi
+	jb .Ldec_key_loop
+	xor %rax, %rax
+	ret
+
+/*
+ * void aesni_enc(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
+ */
+ENTRY(aesni_enc)
+	movl 480(KEYP), KLEN		# key length
+	movups (INP), STATE		# input
+	call _aesni_enc1
+	movups STATE, (OUTP)		# output
+	ret
+
+/*
+ * _aesni_enc1:		internal ABI
+ * input:
+ *	KEYP:		key struct pointer
+ *	KLEN:		round count
+ *	STATE:		initial state (input)
+ * output:
+ *	STATE:		finial state (output)
+ * changed:
+ *	KEY
+ *	TKEYP (T1)
+ */
+_aesni_enc1:
+	movaps (KEYP), KEY		# key
+	mov KEYP, TKEYP
+	pxor KEY, STATE		# round 0
+	add $0x30, TKEYP
+	cmp $24, KLEN
+	jb .Lenc128
+	lea 0x20(TKEYP), TKEYP
+	je .Lenc192
+	add $0x20, TKEYP
+	movaps -0x60(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps -0x50(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+.align 4
+.Lenc192:
+	movaps -0x40(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps -0x30(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+.align 4
+.Lenc128:
+	movaps -0x20(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps -0x10(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps (TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps 0x10(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps 0x20(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps 0x30(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps 0x40(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps 0x50(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps 0x60(TKEYP), KEY
+	# aesenc KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	movaps 0x70(TKEYP), KEY
+	# aesenclast KEY, STATE	# last round
+	.byte 0x66, 0x0f, 0x38, 0xdd, 0xc2
+	ret
+
+/*
+ * _aesni_enc4:	internal ABI
+ * input:
+ *	KEYP:		key struct pointer
+ *	KLEN:		round count
+ *	STATE1:		initial state (input)
+ *	STATE2
+ *	STATE3
+ *	STATE4
+ * output:
+ *	STATE1:		finial state (output)
+ *	STATE2
+ *	STATE3
+ *	STATE4
+ * changed:
+ *	KEY
+ *	TKEYP (T1)
+ */
+_aesni_enc4:
+	movaps (KEYP), KEY		# key
+	mov KEYP, TKEYP
+	pxor KEY, STATE1		# round 0
+	pxor KEY, STATE2
+	pxor KEY, STATE3
+	pxor KEY, STATE4
+	add $0x30, TKEYP
+	cmp $24, KLEN
+	jb .L4enc128
+	lea 0x20(TKEYP), TKEYP
+	je .L4enc192
+	add $0x20, TKEYP
+	movaps -0x60(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps -0x50(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+#.align 4
+.L4enc192:
+	movaps -0x40(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps -0x30(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+#.align 4
+.L4enc128:
+	movaps -0x20(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps -0x10(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps (TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps 0x10(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps 0x20(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps 0x30(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps 0x40(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps 0x50(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps 0x60(TKEYP), KEY
+	# aesenc KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xc2
+	# aesenc KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xe2
+	# aesenc KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xea
+	# aesenc KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdc, 0xf2
+	movaps 0x70(TKEYP), KEY
+	# aesenclast KEY, STATE1	# last round
+	.byte 0x66, 0x0f, 0x38, 0xdd, 0xc2
+	# aesenclast KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdd, 0xe2
+	# aesenclast KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdd, 0xea
+	# aesenclast KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdd, 0xf2
+	ret
+
+/*
+ * void aesni_dec (struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
+ */
+ENTRY(aesni_dec)
+	mov 480(KEYP), KLEN		# key length
+	add $240, KEYP
+	movups (INP), STATE		# input
+	call _aesni_dec1
+	movups STATE, (OUTP)		#output
+	ret
+
+/*
+ * _aesni_dec1:		internal ABI
+ * input:
+ *	KEYP:		key struct pointer
+ *	KLEN:		key length
+ *	STATE:		initial state (input)
+ * output:
+ *	STATE:		finial state (output)
+ * changed:
+ *	KEY
+ *	TKEYP (T1)
+ */
+_aesni_dec1:
+	movaps (KEYP), KEY		# key
+	mov KEYP, TKEYP
+	pxor KEY, STATE		# round 0
+	add $0x30, TKEYP
+	cmp $24, KLEN
+	jb .Ldec128
+	lea 0x20(TKEYP), TKEYP
+	je .Ldec192
+	add $0x20, TKEYP
+	movaps -0x60(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps -0x50(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+.align 4
+.Ldec192:
+	movaps -0x40(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps -0x30(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+.align 4
+.Ldec128:
+	movaps -0x20(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps -0x10(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps (TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps 0x10(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps 0x20(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps 0x30(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps 0x40(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps 0x50(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps 0x60(TKEYP), KEY
+	# aesdec KEY, STATE
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	movaps 0x70(TKEYP), KEY
+	# aesdeclast KEY, STATE		# last round
+	.byte 0x66, 0x0f, 0x38, 0xdf, 0xc2
+	ret
+
+/*
+ * _aesni_dec4:	internal ABI
+ * input:
+ *	KEYP:		key struct pointer
+ *	KLEN:		key length
+ *	STATE1:		initial state (input)
+ *	STATE2
+ *	STATE3
+ *	STATE4
+ * output:
+ *	STATE1:		finial state (output)
+ *	STATE2
+ *	STATE3
+ *	STATE4
+ * changed:
+ *	KEY
+ *	TKEYP (T1)
+ */
+_aesni_dec4:
+	movaps (KEYP), KEY		# key
+	mov KEYP, TKEYP
+	pxor KEY, STATE1		# round 0
+	pxor KEY, STATE2
+	pxor KEY, STATE3
+	pxor KEY, STATE4
+	add $0x30, TKEYP
+	cmp $24, KLEN
+	jb .L4dec128
+	lea 0x20(TKEYP), TKEYP
+	je .L4dec192
+	add $0x20, TKEYP
+	movaps -0x60(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps -0x50(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+.align 4
+.L4dec192:
+	movaps -0x40(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps -0x30(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+.align 4
+.L4dec128:
+	movaps -0x20(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps -0x10(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps (TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps 0x10(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps 0x20(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps 0x30(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps 0x40(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps 0x50(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps 0x60(TKEYP), KEY
+	# aesdec KEY, STATE1
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xc2
+	# aesdec KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xe2
+	# aesdec KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xea
+	# aesdec KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xde, 0xf2
+	movaps 0x70(TKEYP), KEY
+	# aesdeclast KEY, STATE1	# last round
+	.byte 0x66, 0x0f, 0x38, 0xdf, 0xc2
+	# aesdeclast KEY, STATE2
+	.byte 0x66, 0x0f, 0x38, 0xdf, 0xe2
+	# aesdeclast KEY, STATE3
+	.byte 0x66, 0x0f, 0x38, 0xdf, 0xea
+	# aesdeclast KEY, STATE4
+	.byte 0x66, 0x0f, 0x38, 0xdf, 0xf2
+	ret
+
+/*
+ * void aesni_ecb_enc(struct crypto_aes_ctx *ctx, const u8 *dst, u8 *src,
+ *		      size_t len)
+ */
+ENTRY(aesni_ecb_enc)
+	test LEN, LEN		# check length
+	jz .Lecb_enc_ret
+	mov 480(KEYP), KLEN
+	cmp $16, LEN
+	jb .Lecb_enc_ret
+	cmp $64, LEN
+	jb .Lecb_enc_loop1
+.align 4
+.Lecb_enc_loop4:
+	movups (INP), STATE1
+	movups 0x10(INP), STATE2
+	movups 0x20(INP), STATE3
+	movups 0x30(INP), STATE4
+	call _aesni_enc4
+	movups STATE1, (OUTP)
+	movups STATE2, 0x10(OUTP)
+	movups STATE3, 0x20(OUTP)
+	movups STATE4, 0x30(OUTP)
+	sub $64, LEN
+	add $64, INP
+	add $64, OUTP
+	cmp $64, LEN
+	jge .Lecb_enc_loop4
+	cmp $16, LEN
+	jb .Lecb_enc_ret
+.align 4
+.Lecb_enc_loop1:
+	movups (INP), STATE1
+	call _aesni_enc1
+	movups STATE1, (OUTP)
+	sub $16, LEN
+	add $16, INP
+	add $16, OUTP
+	cmp $16, LEN
+	jge .Lecb_enc_loop1
+.Lecb_enc_ret:
+	ret
+
+/*
+ * void aesni_ecb_dec(struct crypto_aes_ctx *ctx, const u8 *dst, u8 *src,
+ *		      size_t len);
+ */
+ENTRY(aesni_ecb_dec)
+	test LEN, LEN
+	jz .Lecb_dec_ret
+	mov 480(KEYP), KLEN
+	add $240, KEYP
+	cmp $16, LEN
+	jb .Lecb_dec_ret
+	cmp $64, LEN
+	jb .Lecb_dec_loop1
+.align 4
+.Lecb_dec_loop4:
+	movups (INP), STATE1
+	movups 0x10(INP), STATE2
+	movups 0x20(INP), STATE3
+	movups 0x30(INP), STATE4
+	call _aesni_dec4
+	movups STATE1, (OUTP)
+	movups STATE2, 0x10(OUTP)
+	movups STATE3, 0x20(OUTP)
+	movups STATE4, 0x30(OUTP)
+	sub $64, LEN
+	add $64, INP
+	add $64, OUTP
+	cmp $64, LEN
+	jge .Lecb_dec_loop4
+	cmp $16, LEN
+	jb .Lecb_dec_ret
+.align 4
+.Lecb_dec_loop1:
+	movups (INP), STATE1
+	call _aesni_dec1
+	movups STATE1, (OUTP)
+	sub $16, LEN
+	add $16, INP
+	add $16, OUTP
+	cmp $16, LEN
+	jge .Lecb_dec_loop1
+.Lecb_dec_ret:
+	ret
+
+/*
+ * void aesni_cbc_enc(struct crypto_aes_ctx *ctx, const u8 *dst, u8 *src,
+ *		      size_t len, u8 *iv)
+ */
+ENTRY(aesni_cbc_enc)
+	cmp $16, LEN
+	jb .Lcbc_enc_ret
+	mov 480(KEYP), KLEN
+	movups (IVP), STATE	# load iv as initial state
+.align 4
+.Lcbc_enc_loop:
+	movups (INP), IN	# load input
+	pxor IN, STATE
+	call _aesni_enc1
+	movups STATE, (OUTP)	# store output
+	sub $16, LEN
+	add $16, INP
+	add $16, OUTP
+	cmp $16, LEN
+	jge .Lcbc_enc_loop
+	movups STATE, (IVP)
+.Lcbc_enc_ret:
+	ret
+
+/*
+ * void aesni_cbc_dec(struct crypto_aes_ctx *ctx, const u8 *dst, u8 *src,
+ *		      size_t len, u8 *iv)
+ */
+ENTRY(aesni_cbc_dec)
+	cmp $16, LEN
+	jb .Lcbc_dec_ret
+	mov 480(KEYP), KLEN
+	add $240, KEYP
+	movups (IVP), IV
+	cmp $64, LEN
+	jb .Lcbc_dec_loop1
+.align 4
+.Lcbc_dec_loop4:
+	movups (INP), IN1
+	movaps IN1, STATE1
+	movups 0x10(INP), IN2
+	movaps IN2, STATE2
+	movups 0x20(INP), IN3
+	movaps IN3, STATE3
+	movups 0x30(INP), IN4
+	movaps IN4, STATE4
+	call _aesni_dec4
+	pxor IV, STATE1
+	pxor IN1, STATE2
+	pxor IN2, STATE3
+	pxor IN3, STATE4
+	movaps IN4, IV
+	movups STATE1, (OUTP)
+	movups STATE2, 0x10(OUTP)
+	movups STATE3, 0x20(OUTP)
+	movups STATE4, 0x30(OUTP)
+	sub $64, LEN
+	add $64, INP
+	add $64, OUTP
+	cmp $64, LEN
+	jge .Lcbc_dec_loop4
+	cmp $16, LEN
+	jb .Lcbc_dec_ret
+.align 4
+.Lcbc_dec_loop1:
+	movups (INP), IN
+	movaps IN, STATE
+	call _aesni_dec1
+	pxor IV, STATE
+	movups STATE, (OUTP)
+	movaps IN, IV
+	sub $16, LEN
+	add $16, INP
+	add $16, OUTP
+	cmp $16, LEN
+	jge .Lcbc_dec_loop1
+	movups IV, (IVP)
+.Lcbc_dec_ret:
+	ret
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
new file mode 100644
index 0000000..02af0af
--- /dev/null
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -0,0 +1,461 @@
+/*
+ * Support for Intel AES-NI instructions. This file contains glue
+ * code, the real AES implementation is in intel-aes_asm.S.
+ *
+ * Copyright (C) 2008, Intel Corp.
+ *    Author: Huang Ying <ying.huang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/hardirq.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/cryptd.h>
+#include <asm/i387.h>
+#include <asm/aes.h>
+
+struct async_aes_ctx {
+	struct cryptd_ablkcipher *cryptd_tfm;
+};
+
+#define AESNI_ALIGN	16
+#define AES_BLOCK_MASK	(~(AES_BLOCK_SIZE-1))
+
+asmlinkage int aesni_set_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
+			     unsigned int key_len);
+asmlinkage void aesni_enc(struct crypto_aes_ctx *ctx, u8 *out,
+			  const u8 *in);
+asmlinkage void aesni_dec(struct crypto_aes_ctx *ctx, u8 *out,
+			  const u8 *in);
+asmlinkage void aesni_ecb_enc(struct crypto_aes_ctx *ctx, u8 *out,
+			      const u8 *in, unsigned int len);
+asmlinkage void aesni_ecb_dec(struct crypto_aes_ctx *ctx, u8 *out,
+			      const u8 *in, unsigned int len);
+asmlinkage void aesni_cbc_enc(struct crypto_aes_ctx *ctx, u8 *out,
+			      const u8 *in, unsigned int len, u8 *iv);
+asmlinkage void aesni_cbc_dec(struct crypto_aes_ctx *ctx, u8 *out,
+			      const u8 *in, unsigned int len, u8 *iv);
+
+static inline int kernel_fpu_using(void)
+{
+	if (in_interrupt() && !(read_cr0() & X86_CR0_TS))
+		return 1;
+	return 0;
+}
+
+static inline struct crypto_aes_ctx *aes_ctx(void *raw_ctx)
+{
+	unsigned long addr = (unsigned long)raw_ctx;
+	unsigned long align = AESNI_ALIGN;
+
+	if (align <= crypto_tfm_ctx_alignment())
+		align = 1;
+	return (struct crypto_aes_ctx *)ALIGN(addr, align);
+}
+
+static int aes_set_key_common(struct crypto_tfm *tfm, void *raw_ctx,
+			      const u8 *in_key, unsigned int key_len)
+{
+	struct crypto_aes_ctx *ctx = aes_ctx(raw_ctx);
+	u32 *flags = &tfm->crt_flags;
+	int err;
+
+	if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 &&
+	    key_len != AES_KEYSIZE_256) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	if (kernel_fpu_using())
+		err = crypto_aes_expand_key(ctx, in_key, key_len);
+	else {
+		kernel_fpu_begin();
+		err = aesni_set_key(ctx, in_key, key_len);
+		kernel_fpu_end();
+	}
+
+	return err;
+}
+
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		       unsigned int key_len)
+{
+	return aes_set_key_common(tfm, crypto_tfm_ctx(tfm), in_key, key_len);
+}
+
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm));
+
+	if (kernel_fpu_using())
+		crypto_aes_encrypt_x86(ctx, dst, src);
+	else {
+		kernel_fpu_begin();
+		aesni_enc(ctx, dst, src);
+		kernel_fpu_end();
+	}
+}
+
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm));
+
+	if (kernel_fpu_using())
+		crypto_aes_decrypt_x86(ctx, dst, src);
+	else {
+		kernel_fpu_begin();
+		aesni_dec(ctx, dst, src);
+		kernel_fpu_end();
+	}
+}
+
+static struct crypto_alg aesni_alg = {
+	.cra_name		= "aes",
+	.cra_driver_name	= "aes-aesni",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
+	.cra_alignmask		= 0,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(aesni_alg.cra_list),
+	.cra_u	= {
+		.cipher	= {
+			.cia_min_keysize	= AES_MIN_KEY_SIZE,
+			.cia_max_keysize	= AES_MAX_KEY_SIZE,
+			.cia_setkey		= aes_set_key,
+			.cia_encrypt		= aes_encrypt,
+			.cia_decrypt		= aes_decrypt
+		}
+	}
+};
+
+static int ecb_encrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_blkcipher_ctx(desc->tfm));
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	kernel_fpu_begin();
+	while ((nbytes = walk.nbytes)) {
+		aesni_ecb_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+			      nbytes & AES_BLOCK_MASK);
+		nbytes &= AES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	kernel_fpu_end();
+
+	return err;
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_blkcipher_ctx(desc->tfm));
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	kernel_fpu_begin();
+	while ((nbytes = walk.nbytes)) {
+		aesni_ecb_dec(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+			      nbytes & AES_BLOCK_MASK);
+		nbytes &= AES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	kernel_fpu_end();
+
+	return err;
+}
+
+static struct crypto_alg blk_ecb_alg = {
+	.cra_name		= "__ecb-aes-aesni",
+	.cra_driver_name	= "__driver-ecb-aes-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ecb_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
+			.setkey		= aes_set_key,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+};
+
+static int cbc_encrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_blkcipher_ctx(desc->tfm));
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	kernel_fpu_begin();
+	while ((nbytes = walk.nbytes)) {
+		aesni_cbc_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+			      nbytes & AES_BLOCK_MASK, walk.iv);
+		nbytes &= AES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	kernel_fpu_end();
+
+	return err;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_blkcipher_ctx(desc->tfm));
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	kernel_fpu_begin();
+	while ((nbytes = walk.nbytes)) {
+		aesni_cbc_dec(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+			      nbytes & AES_BLOCK_MASK, walk.iv);
+		nbytes &= AES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	kernel_fpu_end();
+
+	return err;
+}
+
+static struct crypto_alg blk_cbc_alg = {
+	.cra_name		= "__cbc-aes-aesni",
+	.cra_driver_name	= "__driver-cbc-aes-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_cbc_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
+			.setkey		= aes_set_key,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+};
+
+static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
+			unsigned int key_len)
+{
+	struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+
+	return crypto_ablkcipher_setkey(&ctx->cryptd_tfm->base, key, key_len);
+}
+
+static int ablk_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+	struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+
+	if (kernel_fpu_using()) {
+		struct ablkcipher_request *cryptd_req =
+			ablkcipher_request_ctx(req);
+		memcpy(cryptd_req, req, sizeof(*req));
+		ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
+		return crypto_ablkcipher_encrypt(cryptd_req);
+	} else {
+		struct blkcipher_desc desc;
+		desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
+		desc.info = req->info;
+		desc.flags = 0;
+		return crypto_blkcipher_crt(desc.tfm)->encrypt(
+			&desc, req->dst, req->src, req->nbytes);
+	}
+}
+
+static int ablk_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+	struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+
+	if (kernel_fpu_using()) {
+		struct ablkcipher_request *cryptd_req =
+			ablkcipher_request_ctx(req);
+		memcpy(cryptd_req, req, sizeof(*req));
+		ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
+		return crypto_ablkcipher_decrypt(cryptd_req);
+	} else {
+		struct blkcipher_desc desc;
+		desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
+		desc.info = req->info;
+		desc.flags = 0;
+		return crypto_blkcipher_crt(desc.tfm)->decrypt(
+			&desc, req->dst, req->src, req->nbytes);
+	}
+}
+
+static void ablk_exit(struct crypto_tfm *tfm)
+{
+	struct async_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	cryptd_free_ablkcipher(ctx->cryptd_tfm);
+}
+
+static void ablk_init_common(struct crypto_tfm *tfm,
+			     struct cryptd_ablkcipher *cryptd_tfm)
+{
+	struct async_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->cryptd_tfm = cryptd_tfm;
+	tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
+		crypto_ablkcipher_reqsize(&cryptd_tfm->base);
+}
+
+static int ablk_ecb_init(struct crypto_tfm *tfm)
+{
+	struct cryptd_ablkcipher *cryptd_tfm;
+
+	cryptd_tfm = cryptd_alloc_ablkcipher("__driver-ecb-aes-aesni", 0, 0);
+	if (IS_ERR(cryptd_tfm))
+		return PTR_ERR(cryptd_tfm);
+	ablk_init_common(tfm, cryptd_tfm);
+	return 0;
+}
+
+static struct crypto_alg ablk_ecb_alg = {
+	.cra_name		= "ecb(aes)",
+	.cra_driver_name	= "ecb-aes-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_aes_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(ablk_ecb_alg.cra_list),
+	.cra_init		= ablk_ecb_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+};
+
+static int ablk_cbc_init(struct crypto_tfm *tfm)
+{
+	struct cryptd_ablkcipher *cryptd_tfm;
+
+	cryptd_tfm = cryptd_alloc_ablkcipher("__driver-cbc-aes-aesni", 0, 0);
+	if (IS_ERR(cryptd_tfm))
+		return PTR_ERR(cryptd_tfm);
+	ablk_init_common(tfm, cryptd_tfm);
+	return 0;
+}
+
+static struct crypto_alg ablk_cbc_alg = {
+	.cra_name		= "cbc(aes)",
+	.cra_driver_name	= "cbc-aes-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_aes_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(ablk_cbc_alg.cra_list),
+	.cra_init		= ablk_cbc_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
+			.ivsize		= AES_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+};
+
+static int __init aesni_init(void)
+{
+	int err;
+
+	if (!cpu_has_aes) {
+		printk(KERN_ERR "Intel AES-NI instructions are not detected.\n");
+		return -ENODEV;
+	}
+	if ((err = crypto_register_alg(&aesni_alg)))
+		goto aes_err;
+	if ((err = crypto_register_alg(&blk_ecb_alg)))
+		goto blk_ecb_err;
+	if ((err = crypto_register_alg(&blk_cbc_alg)))
+		goto blk_cbc_err;
+	if ((err = crypto_register_alg(&ablk_ecb_alg)))
+		goto ablk_ecb_err;
+	if ((err = crypto_register_alg(&ablk_cbc_alg)))
+		goto ablk_cbc_err;
+
+	return err;
+
+ablk_cbc_err:
+	crypto_unregister_alg(&ablk_ecb_alg);
+ablk_ecb_err:
+	crypto_unregister_alg(&blk_cbc_alg);
+blk_cbc_err:
+	crypto_unregister_alg(&blk_ecb_alg);
+blk_ecb_err:
+	crypto_unregister_alg(&aesni_alg);
+aes_err:
+	return err;
+}
+
+static void __exit aesni_exit(void)
+{
+	crypto_unregister_alg(&ablk_cbc_alg);
+	crypto_unregister_alg(&ablk_ecb_alg);
+	crypto_unregister_alg(&blk_cbc_alg);
+	crypto_unregister_alg(&blk_ecb_alg);
+	crypto_unregister_alg(&aesni_alg);
+}
+
+module_init(aesni_init);
+module_exit(aesni_exit);
+
+MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, Intel AES-NI instructions optimized");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("aes");
diff --git a/arch/x86/include/asm/aes.h b/arch/x86/include/asm/aes.h
new file mode 100644
index 0000000..80545a1
--- /dev/null
+++ b/arch/x86/include/asm/aes.h
@@ -0,0 +1,11 @@
+#ifndef ASM_X86_AES_H
+#define ASM_X86_AES_H
+
+#include <linux/crypto.h>
+#include <crypto/aes.h>
+
+void crypto_aes_encrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst,
+			    const u8 *src);
+void crypto_aes_decrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst,
+			    const u8 *src);
+#endif
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 7301e60..0beba0d 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -213,6 +213,7 @@
 #define cpu_has_xmm		boot_cpu_has(X86_FEATURE_XMM)
 #define cpu_has_xmm2		boot_cpu_has(X86_FEATURE_XMM2)
 #define cpu_has_xmm3		boot_cpu_has(X86_FEATURE_XMM3)
+#define cpu_has_aes		boot_cpu_has(X86_FEATURE_AES)
 #define cpu_has_ht		boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp		boot_cpu_has(X86_FEATURE_MP)
 #define cpu_has_nx		boot_cpu_has(X86_FEATURE_NX)
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index ca5ffb2..edc90f2 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -37,8 +37,6 @@
 
 #else /* !CONFIG_X86_32 */
 
-#define MAX_EFI_IO_PAGES	100
-
 extern u64 efi_call0(void *fp);
 extern u64 efi_call1(void *fp, u64 arg1);
 extern u64 efi_call2(void *fp, u64 arg1, u64 arg2);
diff --git a/arch/x86/include/asm/fixmap_64.h b/arch/x86/include/asm/fixmap_64.h
index 00a30ab9..8be7409 100644
--- a/arch/x86/include/asm/fixmap_64.h
+++ b/arch/x86/include/asm/fixmap_64.h
@@ -16,7 +16,6 @@
 #include <asm/apicdef.h>
 #include <asm/page.h>
 #include <asm/vsyscall.h>
-#include <asm/efi.h>
 
 /*
  * Here we define all the compile-time 'special' virtual
@@ -43,9 +42,6 @@
 	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_EFI_IO_MAP_LAST_PAGE,
-	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE
-				  + MAX_EFI_IO_PAGES - 1,
 #ifdef CONFIG_PARAVIRT
 	FIX_PARAVIRT_BOOTMAP,
 #endif
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index 48f0004..71c9e51 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -172,7 +172,13 @@
 
 #else  /* CONFIG_X86_32 */
 
-extern void finit(void);
+#ifdef CONFIG_MATH_EMULATION
+extern void finit_task(struct task_struct *tsk);
+#else
+static inline void finit_task(struct task_struct *tsk)
+{
+}
+#endif
 
 static inline void tolerant_fwait(void)
 {
diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
index 2bb6a83..4f5c247 100644
--- a/arch/x86/include/asm/timer.h
+++ b/arch/x86/include/asm/timer.h
@@ -11,8 +11,8 @@
 
 #ifdef CONFIG_X86_32
 extern int timer_ack;
+#endif
 extern int recalibrate_cpu_khz(void);
-#endif /* CONFIG_X86_32 */
 
 extern int no_timer_check;
 
diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig
index 65792c2..52c8398 100644
--- a/arch/x86/kernel/cpu/cpufreq/Kconfig
+++ b/arch/x86/kernel/cpu/cpufreq/Kconfig
@@ -87,30 +87,15 @@
 config X86_POWERNOW_K8
 	tristate "AMD Opteron/Athlon64 PowerNow!"
 	select CPU_FREQ_TABLE
+	depends on ACPI && ACPI_PROCESSOR
 	help
-	  This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
+	  This adds the CPUFreq driver for K8/K10 Opteron/Athlon64 processors.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called powernow-k8.
 
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 
-	  If in doubt, say N.
-
-config X86_POWERNOW_K8_ACPI
-	bool
-	prompt "ACPI Support" if X86_32
-	depends on ACPI && X86_POWERNOW_K8 && ACPI_PROCESSOR
-	depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
-	default y
-	help
-	  This provides access to the K8s Processor Performance States via ACPI.
-	  This driver is probably required for CPUFreq to work with multi-socket and
-	  SMP systems.  It is not required on at least some single-socket yet
-	  multi-core systems, even if SMP is enabled.
-
-	  It is safe to say Y here.
-
 config X86_GX_SUSPMOD
 	tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
 	depends on X86_32 && PCI
diff --git a/arch/x86/kernel/cpu/cpufreq/Makefile b/arch/x86/kernel/cpu/cpufreq/Makefile
index 560f776..509296d 100644
--- a/arch/x86/kernel/cpu/cpufreq/Makefile
+++ b/arch/x86/kernel/cpu/cpufreq/Makefile
@@ -1,6 +1,11 @@
+# Link order matters. K8 is preferred to ACPI because of firmware bugs in early
+# K8 systems. ACPI is preferred to all other hardware-specific drivers.
+# speedstep-* is preferred over p4-clockmod.
+
+obj-$(CONFIG_X86_POWERNOW_K8)		+= powernow-k8.o
+obj-$(CONFIG_X86_ACPI_CPUFREQ)		+= acpi-cpufreq.o
 obj-$(CONFIG_X86_POWERNOW_K6)		+= powernow-k6.o
 obj-$(CONFIG_X86_POWERNOW_K7)		+= powernow-k7.o
-obj-$(CONFIG_X86_POWERNOW_K8)		+= powernow-k8.o
 obj-$(CONFIG_X86_LONGHAUL)		+= longhaul.o
 obj-$(CONFIG_X86_E_POWERSAVER)		+= e_powersaver.o
 obj-$(CONFIG_ELAN_CPUFREQ)		+= elanfreq.o
@@ -10,7 +15,6 @@
 obj-$(CONFIG_X86_SPEEDSTEP_ICH)		+= speedstep-ich.o
 obj-$(CONFIG_X86_SPEEDSTEP_LIB)		+= speedstep-lib.o
 obj-$(CONFIG_X86_SPEEDSTEP_SMI)		+= speedstep-smi.o
-obj-$(CONFIG_X86_ACPI_CPUFREQ)		+= acpi-cpufreq.o
 obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO)	+= speedstep-centrino.o
 obj-$(CONFIG_X86_P4_CLOCKMOD)		+= p4-clockmod.o
 obj-$(CONFIG_X86_CPUFREQ_NFORCE2)	+= cpufreq-nforce2.o
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index 4b1c319..3babe1f 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -1,5 +1,5 @@
 /*
- * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.4 $)
+ * acpi-cpufreq.c - ACPI Processor P-States Driver
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -36,16 +36,18 @@
 #include <linux/ftrace.h>
 
 #include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+
 #include <acpi/processor.h>
 
-#include <asm/io.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpufeature.h>
-#include <asm/delay.h>
-#include <asm/uaccess.h>
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"acpi-cpufreq", msg)
 
 MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
@@ -95,7 +97,7 @@
 
 	perf = data->acpi_data;
 
-	for (i=0; i<perf->state_count; i++) {
+	for (i = 0; i < perf->state_count; i++) {
 		if (value == perf->states[i].status)
 			return data->freq_table[i].frequency;
 	}
@@ -110,7 +112,7 @@
 	msr &= INTEL_MSR_RANGE;
 	perf = data->acpi_data;
 
-	for (i=0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+	for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
 		if (msr == perf->states[data->freq_table[i].index].status)
 			return data->freq_table[i].frequency;
 	}
@@ -138,15 +140,13 @@
 	u8 bit_width;
 };
 
-typedef union {
-	struct msr_addr msr;
-	struct io_addr io;
-} drv_addr_union;
-
 struct drv_cmd {
 	unsigned int type;
 	const struct cpumask *mask;
-	drv_addr_union addr;
+	union {
+		struct msr_addr msr;
+		struct io_addr io;
+	} addr;
 	u32 val;
 };
 
@@ -369,7 +369,7 @@
 	unsigned int cur_freq;
 	unsigned int i;
 
-	for (i=0; i<100; i++) {
+	for (i = 0; i < 100; i++) {
 		cur_freq = extract_freq(get_cur_val(mask), data);
 		if (cur_freq == freq)
 			return 1;
@@ -494,7 +494,7 @@
 		unsigned long freq;
 		unsigned long freqn = perf->states[0].core_frequency * 1000;
 
-		for (i=0; i<(perf->state_count-1); i++) {
+		for (i = 0; i < (perf->state_count-1); i++) {
 			freq = freqn;
 			freqn = perf->states[i+1].core_frequency * 1000;
 			if ((2 * cpu_khz) > (freqn + freq)) {
@@ -673,7 +673,7 @@
 
 	/* detect transition latency */
 	policy->cpuinfo.transition_latency = 0;
-	for (i=0; i<perf->state_count; i++) {
+	for (i = 0; i < perf->state_count; i++) {
 		if ((perf->states[i].transition_latency * 1000) >
 		    policy->cpuinfo.transition_latency)
 			policy->cpuinfo.transition_latency =
@@ -682,8 +682,8 @@
 
 	data->max_freq = perf->states[0].core_frequency * 1000;
 	/* table init */
-	for (i=0; i<perf->state_count; i++) {
-		if (i>0 && perf->states[i].core_frequency >=
+	for (i = 0; i < perf->state_count; i++) {
+		if (i > 0 && perf->states[i].core_frequency >=
 		    data->freq_table[valid_states-1].frequency / 1000)
 			continue;
 
diff --git a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
index 965ea52..733093d 100644
--- a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
+++ b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -32,7 +32,7 @@
  * nforce2_chipset:
  * FSB is changed using the chipset
  */
-static struct pci_dev *nforce2_chipset_dev;
+static struct pci_dev *nforce2_dev;
 
 /* fid:
  * multiplier * 10
@@ -56,7 +56,9 @@
 MODULE_PARM_DESC(min_fsb,
 		"Minimum FSB to use, if not defined: current FSB - 50");
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "cpufreq-nforce2", msg)
+#define PFX "cpufreq-nforce2: "
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"cpufreq-nforce2", msg)
 
 /**
  * nforce2_calc_fsb - calculate FSB
@@ -118,11 +120,11 @@
 	int temp;
 
 	/* Set the pll addr. to 0x00 */
-	pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, 0);
+	pci_write_config_dword(nforce2_dev, NFORCE2_PLLADR, 0);
 
 	/* Now write the value in all 64 registers */
 	for (temp = 0; temp <= 0x3f; temp++)
-		pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLREG, pll);
+		pci_write_config_dword(nforce2_dev, NFORCE2_PLLREG, pll);
 
 	return;
 }
@@ -139,8 +141,8 @@
 	u32 fsb, temp = 0;
 
 	/* Get chipset boot FSB from subdevice 5 (FSB at boot-time) */
-	nforce2_sub5 = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
-						0x01EF, PCI_ANY_ID, PCI_ANY_ID, NULL);
+	nforce2_sub5 = pci_get_subsys(PCI_VENDOR_ID_NVIDIA, 0x01EF,
+				PCI_ANY_ID, PCI_ANY_ID, NULL);
 	if (!nforce2_sub5)
 		return 0;
 
@@ -148,13 +150,13 @@
 	fsb /= 1000000;
 
 	/* Check if PLL register is already set */
-	pci_read_config_byte(nforce2_chipset_dev, NFORCE2_PLLENABLE, (u8 *)&temp);
+	pci_read_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8 *)&temp);
 
 	if (bootfsb || !temp)
 		return fsb;
 
 	/* Use PLL register FSB value */
-	pci_read_config_dword(nforce2_chipset_dev, NFORCE2_PLLREG, &temp);
+	pci_read_config_dword(nforce2_dev, NFORCE2_PLLREG, &temp);
 	fsb = nforce2_calc_fsb(temp);
 
 	return fsb;
@@ -174,18 +176,18 @@
 	int pll = 0;
 
 	if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) {
-		printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb);
+		printk(KERN_ERR PFX "FSB %d is out of range!\n", fsb);
 		return -EINVAL;
 	}
 
 	tfsb = nforce2_fsb_read(0);
 	if (!tfsb) {
-		printk(KERN_ERR "cpufreq: Error while reading the FSB\n");
+		printk(KERN_ERR PFX "Error while reading the FSB\n");
 		return -EINVAL;
 	}
 
 	/* First write? Then set actual value */
-	pci_read_config_byte(nforce2_chipset_dev, NFORCE2_PLLENABLE, (u8 *)&temp);
+	pci_read_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8 *)&temp);
 	if (!temp) {
 		pll = nforce2_calc_pll(tfsb);
 
@@ -197,7 +199,7 @@
 
 	/* Enable write access */
 	temp = 0x01;
-	pci_write_config_byte(nforce2_chipset_dev, NFORCE2_PLLENABLE, (u8)temp);
+	pci_write_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8)temp);
 
 	diff = tfsb - fsb;
 
@@ -222,7 +224,7 @@
 	}
 
 	temp = 0x40;
-	pci_write_config_byte(nforce2_chipset_dev, NFORCE2_PLLADR, (u8)temp);
+	pci_write_config_byte(nforce2_dev, NFORCE2_PLLADR, (u8)temp);
 
 	return 0;
 }
@@ -244,7 +246,8 @@
  * nforce2_target - set a new CPUFreq policy
  * @policy: new policy
  * @target_freq: the target frequency
- * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
+ * @relation: how that frequency relates to achieved frequency
+ *  (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
  *
  * Sets a new CPUFreq policy.
  */
@@ -276,7 +279,7 @@
 	/* local_irq_save(flags); */
 
 	if (nforce2_set_fsb(target_fsb) < 0)
-		printk(KERN_ERR "cpufreq: Changing FSB to %d failed\n",
+		printk(KERN_ERR PFX "Changing FSB to %d failed\n",
 			target_fsb);
 	else
 		dprintk("Changed FSB successfully to %d\n",
@@ -327,8 +330,8 @@
 	/* FIX: Get FID from CPU */
 	if (!fid) {
 		if (!cpu_khz) {
-			printk(KERN_WARNING
-			       "cpufreq: cpu_khz not set, can't calculate multiplier!\n");
+			printk(KERN_WARNING PFX
+			"cpu_khz not set, can't calculate multiplier!\n");
 			return -ENODEV;
 		}
 
@@ -343,7 +346,7 @@
 		}
 	}
 
-	printk(KERN_INFO "cpufreq: FSB currently at %i MHz, FID %d.%d\n", fsb,
+	printk(KERN_INFO PFX "FSB currently at %i MHz, FID %d.%d\n", fsb,
 	       fid / 10, fid % 10);
 
 	/* Set maximum FSB to FSB at boot time */
@@ -392,17 +395,18 @@
  */
 static unsigned int nforce2_detect_chipset(void)
 {
-	nforce2_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
+	nforce2_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
 					PCI_DEVICE_ID_NVIDIA_NFORCE2,
 					PCI_ANY_ID, PCI_ANY_ID, NULL);
 
-	if (nforce2_chipset_dev == NULL)
+	if (nforce2_dev == NULL)
 		return -ENODEV;
 
-	printk(KERN_INFO "cpufreq: Detected nForce2 chipset revision %X\n",
-	       nforce2_chipset_dev->revision);
-	printk(KERN_INFO
-	       "cpufreq: FSB changing is maybe unstable and can lead to crashes and data loss.\n");
+	printk(KERN_INFO PFX "Detected nForce2 chipset revision %X\n",
+	       nforce2_dev->revision);
+	printk(KERN_INFO PFX
+	       "FSB changing is maybe unstable and can lead to "
+	       "crashes and data loss.\n");
 
 	return 0;
 }
@@ -420,7 +424,7 @@
 
 	/* detect chipset */
 	if (nforce2_detect_chipset()) {
-		printk(KERN_ERR "cpufreq: No nForce2 chipset.\n");
+		printk(KERN_INFO PFX "No nForce2 chipset.\n");
 		return -ENODEV;
 	}
 
diff --git a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
index c2f930d..3f83ea1 100644
--- a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
+++ b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
@@ -12,12 +12,12 @@
 #include <linux/cpufreq.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
+#include <linux/timex.h>
+#include <linux/io.h>
+#include <linux/delay.h>
 
 #include <asm/msr.h>
 #include <asm/tsc.h>
-#include <asm/timex.h>
-#include <asm/io.h>
-#include <asm/delay.h>
 
 #define EPS_BRAND_C7M	0
 #define EPS_BRAND_C7	1
@@ -184,7 +184,7 @@
 		break;
 	}
 
-	switch(brand) {
+	switch (brand) {
 	case EPS_BRAND_C7M:
 		printk(KERN_CONT "C7-M\n");
 		break;
@@ -218,17 +218,20 @@
 	/* Print voltage and multiplier */
 	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
 	current_voltage = lo & 0xff;
-	printk(KERN_INFO "eps: Current voltage = %dmV\n", current_voltage * 16 + 700);
+	printk(KERN_INFO "eps: Current voltage = %dmV\n",
+			current_voltage * 16 + 700);
 	current_multiplier = (lo >> 8) & 0xff;
 	printk(KERN_INFO "eps: Current multiplier = %d\n", current_multiplier);
 
 	/* Print limits */
 	max_voltage = hi & 0xff;
-	printk(KERN_INFO "eps: Highest voltage = %dmV\n", max_voltage * 16 + 700);
+	printk(KERN_INFO "eps: Highest voltage = %dmV\n",
+			max_voltage * 16 + 700);
 	max_multiplier = (hi >> 8) & 0xff;
 	printk(KERN_INFO "eps: Highest multiplier = %d\n", max_multiplier);
 	min_voltage = (hi >> 16) & 0xff;
-	printk(KERN_INFO "eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700);
+	printk(KERN_INFO "eps: Lowest voltage = %dmV\n",
+			min_voltage * 16 + 700);
 	min_multiplier = (hi >> 24) & 0xff;
 	printk(KERN_INFO "eps: Lowest multiplier = %d\n", min_multiplier);
 
@@ -318,7 +321,7 @@
 	return 0;
 }
 
-static struct freq_attr* eps_attr[] = {
+static struct freq_attr *eps_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
 };
@@ -356,7 +359,7 @@
 	cpufreq_unregister_driver(&eps_driver);
 }
 
-MODULE_AUTHOR("Rafa³ Bilski <rafalbilski@interia.pl>");
+MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>");
 MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's.");
 MODULE_LICENSE("GPL");
 
diff --git a/arch/x86/kernel/cpu/cpufreq/elanfreq.c b/arch/x86/kernel/cpu/cpufreq/elanfreq.c
index fe613c9..006b278 100644
--- a/arch/x86/kernel/cpu/cpufreq/elanfreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/elanfreq.c
@@ -184,7 +184,8 @@
 {
 	unsigned int newstate = 0;
 
-	if (cpufreq_frequency_table_target(policy, &elanfreq_table[0], target_freq, relation, &newstate))
+	if (cpufreq_frequency_table_target(policy, &elanfreq_table[0],
+				target_freq, relation, &newstate))
 		return -EINVAL;
 
 	elanfreq_set_cpu_state(newstate);
@@ -301,7 +302,8 @@
 module_param(max_freq, int, 0444);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Robert Schwebel <r.schwebel@pengutronix.de>, Sven Geggus <sven@geggus.net>");
+MODULE_AUTHOR("Robert Schwebel <r.schwebel@pengutronix.de>, "
+		"Sven Geggus <sven@geggus.net>");
 MODULE_DESCRIPTION("cpufreq driver for AMD's Elan CPUs");
 
 module_init(elanfreq_init);
diff --git a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
index 9d9eae8..ac27ec2 100644
--- a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
+++ b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
@@ -79,8 +79,9 @@
 #include <linux/smp.h>
 #include <linux/cpufreq.h>
 #include <linux/pci.h>
+#include <linux/errno.h>
+
 #include <asm/processor-cyrix.h>
-#include <asm/errno.h>
 
 /* PCI config registers, all at F0 */
 #define PCI_PMER1	0x80	/* power management enable register 1 */
@@ -122,8 +123,8 @@
 static int stock_freq;
 
 /* PCI bus clock - defaults to 30.000 if cpu_khz is not available */
-static int pci_busclk = 0;
-module_param (pci_busclk, int, 0444);
+static int pci_busclk;
+module_param(pci_busclk, int, 0444);
 
 /* maximum duration for which the cpu may be suspended
  * (32us * MAX_DURATION). If no parameter is given, this defaults
@@ -132,7 +133,7 @@
  * is suspended -- processing power is just 0.39% of what it used to be,
  * though. 781.25 kHz(!) for a 200 MHz processor -- wow. */
 static int max_duration = 255;
-module_param (max_duration, int, 0444);
+module_param(max_duration, int, 0444);
 
 /* For the default policy, we want at least some processing power
  * - let's say 5%. (min = maxfreq / POLICY_MIN_DIV)
@@ -140,7 +141,8 @@
 #define POLICY_MIN_DIV 20
 
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "gx-suspmod", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"gx-suspmod", msg)
 
 /**
  * we can detect a core multipiler from dir0_lsb
@@ -166,12 +168,20 @@
  *	Low Level chipset interface				*
  ****************************************************************/
 static struct pci_device_id gx_chipset_tbl[] __initdata = {
-	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, PCI_ANY_ID, PCI_ANY_ID },
-	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID },
-	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510,
+		PCI_ANY_ID, PCI_ANY_ID },
 	{ 0, },
 };
 
+static void gx_write_byte(int reg, int value)
+{
+	pci_write_config_byte(gx_params->cs55x0, reg, value);
+}
+
 /**
  * gx_detect_chipset:
  *
@@ -200,7 +210,8 @@
 /**
  * gx_get_cpuspeed:
  *
- * Finds out at which efficient frequency the Cyrix MediaGX/NatSemi Geode CPU runs.
+ * Finds out at which efficient frequency the Cyrix MediaGX/NatSemi
+ * Geode CPU runs.
  */
 static unsigned int gx_get_cpuspeed(unsigned int cpu)
 {
@@ -217,17 +228,18 @@
  *
  **/
 
-static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off_duration)
+static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration,
+		u8 *off_duration)
 {
 	unsigned int i;
 	u8 tmp_on, tmp_off;
 	int old_tmp_freq = stock_freq;
 	int tmp_freq;
 
-	*off_duration=1;
-	*on_duration=0;
+	*off_duration = 1;
+	*on_duration = 0;
 
-	for (i=max_duration; i>0; i--) {
+	for (i = max_duration; i > 0; i--) {
 		tmp_off = ((khz * i) / stock_freq) & 0xff;
 		tmp_on = i - tmp_off;
 		tmp_freq = (stock_freq * tmp_off) / i;
@@ -259,26 +271,34 @@
 	freqs.cpu = 0;
 	freqs.old = gx_get_cpuspeed(0);
 
-	new_khz = gx_validate_speed(khz, &gx_params->on_duration, &gx_params->off_duration);
+	new_khz = gx_validate_speed(khz, &gx_params->on_duration,
+			&gx_params->off_duration);
 
 	freqs.new = new_khz;
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	local_irq_save(flags);
 
-	if (new_khz != stock_freq) {  /* if new khz == 100% of CPU speed, it is special case */
+
+
+	if (new_khz != stock_freq) {
+		/* if new khz == 100% of CPU speed, it is special case */
 		switch (gx_params->cs55x0->device) {
 		case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
 			pmer1 = gx_params->pci_pmer1 | IRQ_SPDUP | VID_SPDUP;
 			/* FIXME: need to test other values -- Zwane,Miura */
-			pci_write_config_byte(gx_params->cs55x0, PCI_IRQTC, 4); /* typical 2 to 4ms */
-			pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */
-			pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1);
+			/* typical 2 to 4ms */
+			gx_write_byte(PCI_IRQTC, 4);
+			/* typical 50 to 100ms */
+			gx_write_byte(PCI_VIDTC, 100);
+			gx_write_byte(PCI_PMER1, pmer1);
 
-			if (gx_params->cs55x0->revision < 0x10) {   /* CS5530(rev 1.2, 1.3) */
-				suscfg = gx_params->pci_suscfg | SUSMOD;
-			} else {                           /* CS5530A,B.. */
-				suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE;
+			if (gx_params->cs55x0->revision < 0x10) {
+				/* CS5530(rev 1.2, 1.3) */
+				suscfg = gx_params->pci_suscfg|SUSMOD;
+			} else {
+				/* CS5530A,B.. */
+				suscfg = gx_params->pci_suscfg|SUSMOD|PWRSVE;
 			}
 			break;
 		case PCI_DEVICE_ID_CYRIX_5520:
@@ -294,13 +314,13 @@
 		suscfg = gx_params->pci_suscfg & ~(SUSMOD);
 		gx_params->off_duration = 0;
 		gx_params->on_duration = 0;
-		dprintk("suspend modulation disabled: cpu runs 100 percent speed.\n");
+		dprintk("suspend modulation disabled: cpu runs 100%% speed.\n");
 	}
 
-	pci_write_config_byte(gx_params->cs55x0, PCI_MODOFF, gx_params->off_duration);
-	pci_write_config_byte(gx_params->cs55x0, PCI_MODON, gx_params->on_duration);
+	gx_write_byte(PCI_MODOFF, gx_params->off_duration);
+	gx_write_byte(PCI_MODON, gx_params->on_duration);
 
-	pci_write_config_byte(gx_params->cs55x0, PCI_SUSCFG, suscfg);
+	gx_write_byte(PCI_SUSCFG, suscfg);
 	pci_read_config_byte(gx_params->cs55x0, PCI_SUSCFG, &suscfg);
 
 	local_irq_restore(flags);
@@ -334,7 +354,8 @@
 		return -EINVAL;
 
 	policy->cpu = 0;
-	cpufreq_verify_within_limits(policy, (stock_freq / max_duration), stock_freq);
+	cpufreq_verify_within_limits(policy, (stock_freq / max_duration),
+			stock_freq);
 
 	/* it needs to be assured that at least one supported frequency is
 	 * within policy->min and policy->max. If it is not, policy->max
@@ -354,7 +375,8 @@
 	policy->max = tmp_freq;
 	if (policy->max < policy->min)
 		policy->max = policy->min;
-	cpufreq_verify_within_limits(policy, (stock_freq / max_duration), stock_freq);
+	cpufreq_verify_within_limits(policy, (stock_freq / max_duration),
+			stock_freq);
 
 	return 0;
 }
@@ -398,18 +420,18 @@
 		return -ENODEV;
 
 	/* determine maximum frequency */
-	if (pci_busclk) {
+	if (pci_busclk)
 		maxfreq = pci_busclk * gx_freq_mult[getCx86(CX86_DIR1) & 0x0f];
-	} else if (cpu_khz) {
+	else if (cpu_khz)
 		maxfreq = cpu_khz;
-	} else {
+	else
 		maxfreq = 30000 * gx_freq_mult[getCx86(CX86_DIR1) & 0x0f];
-	}
+
 	stock_freq = maxfreq;
 	curfreq = gx_get_cpuspeed(0);
 
 	dprintk("cpu max frequency is %d.\n", maxfreq);
-	dprintk("cpu current frequency is %dkHz.\n",curfreq);
+	dprintk("cpu current frequency is %dkHz.\n", curfreq);
 
 	/* setup basic struct for cpufreq API */
 	policy->cpu = 0;
@@ -447,7 +469,8 @@
 	struct pci_dev *gx_pci;
 
 	/* Test if we have the right hardware */
-	if ((gx_pci = gx_detect_chipset()) == NULL)
+	gx_pci = gx_detect_chipset();
+	if (gx_pci == NULL)
 		return -ENODEV;
 
 	/* check whether module parameters are sane */
@@ -468,9 +491,11 @@
 	pci_read_config_byte(params->cs55x0, PCI_PMER1, &(params->pci_pmer1));
 	pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2));
 	pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration));
-	pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration));
+	pci_read_config_byte(params->cs55x0, PCI_MODOFF,
+			&(params->off_duration));
 
-	if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) {
+	ret = cpufreq_register_driver(&gx_suspmod_driver);
+	if (ret) {
 		kfree(params);
 		return ret;                   /* register error! */
 	}
@@ -485,9 +510,9 @@
 	kfree(gx_params);
 }
 
-MODULE_AUTHOR ("Hiroshi Miura <miura@da-cha.org>");
-MODULE_DESCRIPTION ("Cpufreq driver for Cyrix MediaGX and NatSemi Geode");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Hiroshi Miura <miura@da-cha.org>");
+MODULE_DESCRIPTION("Cpufreq driver for Cyrix MediaGX and NatSemi Geode");
+MODULE_LICENSE("GPL");
 
 module_init(cpufreq_gx_init);
 module_exit(cpufreq_gx_exit);
diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.c b/arch/x86/kernel/cpu/cpufreq/longhaul.c
index a4cff5d..f1c51ae 100644
--- a/arch/x86/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/x86/kernel/cpu/cpufreq/longhaul.c
@@ -30,12 +30,12 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
+#include <linux/timex.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
+#include <linux/kernel.h>
 
 #include <asm/msr.h>
-#include <asm/timex.h>
-#include <asm/io.h>
-#include <asm/acpi.h>
-#include <linux/acpi.h>
 #include <acpi/processor.h>
 
 #include "longhaul.h"
@@ -58,7 +58,7 @@
 #define USE_NORTHBRIDGE		(1 << 2)
 
 static int cpu_model;
-static unsigned int numscales=16;
+static unsigned int numscales = 16;
 static unsigned int fsb;
 
 static const struct mV_pos *vrm_mV_table;
@@ -67,8 +67,8 @@
 static unsigned int highest_speed, lowest_speed; /* kHz */
 static unsigned int minmult, maxmult;
 static int can_scale_voltage;
-static struct acpi_processor *pr = NULL;
-static struct acpi_processor_cx *cx = NULL;
+static struct acpi_processor *pr;
+static struct acpi_processor_cx *cx;
 static u32 acpi_regs_addr;
 static u8 longhaul_flags;
 static unsigned int longhaul_index;
@@ -78,12 +78,13 @@
 static int disable_acpi_c3;
 static int revid_errata;
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"longhaul", msg)
 
 
 /* Clock ratios multiplied by 10 */
-static int clock_ratio[32];
-static int eblcr_table[32];
+static int mults[32];
+static int eblcr[32];
 static int longhaul_version;
 static struct cpufreq_frequency_table *longhaul_table;
 
@@ -93,7 +94,7 @@
 static char *print_speed(int speed)
 {
 	if (speed < 1000) {
-		snprintf(speedbuffer, sizeof(speedbuffer),"%dMHz", speed);
+		snprintf(speedbuffer, sizeof(speedbuffer), "%dMHz", speed);
 		return speedbuffer;
 	}
 
@@ -122,27 +123,28 @@
 
 static int longhaul_get_cpu_mult(void)
 {
-	unsigned long invalue=0,lo, hi;
+	unsigned long invalue = 0, lo, hi;
 
-	rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
-	invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22;
-	if (longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) {
+	rdmsr(MSR_IA32_EBL_CR_POWERON, lo, hi);
+	invalue = (lo & (1<<22|1<<23|1<<24|1<<25))>>22;
+	if (longhaul_version == TYPE_LONGHAUL_V2 ||
+	    longhaul_version == TYPE_POWERSAVER) {
 		if (lo & (1<<27))
-			invalue+=16;
+			invalue += 16;
 	}
-	return eblcr_table[invalue];
+	return eblcr[invalue];
 }
 
 /* For processor with BCR2 MSR */
 
-static void do_longhaul1(unsigned int clock_ratio_index)
+static void do_longhaul1(unsigned int mults_index)
 {
 	union msr_bcr2 bcr2;
 
 	rdmsrl(MSR_VIA_BCR2, bcr2.val);
 	/* Enable software clock multiplier */
 	bcr2.bits.ESOFTBF = 1;
-	bcr2.bits.CLOCKMUL = clock_ratio_index & 0xff;
+	bcr2.bits.CLOCKMUL = mults_index & 0xff;
 
 	/* Sync to timer tick */
 	safe_halt();
@@ -161,7 +163,7 @@
 
 /* For processor with Longhaul MSR */
 
-static void do_powersaver(int cx_address, unsigned int clock_ratio_index,
+static void do_powersaver(int cx_address, unsigned int mults_index,
 			  unsigned int dir)
 {
 	union msr_longhaul longhaul;
@@ -173,11 +175,11 @@
 		longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
 	else
 		longhaul.bits.RevisionKey = 0;
-	longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
-	longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
+	longhaul.bits.SoftBusRatio = mults_index & 0xf;
+	longhaul.bits.SoftBusRatio4 = (mults_index & 0x10) >> 4;
 	/* Setup new voltage */
 	if (can_scale_voltage)
-		longhaul.bits.SoftVID = (clock_ratio_index >> 8) & 0x1f;
+		longhaul.bits.SoftVID = (mults_index >> 8) & 0x1f;
 	/* Sync to timer tick */
 	safe_halt();
 	/* Raise voltage if necessary */
@@ -240,14 +242,14 @@
 
 /**
  * longhaul_set_cpu_frequency()
- * @clock_ratio_index : bitpattern of the new multiplier.
+ * @mults_index : bitpattern of the new multiplier.
  *
  * Sets a new clock ratio.
  */
 
 static void longhaul_setstate(unsigned int table_index)
 {
-	unsigned int clock_ratio_index;
+	unsigned int mults_index;
 	int speed, mult;
 	struct cpufreq_freqs freqs;
 	unsigned long flags;
@@ -256,9 +258,9 @@
 	u32 bm_timeout = 1000;
 	unsigned int dir = 0;
 
-	clock_ratio_index = longhaul_table[table_index].index;
+	mults_index = longhaul_table[table_index].index;
 	/* Safety precautions */
-	mult = clock_ratio[clock_ratio_index & 0x1f];
+	mult = mults[mults_index & 0x1f];
 	if (mult == -1)
 		return;
 	speed = calc_speed(mult);
@@ -274,7 +276,7 @@
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
+	dprintk("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
 			fsb, mult/10, mult%10, print_speed(speed/1000));
 retry_loop:
 	preempt_disable();
@@ -282,8 +284,8 @@
 
 	pic2_mask = inb(0xA1);
 	pic1_mask = inb(0x21);	/* works on C3. save mask. */
-	outb(0xFF,0xA1);	/* Overkill */
-	outb(0xFE,0x21);	/* TMR0 only */
+	outb(0xFF, 0xA1);	/* Overkill */
+	outb(0xFE, 0x21);	/* TMR0 only */
 
 	/* Wait while PCI bus is busy. */
 	if (acpi_regs_addr && (longhaul_flags & USE_NORTHBRIDGE
@@ -312,7 +314,7 @@
 	 * Software controlled multipliers only.
 	 */
 	case TYPE_LONGHAUL_V1:
-		do_longhaul1(clock_ratio_index);
+		do_longhaul1(mults_index);
 		break;
 
 	/*
@@ -327,9 +329,9 @@
 		if (longhaul_flags & USE_ACPI_C3) {
 			/* Don't allow wakeup */
 			acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
-			do_powersaver(cx->address, clock_ratio_index, dir);
+			do_powersaver(cx->address, mults_index, dir);
 		} else {
-			do_powersaver(0, clock_ratio_index, dir);
+			do_powersaver(0, mults_index, dir);
 		}
 		break;
 	}
@@ -341,8 +343,8 @@
 		/* Enable bus master arbitration */
 		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
 	}
-	outb(pic2_mask,0xA1);	/* restore mask */
-	outb(pic1_mask,0x21);
+	outb(pic2_mask, 0xA1);	/* restore mask */
+	outb(pic1_mask, 0x21);
 
 	local_irq_restore(flags);
 	preempt_enable();
@@ -392,7 +394,8 @@
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	if (!bm_timeout)
-		printk(KERN_INFO PFX "Warning: Timeout while waiting for idle PCI bus.\n");
+		printk(KERN_INFO PFX "Warning: Timeout while waiting for "
+				"idle PCI bus.\n");
 }
 
 /*
@@ -458,31 +461,32 @@
 		break;
 	}
 
-	dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
+	dprintk("MinMult:%d.%dx MaxMult:%d.%dx\n",
 		 minmult/10, minmult%10, maxmult/10, maxmult%10);
 
 	highest_speed = calc_speed(maxmult);
 	lowest_speed = calc_speed(minmult);
-	dprintk ("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
+	dprintk("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
 		 print_speed(lowest_speed/1000),
 		 print_speed(highest_speed/1000));
 
 	if (lowest_speed == highest_speed) {
-		printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n");
+		printk(KERN_INFO PFX "highestspeed == lowest, aborting.\n");
 		return -EINVAL;
 	}
 	if (lowest_speed > highest_speed) {
-		printk (KERN_INFO PFX "nonsense! lowest (%d > %d) !\n",
+		printk(KERN_INFO PFX "nonsense! lowest (%d > %d) !\n",
 			lowest_speed, highest_speed);
 		return -EINVAL;
 	}
 
-	longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL);
-	if(!longhaul_table)
+	longhaul_table = kmalloc((numscales + 1) * sizeof(*longhaul_table),
+			GFP_KERNEL);
+	if (!longhaul_table)
 		return -ENOMEM;
 
 	for (j = 0; j < numscales; j++) {
-		ratio = clock_ratio[j];
+		ratio = mults[j];
 		if (ratio == -1)
 			continue;
 		if (ratio > maxmult || ratio < minmult)
@@ -507,13 +511,10 @@
 			}
 		}
 		if (min_i != j) {
-			unsigned int temp;
-			temp = longhaul_table[j].frequency;
-			longhaul_table[j].frequency = longhaul_table[min_i].frequency;
-			longhaul_table[min_i].frequency = temp;
-			temp = longhaul_table[j].index;
-			longhaul_table[j].index = longhaul_table[min_i].index;
-			longhaul_table[min_i].index = temp;
+			swap(longhaul_table[j].frequency,
+			     longhaul_table[min_i].frequency);
+			swap(longhaul_table[j].index,
+			     longhaul_table[min_i].index);
 		}
 	}
 
@@ -521,7 +522,7 @@
 
 	/* Find index we are running on */
 	for (j = 0; j < k; j++) {
-		if (clock_ratio[longhaul_table[j].index & 0x1f] == mult) {
+		if (mults[longhaul_table[j].index & 0x1f] == mult) {
 			longhaul_index = j;
 			break;
 		}
@@ -559,20 +560,22 @@
 	maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
 
 	if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
-		printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
+		printk(KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
 					"Voltage scaling disabled.\n",
-					minvid.mV/1000, minvid.mV%1000, maxvid.mV/1000, maxvid.mV%1000);
+					minvid.mV/1000, minvid.mV%1000,
+					maxvid.mV/1000, maxvid.mV%1000);
 		return;
 	}
 
 	if (minvid.mV == maxvid.mV) {
-		printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are "
-				"both %d.%03d. Voltage scaling disabled\n",
+		printk(KERN_INFO PFX "Claims to support voltage scaling but "
+				"min & max are both %d.%03d. "
+				"Voltage scaling disabled\n",
 				maxvid.mV/1000, maxvid.mV%1000);
 		return;
 	}
 
-	/* How many voltage steps */
+	/* How many voltage steps*/
 	numvscales = maxvid.pos - minvid.pos + 1;
 	printk(KERN_INFO PFX
 		"Max VID=%d.%03d  "
@@ -586,7 +589,7 @@
 	j = longhaul.bits.MinMHzBR;
 	if (longhaul.bits.MinMHzBR4)
 		j += 16;
-	min_vid_speed = eblcr_table[j];
+	min_vid_speed = eblcr[j];
 	if (min_vid_speed == -1)
 		return;
 	switch (longhaul.bits.MinMHzFSB) {
@@ -617,7 +620,8 @@
 			pos = minvid.pos;
 		longhaul_table[j].index |= mV_vrm_table[pos] << 8;
 		vid = vrm_mV_table[mV_vrm_table[pos]];
-		printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", speed, j, vid.mV);
+		printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n",
+				speed, j, vid.mV);
 		j++;
 	}
 
@@ -640,7 +644,8 @@
 	unsigned int dir = 0;
 	u8 vid, current_vid;
 
-	if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
+	if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq,
+				relation, &table_index))
 		return -EINVAL;
 
 	/* Don't set same frequency again */
@@ -656,7 +661,8 @@
 		 * this in hardware, C3 is old and we need to do this
 		 * in software. */
 		i = longhaul_index;
-		current_vid = (longhaul_table[longhaul_index].index >> 8) & 0x1f;
+		current_vid = (longhaul_table[longhaul_index].index >> 8);
+		current_vid &= 0x1f;
 		if (table_index > longhaul_index)
 			dir = 1;
 		while (i != table_index) {
@@ -691,9 +697,9 @@
 {
 	struct acpi_device *d;
 
-	if ( acpi_bus_get_device(obj_handle, &d) ) {
+	if (acpi_bus_get_device(obj_handle, &d))
 		return 0;
-	}
+
 	*return_value = acpi_driver_data(d);
 	return 1;
 }
@@ -750,7 +756,7 @@
 	/* Find VT8235 southbridge */
 	dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
 	if (dev == NULL)
-	/* Find VT8237 southbridge */
+		/* Find VT8237 southbridge */
 		dev = pci_get_device(PCI_VENDOR_ID_VIA,
 				     PCI_DEVICE_ID_VIA_8237, NULL);
 	if (dev != NULL) {
@@ -769,7 +775,8 @@
 		if (pci_cmd & 1 << 7) {
 			pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
 			acpi_regs_addr &= 0xff00;
-			printk(KERN_INFO PFX "ACPI I/O at 0x%x\n", acpi_regs_addr);
+			printk(KERN_INFO PFX "ACPI I/O at 0x%x\n",
+					acpi_regs_addr);
 		}
 
 		pci_dev_put(dev);
@@ -781,7 +788,7 @@
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
 	struct cpuinfo_x86 *c = &cpu_data(0);
-	char *cpuname=NULL;
+	char *cpuname = NULL;
 	int ret;
 	u32 lo, hi;
 
@@ -791,8 +798,8 @@
 		cpu_model = CPU_SAMUEL;
 		cpuname = "C3 'Samuel' [C5A]";
 		longhaul_version = TYPE_LONGHAUL_V1;
-		memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
-		memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr));
+		memcpy(mults, samuel1_mults, sizeof(samuel1_mults));
+		memcpy(eblcr, samuel1_eblcr, sizeof(samuel1_eblcr));
 		break;
 
 	case 7:
@@ -803,10 +810,8 @@
 			cpuname = "C3 'Samuel 2' [C5B]";
 			/* Note, this is not a typo, early Samuel2's had
 			 * Samuel1 ratios. */
-			memcpy(clock_ratio, samuel1_clock_ratio,
-				sizeof(samuel1_clock_ratio));
-			memcpy(eblcr_table, samuel2_eblcr,
-				sizeof(samuel2_eblcr));
+			memcpy(mults, samuel1_mults, sizeof(samuel1_mults));
+			memcpy(eblcr, samuel2_eblcr, sizeof(samuel2_eblcr));
 			break;
 		case 1 ... 15:
 			longhaul_version = TYPE_LONGHAUL_V1;
@@ -817,10 +822,8 @@
 				cpu_model = CPU_EZRA;
 				cpuname = "C3 'Ezra' [C5C]";
 			}
-			memcpy(clock_ratio, ezra_clock_ratio,
-				sizeof(ezra_clock_ratio));
-			memcpy(eblcr_table, ezra_eblcr,
-				sizeof(ezra_eblcr));
+			memcpy(mults, ezra_mults, sizeof(ezra_mults));
+			memcpy(eblcr, ezra_eblcr, sizeof(ezra_eblcr));
 			break;
 		}
 		break;
@@ -829,18 +832,16 @@
 		cpu_model = CPU_EZRA_T;
 		cpuname = "C3 'Ezra-T' [C5M]";
 		longhaul_version = TYPE_POWERSAVER;
-		numscales=32;
-		memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio));
-		memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr));
+		numscales = 32;
+		memcpy(mults, ezrat_mults, sizeof(ezrat_mults));
+		memcpy(eblcr, ezrat_eblcr, sizeof(ezrat_eblcr));
 		break;
 
 	case 9:
 		longhaul_version = TYPE_POWERSAVER;
 		numscales = 32;
-		memcpy(clock_ratio,
-		       nehemiah_clock_ratio,
-		       sizeof(nehemiah_clock_ratio));
-		memcpy(eblcr_table, nehemiah_eblcr, sizeof(nehemiah_eblcr));
+		memcpy(mults, nehemiah_mults, sizeof(nehemiah_mults));
+		memcpy(eblcr, nehemiah_eblcr, sizeof(nehemiah_eblcr));
 		switch (c->x86_mask) {
 		case 0 ... 1:
 			cpu_model = CPU_NEHEMIAH;
@@ -869,14 +870,14 @@
 			longhaul_version = TYPE_LONGHAUL_V1;
 	}
 
-	printk (KERN_INFO PFX "VIA %s CPU detected.  ", cpuname);
+	printk(KERN_INFO PFX "VIA %s CPU detected.  ", cpuname);
 	switch (longhaul_version) {
 	case TYPE_LONGHAUL_V1:
 	case TYPE_LONGHAUL_V2:
-		printk ("Longhaul v%d supported.\n", longhaul_version);
+		printk(KERN_CONT "Longhaul v%d supported.\n", longhaul_version);
 		break;
 	case TYPE_POWERSAVER:
-		printk ("Powersaver supported.\n");
+		printk(KERN_CONT "Powersaver supported.\n");
 		break;
 	};
 
@@ -940,7 +941,7 @@
 	return 0;
 }
 
-static struct freq_attr* longhaul_attr[] = {
+static struct freq_attr *longhaul_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
 };
@@ -966,13 +967,15 @@
 
 #ifdef CONFIG_SMP
 	if (num_online_cpus() > 1) {
-		printk(KERN_ERR PFX "More than 1 CPU detected, longhaul disabled.\n");
+		printk(KERN_ERR PFX "More than 1 CPU detected, "
+				"longhaul disabled.\n");
 		return -ENODEV;
 	}
 #endif
 #ifdef CONFIG_X86_IO_APIC
 	if (cpu_has_apic) {
-		printk(KERN_ERR PFX "APIC detected. Longhaul is currently broken in this configuration.\n");
+		printk(KERN_ERR PFX "APIC detected. Longhaul is currently "
+				"broken in this configuration.\n");
 		return -ENODEV;
 	}
 #endif
@@ -993,8 +996,8 @@
 {
 	int i;
 
-	for (i=0; i < numscales; i++) {
-		if (clock_ratio[i] == maxmult) {
+	for (i = 0; i < numscales; i++) {
+		if (mults[i] == maxmult) {
 			longhaul_setstate(i);
 			break;
 		}
@@ -1007,11 +1010,11 @@
 /* Even if BIOS is exporting ACPI C3 state, and it is used
  * with success when CPU is idle, this state doesn't
  * trigger frequency transition in some cases. */
-module_param (disable_acpi_c3, int, 0644);
+module_param(disable_acpi_c3, int, 0644);
 MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
 /* Change CPU voltage with frequency. Very usefull to save
  * power, but most VIA C3 processors aren't supporting it. */
-module_param (scale_voltage, int, 0644);
+module_param(scale_voltage, int, 0644);
 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
 /* Force revision key to 0 for processors which doesn't
  * support voltage scaling, but are introducing itself as
@@ -1019,9 +1022,9 @@
 module_param(revid_errata, int, 0644);
 MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID");
 
-MODULE_AUTHOR ("Dave Jones <davej@redhat.com>");
-MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
+MODULE_DESCRIPTION("Longhaul driver for VIA Cyrix processors.");
+MODULE_LICENSE("GPL");
 
 late_initcall(longhaul_init);
 module_exit(longhaul_exit);
diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.h b/arch/x86/kernel/cpu/cpufreq/longhaul.h
index 4fcc320..e2360a4 100644
--- a/arch/x86/kernel/cpu/cpufreq/longhaul.h
+++ b/arch/x86/kernel/cpu/cpufreq/longhaul.h
@@ -49,14 +49,14 @@
 
 /*
  * Clock ratio tables. Div/Mod by 10 to get ratio.
- * The eblcr ones specify the ratio read from the CPU.
- * The clock_ratio ones specify what to write to the CPU.
+ * The eblcr values specify the ratio read from the CPU.
+ * The mults values specify what to write to the CPU.
  */
 
 /*
  * VIA C3 Samuel 1  & Samuel 2 (stepping 0)
  */
-static const int __initdata samuel1_clock_ratio[16] = {
+static const int __initdata samuel1_mults[16] = {
 	-1, /* 0000 -> RESERVED */
 	30, /* 0001 ->  3.0x */
 	40, /* 0010 ->  4.0x */
@@ -119,7 +119,7 @@
 /*
  * VIA C3 Ezra
  */
-static const int __initdata ezra_clock_ratio[16] = {
+static const int __initdata ezra_mults[16] = {
 	100, /* 0000 -> 10.0x */
 	30,  /* 0001 ->  3.0x */
 	40,  /* 0010 ->  4.0x */
@@ -160,7 +160,7 @@
 /*
  * VIA C3 (Ezra-T) [C5M].
  */
-static const int __initdata ezrat_clock_ratio[32] = {
+static const int __initdata ezrat_mults[32] = {
 	100, /* 0000 -> 10.0x */
 	30,  /* 0001 ->  3.0x */
 	40,  /* 0010 ->  4.0x */
@@ -235,7 +235,7 @@
 /*
  * VIA C3 Nehemiah */
 
-static const int __initdata  nehemiah_clock_ratio[32] = {
+static const int __initdata  nehemiah_mults[32] = {
 	100, /* 0000 -> 10.0x */
 	-1, /* 0001 -> 16.0x */
 	40,  /* 0010 ->  4.0x */
diff --git a/arch/x86/kernel/cpu/cpufreq/longrun.c b/arch/x86/kernel/cpu/cpufreq/longrun.c
index 777a7ff..da5f70f 100644
--- a/arch/x86/kernel/cpu/cpufreq/longrun.c
+++ b/arch/x86/kernel/cpu/cpufreq/longrun.c
@@ -11,12 +11,13 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/cpufreq.h>
+#include <linux/timex.h>
 
 #include <asm/msr.h>
 #include <asm/processor.h>
-#include <asm/timex.h>
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longrun", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"longrun", msg)
 
 static struct cpufreq_driver	longrun_driver;
 
@@ -51,7 +52,7 @@
 	msr_lo &= 0x0000007F;
 	msr_hi &= 0x0000007F;
 
-	if ( longrun_high_freq <= longrun_low_freq ) {
+	if (longrun_high_freq <= longrun_low_freq) {
 		/* Assume degenerate Longrun table */
 		policy->min = policy->max = longrun_high_freq;
 	} else {
@@ -79,7 +80,7 @@
 	if (!policy)
 		return -EINVAL;
 
-	if ( longrun_high_freq <= longrun_low_freq ) {
+	if (longrun_high_freq <= longrun_low_freq) {
 		/* Assume degenerate Longrun table */
 		pctg_lo = pctg_hi = 100;
 	} else {
@@ -152,7 +153,7 @@
 	cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
 	dprintk("cpuid eax is %u\n", eax);
 
-	return (eax * 1000);
+	return eax * 1000;
 }
 
 /**
@@ -196,7 +197,8 @@
 		rdmsr(MSR_TMTA_LRTI_VOLT_MHZ, msr_lo, msr_hi);
 		*high_freq = msr_lo * 1000; /* to kHz */
 
-		dprintk("longrun table interface told %u - %u kHz\n", *low_freq, *high_freq);
+		dprintk("longrun table interface told %u - %u kHz\n",
+				*low_freq, *high_freq);
 
 		if (*low_freq > *high_freq)
 			*low_freq = *high_freq;
@@ -219,7 +221,7 @@
 	cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
 	/* try decreasing in 10% steps, some processors react only
 	 * on some barrier values */
-	for (try_hi = 80; try_hi > 0 && ecx > 90; try_hi -=10) {
+	for (try_hi = 80; try_hi > 0 && ecx > 90; try_hi -= 10) {
 		/* set to 0 to try_hi perf_pctg */
 		msr_lo &= 0xFFFFFF80;
 		msr_hi &= 0xFFFFFF80;
@@ -236,7 +238,7 @@
 
 	/* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
 	 * eqals
-	 * low_freq * ( 1 - perf_pctg) = (cur_freq - high_freq * perf_pctg)
+	 * low_freq * (1 - perf_pctg) = (cur_freq - high_freq * perf_pctg)
 	 *
 	 * high_freq * perf_pctg is stored tempoarily into "ebx".
 	 */
@@ -317,9 +319,10 @@
 }
 
 
-MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
-MODULE_DESCRIPTION ("LongRun driver for Transmeta Crusoe and Efficeon processors.");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION("LongRun driver for Transmeta Crusoe and "
+		"Efficeon processors.");
+MODULE_LICENSE("GPL");
 
 module_init(longrun_init);
 module_exit(longrun_exit);
diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
index b585e04c..41ed949 100644
--- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
@@ -27,15 +27,17 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/cpumask.h>
+#include <linux/timex.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
-#include <asm/timex.h>
+#include <asm/timer.h>
 
 #include "speedstep-lib.h"
 
 #define PFX	"p4-clockmod: "
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "p4-clockmod", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"p4-clockmod", msg)
 
 /*
  * Duty Cycle (3bits), note DC_DISABLE is not specified in
@@ -58,7 +60,8 @@
 {
 	u32 l, h;
 
-	if (!cpu_online(cpu) || (newstate > DC_DISABLE) || (newstate == DC_RESV))
+	if (!cpu_online(cpu) ||
+	    (newstate > DC_DISABLE) || (newstate == DC_RESV))
 		return -EINVAL;
 
 	rdmsr_on_cpu(cpu, MSR_IA32_THERM_STATUS, &l, &h);
@@ -66,7 +69,8 @@
 	if (l & 0x01)
 		dprintk("CPU#%d currently thermal throttled\n", cpu);
 
-	if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT))
+	if (has_N44_O17_errata[cpu] &&
+	    (newstate == DC_25PT || newstate == DC_DFLT))
 		newstate = DC_38PT;
 
 	rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, &l, &h);
@@ -112,7 +116,8 @@
 	struct cpufreq_freqs freqs;
 	int i;
 
-	if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate))
+	if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0],
+				target_freq, relation, &newstate))
 		return -EINVAL;
 
 	freqs.old = cpufreq_p4_get(policy->cpu);
@@ -127,7 +132,8 @@
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	}
 
-	/* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
+	/* run on each logical CPU,
+	 * see section 13.15.3 of IA32 Intel Architecture Software
 	 * Developer's Manual, Volume 3
 	 */
 	for_each_cpu(i, policy->cpus)
@@ -153,28 +159,30 @@
 {
 	if (c->x86 == 0x06) {
 		if (cpu_has(c, X86_FEATURE_EST))
-			printk(KERN_WARNING PFX "Warning: EST-capable CPU detected. "
-			       "The acpi-cpufreq module offers voltage scaling"
-			       " in addition of frequency scaling. You should use "
-			       "that instead of p4-clockmod, if possible.\n");
+			printk(KERN_WARNING PFX "Warning: EST-capable CPU "
+			       "detected. The acpi-cpufreq module offers "
+			       "voltage scaling in addition of frequency "
+			       "scaling. You should use that instead of "
+			       "p4-clockmod, if possible.\n");
 		switch (c->x86_model) {
 		case 0x0E: /* Core */
 		case 0x0F: /* Core Duo */
 		case 0x16: /* Celeron Core */
 			p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
-			return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE);
+			return speedstep_get_frequency(SPEEDSTEP_CPU_PCORE);
 		case 0x0D: /* Pentium M (Dothan) */
 			p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 			/* fall through */
 		case 0x09: /* Pentium M (Banias) */
-			return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
+			return speedstep_get_frequency(SPEEDSTEP_CPU_PM);
 		}
 	}
 
 	if (c->x86 != 0xF) {
 		if (!cpu_has(c, X86_FEATURE_EST))
-			printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. "
-				"Please send an e-mail to <cpufreq@vger.kernel.org>\n");
+			printk(KERN_WARNING PFX "Unknown CPU. "
+				"Please send an e-mail to "
+				"<cpufreq@vger.kernel.org>\n");
 		return 0;
 	}
 
@@ -182,16 +190,16 @@
 	 * throttling is active or not. */
 	p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 
-	if (speedstep_detect_processor() == SPEEDSTEP_PROCESSOR_P4M) {
+	if (speedstep_detect_processor() == SPEEDSTEP_CPU_P4M) {
 		printk(KERN_WARNING PFX "Warning: Pentium 4-M detected. "
 		       "The speedstep-ich or acpi cpufreq modules offer "
 		       "voltage scaling in addition of frequency scaling. "
 		       "You should use either one instead of p4-clockmod, "
 		       "if possible.\n");
-		return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_P4M);
+		return speedstep_get_frequency(SPEEDSTEP_CPU_P4M);
 	}
 
-	return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_P4D);
+	return speedstep_get_frequency(SPEEDSTEP_CPU_P4D);
 }
 
 
@@ -217,14 +225,20 @@
 		dprintk("has errata -- disabling low frequencies\n");
 	}
 
+	if (speedstep_detect_processor() == SPEEDSTEP_CPU_P4D &&
+	    c->x86_model < 2) {
+		/* switch to maximum frequency and measure result */
+		cpufreq_p4_setdc(policy->cpu, DC_DISABLE);
+		recalibrate_cpu_khz();
+	}
 	/* get max frequency */
 	stock_freq = cpufreq_p4_get_frequency(c);
 	if (!stock_freq)
 		return -EINVAL;
 
 	/* table init */
-	for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
-		if ((i<2) && (has_N44_O17_errata[policy->cpu]))
+	for (i = 1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if ((i < 2) && (has_N44_O17_errata[policy->cpu]))
 			p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
 		else
 			p4clockmod_table[i].frequency = (stock_freq * i)/8;
@@ -232,7 +246,10 @@
 	cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
 
 	/* cpuinfo and default policy values */
-	policy->cpuinfo.transition_latency = 1000000; /* assumed */
+
+	/* the transition latency is set to be 1 higher than the maximum
+	 * transition latency of the ondemand governor */
+	policy->cpuinfo.transition_latency = 10000001;
 	policy->cur = stock_freq;
 
 	return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]);
@@ -258,12 +275,12 @@
 		l = DC_DISABLE;
 
 	if (l != DC_DISABLE)
-		return (stock_freq * l / 8);
+		return stock_freq * l / 8;
 
 	return stock_freq;
 }
 
-static struct freq_attr* p4clockmod_attr[] = {
+static struct freq_attr *p4clockmod_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
 };
@@ -277,7 +294,6 @@
 	.name		= "p4-clockmod",
 	.owner		= THIS_MODULE,
 	.attr		= p4clockmod_attr,
-	.hide_interface	= 1,
 };
 
 
@@ -299,9 +315,10 @@
 
 	ret = cpufreq_register_driver(&p4clockmod_driver);
 	if (!ret)
-		printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n");
+		printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock "
+				"Modulation available\n");
 
-	return (ret);
+	return ret;
 }
 
 
@@ -311,9 +328,9 @@
 }
 
 
-MODULE_AUTHOR ("Zwane Mwaikambo <zwane@commfireservices.com>");
-MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Zwane Mwaikambo <zwane@commfireservices.com>");
+MODULE_DESCRIPTION("cpufreq driver for Pentium(TM) 4/Xeon(TM)");
+MODULE_LICENSE("GPL");
 
 late_initcall(cpufreq_p4_init);
 module_exit(cpufreq_p4_exit);
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c
index c1ac579..f10dea4 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c
@@ -1,6 +1,7 @@
 /*
  *  This file was based upon code in Powertweak Linux (http://powertweak.sf.net)
- *  (C) 2000-2003  Dave Jones, Arjan van de Ven, Janne Pänkälä, Dominik Brodowski.
+ *  (C) 2000-2003  Dave Jones, Arjan van de Ven, Janne Pänkälä,
+ *                 Dominik Brodowski.
  *
  *  Licensed under the terms of the GNU GPL License version 2.
  *
@@ -13,14 +14,15 @@
 #include <linux/cpufreq.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-
-#include <asm/msr.h>
 #include <linux/timex.h>
 #include <linux/io.h>
 
+#include <asm/msr.h>
+
 #define POWERNOW_IOPORT 0xfff0          /* it doesn't matter where, as long
 					   as it is unused */
 
+#define PFX "powernow-k6: "
 static unsigned int                     busfreq;   /* FSB, in 10 kHz */
 static unsigned int                     max_multiplier;
 
@@ -47,8 +49,8 @@
  */
 static int powernow_k6_get_cpu_multiplier(void)
 {
-	u64             invalue = 0;
-	u32             msrval;
+	u64 invalue = 0;
+	u32 msrval;
 
 	msrval = POWERNOW_IOPORT + 0x1;
 	wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
@@ -68,12 +70,12 @@
  */
 static void powernow_k6_set_state(unsigned int best_i)
 {
-	unsigned long           outvalue = 0, invalue = 0;
-	unsigned long           msrval;
-	struct cpufreq_freqs    freqs;
+	unsigned long outvalue = 0, invalue = 0;
+	unsigned long msrval;
+	struct cpufreq_freqs freqs;
 
 	if (clock_ratio[best_i].index > max_multiplier) {
-		printk(KERN_ERR "cpufreq: invalid target frequency\n");
+		printk(KERN_ERR PFX "invalid target frequency\n");
 		return;
 	}
 
@@ -119,7 +121,8 @@
  * powernow_k6_setpolicy - sets a new CPUFreq policy
  * @policy: new policy
  * @target_freq: the target frequency
- * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
+ * @relation: how that frequency relates to achieved frequency
+ *  (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
  *
  * sets a new CPUFreq policy
  */
@@ -127,9 +130,10 @@
 			       unsigned int target_freq,
 			       unsigned int relation)
 {
-	unsigned int    newstate = 0;
+	unsigned int newstate = 0;
 
-	if (cpufreq_frequency_table_target(policy, &clock_ratio[0], target_freq, relation, &newstate))
+	if (cpufreq_frequency_table_target(policy, &clock_ratio[0],
+				target_freq, relation, &newstate))
 		return -EINVAL;
 
 	powernow_k6_set_state(newstate);
@@ -140,7 +144,7 @@
 
 static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
 {
-	unsigned int i;
+	unsigned int i, f;
 	int result;
 
 	if (policy->cpu != 0)
@@ -152,10 +156,11 @@
 
 	/* table init */
 	for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
-		if (clock_ratio[i].index > max_multiplier)
+		f = clock_ratio[i].index;
+		if (f > max_multiplier)
 			clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID;
 		else
-			clock_ratio[i].frequency = busfreq * clock_ratio[i].index;
+			clock_ratio[i].frequency = busfreq * f;
 	}
 
 	/* cpuinfo and default policy values */
@@ -185,7 +190,9 @@
 
 static unsigned int powernow_k6_get(unsigned int cpu)
 {
-	return busfreq * powernow_k6_get_cpu_multiplier();
+	unsigned int ret;
+	ret = (busfreq * powernow_k6_get_cpu_multiplier());
+	return ret;
 }
 
 static struct freq_attr *powernow_k6_attr[] = {
@@ -221,7 +228,7 @@
 		return -ENODEV;
 
 	if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) {
-		printk("cpufreq: PowerNow IOPORT region already used.\n");
+		printk(KERN_INFO PFX "PowerNow IOPORT region already used.\n");
 		return -EIO;
 	}
 
@@ -246,7 +253,8 @@
 }
 
 
-MODULE_AUTHOR("Arjan van de Ven, Dave Jones <davej@redhat.com>, Dominik Brodowski <linux@brodo.de>");
+MODULE_AUTHOR("Arjan van de Ven, Dave Jones <davej@redhat.com>, "
+		"Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION("PowerNow! driver for AMD K6-2+ / K6-3+ processors.");
 MODULE_LICENSE("GPL");
 
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
index 1b446d7..3c28ccd 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
@@ -6,10 +6,12 @@
  *  Licensed under the terms of the GNU GPL License version 2.
  *  Based upon datasheets & sample CPUs kindly provided by AMD.
  *
- * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt.
- * - We cli/sti on stepping A0 CPUs around the FID/VID transition.
- * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect.
- * - We disable half multipliers if ACPI is used on A0 stepping CPUs.
+ * Errata 5:
+ *  CPU may fail to execute a FID/VID change in presence of interrupt.
+ *  - We cli/sti on stepping A0 CPUs around the FID/VID transition.
+ * Errata 15:
+ *  CPU with half frequency multipliers may hang upon wakeup from disconnect.
+ *  - We disable half multipliers if ACPI is used on A0 stepping CPUs.
  */
 
 #include <linux/kernel.h>
@@ -20,11 +22,11 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/dmi.h>
+#include <linux/timex.h>
+#include <linux/io.h>
 
+#include <asm/timer.h>		/* Needed for recalibrate_cpu_khz() */
 #include <asm/msr.h>
-#include <asm/timer.h>
-#include <asm/timex.h>
-#include <asm/io.h>
 #include <asm/system.h>
 
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
@@ -58,9 +60,9 @@
 union powernow_acpi_control_t {
 	struct {
 		unsigned long fid:5,
-		vid:5,
-		sgtc:20,
-		res1:2;
+			vid:5,
+			sgtc:20,
+			res1:2;
 	} bits;
 	unsigned long val;
 };
@@ -94,14 +96,15 @@
 
 static unsigned int can_scale_bus;
 static unsigned int can_scale_vid;
-static unsigned int minimum_speed=-1;
+static unsigned int minimum_speed = -1;
 static unsigned int maximum_speed;
 static unsigned int number_scales;
 static unsigned int fsb;
 static unsigned int latency;
 static char have_a0;
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k7", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"powernow-k7", msg)
 
 static int check_fsb(unsigned int fsbspeed)
 {
@@ -109,7 +112,7 @@
 	unsigned int f = fsb / 1000;
 
 	delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed;
-	return (delta < 5);
+	return delta < 5;
 }
 
 static int check_powernow(void)
@@ -117,24 +120,26 @@
 	struct cpuinfo_x86 *c = &cpu_data(0);
 	unsigned int maxei, eax, ebx, ecx, edx;
 
-	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 !=6)) {
+	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 6)) {
 #ifdef MODULE
-		printk (KERN_INFO PFX "This module only works with AMD K7 CPUs\n");
+		printk(KERN_INFO PFX "This module only works with "
+				"AMD K7 CPUs\n");
 #endif
 		return 0;
 	}
 
 	/* Get maximum capabilities */
-	maxei = cpuid_eax (0x80000000);
+	maxei = cpuid_eax(0x80000000);
 	if (maxei < 0x80000007) {	/* Any powernow info ? */
 #ifdef MODULE
-		printk (KERN_INFO PFX "No powernow capabilities detected\n");
+		printk(KERN_INFO PFX "No powernow capabilities detected\n");
 #endif
 		return 0;
 	}
 
 	if ((c->x86_model == 6) && (c->x86_mask == 0)) {
-		printk (KERN_INFO PFX "K7 660[A0] core detected, enabling errata workarounds\n");
+		printk(KERN_INFO PFX "K7 660[A0] core detected, "
+				"enabling errata workarounds\n");
 		have_a0 = 1;
 	}
 
@@ -144,37 +149,42 @@
 	if (!(edx & (1 << 1 | 1 << 2)))
 		return 0;
 
-	printk (KERN_INFO PFX "PowerNOW! Technology present. Can scale: ");
+	printk(KERN_INFO PFX "PowerNOW! Technology present. Can scale: ");
 
 	if (edx & 1 << 1) {
-		printk ("frequency");
-		can_scale_bus=1;
+		printk("frequency");
+		can_scale_bus = 1;
 	}
 
 	if ((edx & (1 << 1 | 1 << 2)) == 0x6)
-		printk (" and ");
+		printk(" and ");
 
 	if (edx & 1 << 2) {
-		printk ("voltage");
-		can_scale_vid=1;
+		printk("voltage");
+		can_scale_vid = 1;
 	}
 
-	printk (".\n");
+	printk(".\n");
 	return 1;
 }
 
+static void invalidate_entry(unsigned int entry)
+{
+	powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
+}
 
-static int get_ranges (unsigned char *pst)
+static int get_ranges(unsigned char *pst)
 {
 	unsigned int j;
 	unsigned int speed;
 	u8 fid, vid;
 
-	powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL);
+	powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) *
+				(number_scales + 1)), GFP_KERNEL);
 	if (!powernow_table)
 		return -ENOMEM;
 
-	for (j=0 ; j < number_scales; j++) {
+	for (j = 0 ; j < number_scales; j++) {
 		fid = *pst++;
 
 		powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
@@ -182,10 +192,10 @@
 
 		speed = powernow_table[j].frequency;
 
-		if ((fid_codes[fid] % 10)==5) {
+		if ((fid_codes[fid] % 10) == 5) {
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
 			if (have_a0 == 1)
-				powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID;
+				invalidate_entry(j);
 #endif
 		}
 
@@ -197,7 +207,7 @@
 		vid = *pst++;
 		powernow_table[j].index |= (vid << 8); /* upper 8 bits */
 
-		dprintk ("   FID: 0x%x (%d.%dx [%dMHz])  "
+		dprintk("   FID: 0x%x (%d.%dx [%dMHz])  "
 			 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
 			 fid_codes[fid] % 10, speed/1000, vid,
 			 mobile_vid_table[vid]/1000,
@@ -214,13 +224,13 @@
 {
 	union msr_fidvidctl fidvidctl;
 
-	rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
+	rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
 	if (fidvidctl.bits.FID != fid) {
 		fidvidctl.bits.SGTC = latency;
 		fidvidctl.bits.FID = fid;
 		fidvidctl.bits.VIDC = 0;
 		fidvidctl.bits.FIDC = 1;
-		wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
+		wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
 	}
 }
 
@@ -229,18 +239,18 @@
 {
 	union msr_fidvidctl fidvidctl;
 
-	rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
+	rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
 	if (fidvidctl.bits.VID != vid) {
 		fidvidctl.bits.SGTC = latency;
 		fidvidctl.bits.VID = vid;
 		fidvidctl.bits.FIDC = 0;
 		fidvidctl.bits.VIDC = 1;
-		wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
+		wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
 	}
 }
 
 
-static void change_speed (unsigned int index)
+static void change_speed(unsigned int index)
 {
 	u8 fid, vid;
 	struct cpufreq_freqs freqs;
@@ -257,7 +267,7 @@
 
 	freqs.cpu = 0;
 
-	rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
+	rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
 	cfid = fidvidstatus.bits.CFID;
 	freqs.old = fsb * fid_codes[cfid] / 10;
 
@@ -321,12 +331,14 @@
 		goto err1;
 	}
 
-	if (acpi_processor_perf->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) {
+	if (acpi_processor_perf->control_register.space_id !=
+			ACPI_ADR_SPACE_FIXED_HARDWARE) {
 		retval = -ENODEV;
 		goto err2;
 	}
 
-	if (acpi_processor_perf->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) {
+	if (acpi_processor_perf->status_register.space_id !=
+			ACPI_ADR_SPACE_FIXED_HARDWARE) {
 		retval = -ENODEV;
 		goto err2;
 	}
@@ -338,7 +350,8 @@
 		goto err2;
 	}
 
-	powernow_table = kzalloc((number_scales + 1) * (sizeof(struct cpufreq_frequency_table)), GFP_KERNEL);
+	powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) *
+				(number_scales + 1)), GFP_KERNEL);
 	if (!powernow_table) {
 		retval = -ENOMEM;
 		goto err2;
@@ -352,7 +365,7 @@
 		unsigned int speed, speed_mhz;
 
 		pc.val = (unsigned long) state->control;
-		dprintk ("acpi:  P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
+		dprintk("acpi:  P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
 			 i,
 			 (u32) state->core_frequency,
 			 (u32) state->power,
@@ -381,12 +394,12 @@
 		if (speed % 1000 > 0)
 			speed_mhz++;
 
-		if ((fid_codes[fid] % 10)==5) {
+		if ((fid_codes[fid] % 10) == 5) {
 			if (have_a0 == 1)
-				powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+				invalidate_entry(i);
 		}
 
-		dprintk ("   FID: 0x%x (%d.%dx [%dMHz])  "
+		dprintk("   FID: 0x%x (%d.%dx [%dMHz])  "
 			 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
 			 fid_codes[fid] % 10, speed_mhz, vid,
 			 mobile_vid_table[vid]/1000,
@@ -422,7 +435,8 @@
 err05:
 	kfree(acpi_processor_perf);
 err0:
-	printk(KERN_WARNING PFX "ACPI perflib can not be used in this platform\n");
+	printk(KERN_WARNING PFX "ACPI perflib can not be used on "
+			"this platform\n");
 	acpi_processor_perf = NULL;
 	return retval;
 }
@@ -435,7 +449,14 @@
 }
 #endif
 
-static int powernow_decode_bios (int maxfid, int startvid)
+static void print_pst_entry(struct pst_s *pst, unsigned int j)
+{
+	dprintk("PST:%d (@%p)\n", j, pst);
+	dprintk(" cpuid: 0x%x  fsb: %d  maxFID: 0x%x  startvid: 0x%x\n",
+		pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
+}
+
+static int powernow_decode_bios(int maxfid, int startvid)
 {
 	struct psb_s *psb;
 	struct pst_s *pst;
@@ -446,61 +467,67 @@
 
 	etuple = cpuid_eax(0x80000001);
 
-	for (i=0xC0000; i < 0xffff0 ; i+=16) {
+	for (i = 0xC0000; i < 0xffff0 ; i += 16) {
 
 		p = phys_to_virt(i);
 
-		if (memcmp(p, "AMDK7PNOW!",  10) == 0){
-			dprintk ("Found PSB header at %p\n", p);
+		if (memcmp(p, "AMDK7PNOW!",  10) == 0) {
+			dprintk("Found PSB header at %p\n", p);
 			psb = (struct psb_s *) p;
-			dprintk ("Table version: 0x%x\n", psb->tableversion);
+			dprintk("Table version: 0x%x\n", psb->tableversion);
 			if (psb->tableversion != 0x12) {
-				printk (KERN_INFO PFX "Sorry, only v1.2 tables supported right now\n");
+				printk(KERN_INFO PFX "Sorry, only v1.2 tables"
+						" supported right now\n");
 				return -ENODEV;
 			}
 
-			dprintk ("Flags: 0x%x\n", psb->flags);
-			if ((psb->flags & 1)==0) {
-				dprintk ("Mobile voltage regulator\n");
-			} else {
-				dprintk ("Desktop voltage regulator\n");
-			}
+			dprintk("Flags: 0x%x\n", psb->flags);
+			if ((psb->flags & 1) == 0)
+				dprintk("Mobile voltage regulator\n");
+			else
+				dprintk("Desktop voltage regulator\n");
 
 			latency = psb->settlingtime;
 			if (latency < 100) {
-				printk(KERN_INFO PFX "BIOS set settling time to %d microseconds. "
-						"Should be at least 100. Correcting.\n", latency);
+				printk(KERN_INFO PFX "BIOS set settling time "
+						"to %d microseconds. "
+						"Should be at least 100. "
+						"Correcting.\n", latency);
 				latency = 100;
 			}
-			dprintk ("Settling Time: %d microseconds.\n", psb->settlingtime);
-			dprintk ("Has %d PST tables. (Only dumping ones relevant to this CPU).\n", psb->numpst);
+			dprintk("Settling Time: %d microseconds.\n",
+					psb->settlingtime);
+			dprintk("Has %d PST tables. (Only dumping ones "
+					"relevant to this CPU).\n",
+					psb->numpst);
 
-			p += sizeof (struct psb_s);
+			p += sizeof(struct psb_s);
 
 			pst = (struct pst_s *) p;
 
-			for (j=0; j<psb->numpst; j++) {
+			for (j = 0; j < psb->numpst; j++) {
 				pst = (struct pst_s *) p;
 				number_scales = pst->numpstates;
 
-				if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) &&
-				    (maxfid==pst->maxfid) && (startvid==pst->startvid))
-				{
-					dprintk ("PST:%d (@%p)\n", j, pst);
-					dprintk (" cpuid: 0x%x  fsb: %d  maxFID: 0x%x  startvid: 0x%x\n",
-						 pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
-
-					ret = get_ranges ((char *) pst + sizeof (struct pst_s));
+				if ((etuple == pst->cpuid) &&
+				    check_fsb(pst->fsbspeed) &&
+				    (maxfid == pst->maxfid) &&
+				    (startvid == pst->startvid)) {
+					print_pst_entry(pst, j);
+					p = (char *)pst + sizeof(struct pst_s);
+					ret = get_ranges(p);
 					return ret;
 				} else {
 					unsigned int k;
-					p = (char *) pst + sizeof (struct pst_s);
-					for (k=0; k<number_scales; k++)
-						p+=2;
+					p = (char *)pst + sizeof(struct pst_s);
+					for (k = 0; k < number_scales; k++)
+						p += 2;
 				}
 			}
-			printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple);
-			printk (KERN_INFO PFX "This is indicative of a broken BIOS.\n");
+			printk(KERN_INFO PFX "No PST tables match this cpuid "
+					"(0x%x)\n", etuple);
+			printk(KERN_INFO PFX "This is indicative of a broken "
+					"BIOS.\n");
 
 			return -EINVAL;
 		}
@@ -511,13 +538,14 @@
 }
 
 
-static int powernow_target (struct cpufreq_policy *policy,
+static int powernow_target(struct cpufreq_policy *policy,
 			    unsigned int target_freq,
 			    unsigned int relation)
 {
 	unsigned int newstate;
 
-	if (cpufreq_frequency_table_target(policy, powernow_table, target_freq, relation, &newstate))
+	if (cpufreq_frequency_table_target(policy, powernow_table, target_freq,
+				relation, &newstate))
 		return -EINVAL;
 
 	change_speed(newstate);
@@ -526,7 +554,7 @@
 }
 
 
-static int powernow_verify (struct cpufreq_policy *policy)
+static int powernow_verify(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy, powernow_table);
 }
@@ -566,18 +594,23 @@
 
 	if (cpu)
 		return 0;
-	rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
+	rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
 	cfid = fidvidstatus.bits.CFID;
 
-	return (fsb * fid_codes[cfid] / 10);
+	return fsb * fid_codes[cfid] / 10;
 }
 
 
 static int __init acer_cpufreq_pst(const struct dmi_system_id *d)
 {
-	printk(KERN_WARNING "%s laptop with broken PST tables in BIOS detected.\n", d->ident);
-	printk(KERN_WARNING "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
-	printk(KERN_WARNING "cpufreq scaling has been disabled as a result of this.\n");
+	printk(KERN_WARNING PFX
+		"%s laptop with broken PST tables in BIOS detected.\n",
+		d->ident);
+	printk(KERN_WARNING PFX
+		"You need to downgrade to 3A21 (09/09/2002), or try a newer "
+		"BIOS than 3A71 (01/20/2003)\n");
+	printk(KERN_WARNING PFX
+		"cpufreq scaling has been disabled as a result of this.\n");
 	return 0;
 }
 
@@ -598,7 +631,7 @@
 	{ }
 };
 
-static int __init powernow_cpu_init (struct cpufreq_policy *policy)
+static int __init powernow_cpu_init(struct cpufreq_policy *policy)
 {
 	union msr_fidvidstatus fidvidstatus;
 	int result;
@@ -606,7 +639,7 @@
 	if (policy->cpu != 0)
 		return -ENODEV;
 
-	rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
+	rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
 
 	recalibrate_cpu_khz();
 
@@ -618,19 +651,21 @@
 	dprintk("FSB: %3dMHz\n", fsb/1000);
 
 	if (dmi_check_system(powernow_dmi_table) || acpi_force) {
-		printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");
+		printk(KERN_INFO PFX "PSB/PST known to be broken.  "
+				"Trying ACPI instead\n");
 		result = powernow_acpi_init();
 	} else {
-		result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);
+		result = powernow_decode_bios(fidvidstatus.bits.MFID,
+				fidvidstatus.bits.SVID);
 		if (result) {
-			printk (KERN_INFO PFX "Trying ACPI perflib\n");
+			printk(KERN_INFO PFX "Trying ACPI perflib\n");
 			maximum_speed = 0;
 			minimum_speed = -1;
 			latency = 0;
 			result = powernow_acpi_init();
 			if (result) {
-				printk (KERN_INFO PFX "ACPI and legacy methods failed\n");
-				printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.html\n");
+				printk(KERN_INFO PFX
+					"ACPI and legacy methods failed\n");
 			}
 		} else {
 			/* SGTC use the bus clock as timer */
@@ -642,10 +677,11 @@
 	if (result)
 		return result;
 
-	printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
+	printk(KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
 				minimum_speed/1000, maximum_speed/1000);
 
-	policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency);
+	policy->cpuinfo.transition_latency =
+		cpufreq_scale(2000000UL, fsb, latency);
 
 	policy->cur = powernow_get(0);
 
@@ -654,7 +690,8 @@
 	return cpufreq_frequency_table_cpuinfo(policy, powernow_table);
 }
 
-static int powernow_cpu_exit (struct cpufreq_policy *policy) {
+static int powernow_cpu_exit(struct cpufreq_policy *policy)
+{
 	cpufreq_frequency_table_put_attr(policy->cpu);
 
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
@@ -669,7 +706,7 @@
 	return 0;
 }
 
-static struct freq_attr* powernow_table_attr[] = {
+static struct freq_attr *powernow_table_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
 };
@@ -685,15 +722,15 @@
 	.attr	= powernow_table_attr,
 };
 
-static int __init powernow_init (void)
+static int __init powernow_init(void)
 {
-	if (check_powernow()==0)
+	if (check_powernow() == 0)
 		return -ENODEV;
 	return cpufreq_register_driver(&powernow_driver);
 }
 
 
-static void __exit powernow_exit (void)
+static void __exit powernow_exit(void)
 {
 	cpufreq_unregister_driver(&powernow_driver);
 }
@@ -701,9 +738,9 @@
 module_param(acpi_force,  int, 0444);
 MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
 
-MODULE_AUTHOR ("Dave Jones <davej@redhat.com>");
-MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
+MODULE_DESCRIPTION("Powernow driver for AMD K7 processors.");
+MODULE_LICENSE("GPL");
 
 late_initcall(powernow_init);
 module_exit(powernow_exit);
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index 6428aa1..a15ac94 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -33,16 +33,14 @@
 #include <linux/string.h>
 #include <linux/cpumask.h>
 #include <linux/sched.h>	/* for current / set_cpus_allowed() */
+#include <linux/io.h>
+#include <linux/delay.h>
 
 #include <asm/msr.h>
-#include <asm/io.h>
-#include <asm/delay.h>
 
-#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 #include <linux/acpi.h>
 #include <linux/mutex.h>
 #include <acpi/processor.h>
-#endif
 
 #define PFX "powernow-k8: "
 #define VERSION "version 2.20.00"
@@ -71,7 +69,8 @@
 	return 1000 * find_freq_from_fid(fid);
 }
 
-static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data, u32 pstate)
+static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data,
+		u32 pstate)
 {
 	return data[pstate].frequency;
 }
@@ -186,7 +185,9 @@
 		return 1;
 	}
 
-	lo = fid | (data->currvid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID;
+	lo = fid;
+	lo |= (data->currvid << MSR_C_LO_VID_SHIFT);
+	lo |= MSR_C_LO_INIT_FID_VID;
 
 	dprintk("writing fid 0x%x, lo 0x%x, hi 0x%x\n",
 		fid, lo, data->plllock * PLL_LOCK_CONVERSION);
@@ -194,7 +195,9 @@
 	do {
 		wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION);
 		if (i++ > 100) {
-			printk(KERN_ERR PFX "Hardware error - pending bit very stuck - no further pstate changes possible\n");
+			printk(KERN_ERR PFX
+				"Hardware error - pending bit very stuck - "
+				"no further pstate changes possible\n");
 			return 1;
 		}
 	} while (query_current_values_with_pending_wait(data));
@@ -202,14 +205,16 @@
 	count_off_irt(data);
 
 	if (savevid != data->currvid) {
-		printk(KERN_ERR PFX "vid change on fid trans, old 0x%x, new 0x%x\n",
-		       savevid, data->currvid);
+		printk(KERN_ERR PFX
+			"vid change on fid trans, old 0x%x, new 0x%x\n",
+			savevid, data->currvid);
 		return 1;
 	}
 
 	if (fid != data->currfid) {
-		printk(KERN_ERR PFX "fid trans failed, fid 0x%x, curr 0x%x\n", fid,
-		        data->currfid);
+		printk(KERN_ERR PFX
+			"fid trans failed, fid 0x%x, curr 0x%x\n", fid,
+			data->currfid);
 		return 1;
 	}
 
@@ -228,7 +233,9 @@
 		return 1;
 	}
 
-	lo = data->currfid | (vid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID;
+	lo = data->currfid;
+	lo |= (vid << MSR_C_LO_VID_SHIFT);
+	lo |= MSR_C_LO_INIT_FID_VID;
 
 	dprintk("writing vid 0x%x, lo 0x%x, hi 0x%x\n",
 		vid, lo, STOP_GRANT_5NS);
@@ -236,20 +243,24 @@
 	do {
 		wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS);
 		if (i++ > 100) {
-			printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
+			printk(KERN_ERR PFX "internal error - pending bit "
+					"very stuck - no further pstate "
+					"changes possible\n");
 			return 1;
 		}
 	} while (query_current_values_with_pending_wait(data));
 
 	if (savefid != data->currfid) {
-		printk(KERN_ERR PFX "fid changed on vid trans, old 0x%x new 0x%x\n",
+		printk(KERN_ERR PFX "fid changed on vid trans, old "
+			"0x%x new 0x%x\n",
 		       savefid, data->currfid);
 		return 1;
 	}
 
 	if (vid != data->currvid) {
-		printk(KERN_ERR PFX "vid trans failed, vid 0x%x, curr 0x%x\n", vid,
-				data->currvid);
+		printk(KERN_ERR PFX "vid trans failed, vid 0x%x, "
+				"curr 0x%x\n",
+				vid, data->currvid);
 		return 1;
 	}
 
@@ -261,7 +272,8 @@
  * Decreasing vid codes represent increasing voltages:
  * vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of VID_OFF is off.
  */
-static int decrease_vid_code_by_step(struct powernow_k8_data *data, u32 reqvid, u32 step)
+static int decrease_vid_code_by_step(struct powernow_k8_data *data,
+		u32 reqvid, u32 step)
 {
 	if ((data->currvid - reqvid) > step)
 		reqvid = data->currvid - step;
@@ -283,7 +295,8 @@
 }
 
 /* Change Opteron/Athlon64 fid and vid, by the 3 phases. */
-static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 reqvid)
+static int transition_fid_vid(struct powernow_k8_data *data,
+		u32 reqfid, u32 reqvid)
 {
 	if (core_voltage_pre_transition(data, reqvid))
 		return 1;
@@ -298,7 +311,8 @@
 		return 1;
 
 	if ((reqfid != data->currfid) || (reqvid != data->currvid)) {
-		printk(KERN_ERR PFX "failed (cpu%d): req 0x%x 0x%x, curr 0x%x 0x%x\n",
+		printk(KERN_ERR PFX "failed (cpu%d): req 0x%x 0x%x, "
+				"curr 0x%x 0x%x\n",
 				smp_processor_id(),
 				reqfid, reqvid, data->currfid, data->currvid);
 		return 1;
@@ -311,13 +325,15 @@
 }
 
 /* Phase 1 - core voltage transition ... setup voltage */
-static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid)
+static int core_voltage_pre_transition(struct powernow_k8_data *data,
+		u32 reqvid)
 {
 	u32 rvosteps = data->rvo;
 	u32 savefid = data->currfid;
 	u32 maxvid, lo;
 
-	dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n",
+	dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, "
+		"reqvid 0x%x, rvo 0x%x\n",
 		smp_processor_id(),
 		data->currfid, data->currvid, reqvid, data->rvo);
 
@@ -340,7 +356,7 @@
 		} else {
 			dprintk("ph1: changing vid for rvo, req 0x%x\n",
 				data->currvid - 1);
-			if (decrease_vid_code_by_step(data, data->currvid - 1, 1))
+			if (decrease_vid_code_by_step(data, data->currvid-1, 1))
 				return 1;
 			rvosteps--;
 		}
@@ -350,7 +366,8 @@
 		return 1;
 
 	if (savefid != data->currfid) {
-		printk(KERN_ERR PFX "ph1 err, currfid changed 0x%x\n", data->currfid);
+		printk(KERN_ERR PFX "ph1 err, currfid changed 0x%x\n",
+				data->currfid);
 		return 1;
 	}
 
@@ -363,20 +380,24 @@
 /* Phase 2 - core frequency transition */
 static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
 {
-	u32 vcoreqfid, vcocurrfid, vcofiddiff, fid_interval, savevid = data->currvid;
+	u32 vcoreqfid, vcocurrfid, vcofiddiff;
+	u32 fid_interval, savevid = data->currvid;
 
-	if ((reqfid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
-		printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n",
-			reqfid, data->currfid);
+	if ((reqfid < HI_FID_TABLE_BOTTOM) &&
+	    (data->currfid < HI_FID_TABLE_BOTTOM)) {
+		printk(KERN_ERR PFX "ph2: illegal lo-lo transition "
+				"0x%x 0x%x\n", reqfid, data->currfid);
 		return 1;
 	}
 
 	if (data->currfid == reqfid) {
-		printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n", data->currfid);
+		printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n",
+				data->currfid);
 		return 0;
 	}
 
-	dprintk("ph2 (cpu%d): starting, currfid 0x%x, currvid 0x%x, reqfid 0x%x\n",
+	dprintk("ph2 (cpu%d): starting, currfid 0x%x, currvid 0x%x, "
+		"reqfid 0x%x\n",
 		smp_processor_id(),
 		data->currfid, data->currvid, reqfid);
 
@@ -390,14 +411,14 @@
 
 		if (reqfid > data->currfid) {
 			if (data->currfid > LO_FID_TABLE_TOP) {
-				if (write_new_fid(data, data->currfid + fid_interval)) {
+				if (write_new_fid(data,
+						data->currfid + fid_interval))
 					return 1;
-				}
 			} else {
 				if (write_new_fid
-				    (data, 2 + convert_fid_to_vco_fid(data->currfid))) {
+				    (data,
+				     2 + convert_fid_to_vco_fid(data->currfid)))
 					return 1;
-				}
 			}
 		} else {
 			if (write_new_fid(data, data->currfid - fid_interval))
@@ -417,7 +438,8 @@
 
 	if (data->currfid != reqfid) {
 		printk(KERN_ERR PFX
-			"ph2: mismatch, failed fid transition, curr 0x%x, req 0x%x\n",
+			"ph2: mismatch, failed fid transition, "
+			"curr 0x%x, req 0x%x\n",
 			data->currfid, reqfid);
 		return 1;
 	}
@@ -435,7 +457,8 @@
 }
 
 /* Phase 3 - core voltage transition flow ... jump to the final vid. */
-static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid)
+static int core_voltage_post_transition(struct powernow_k8_data *data,
+		u32 reqvid)
 {
 	u32 savefid = data->currfid;
 	u32 savereqvid = reqvid;
@@ -457,7 +480,8 @@
 
 		if (data->currvid != reqvid) {
 			printk(KERN_ERR PFX
-			       "ph3: failed vid transition\n, req 0x%x, curr 0x%x",
+			       "ph3: failed vid transition\n, "
+			       "req 0x%x, curr 0x%x",
 			       reqvid, data->currvid);
 			return 1;
 		}
@@ -508,7 +532,8 @@
 	if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
 		if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
 		    ((eax & CPUID_XMOD) > CPUID_XMOD_REV_MASK)) {
-			printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
+			printk(KERN_INFO PFX
+				"Processor cpuid %x not supported\n", eax);
 			goto out;
 		}
 
@@ -520,8 +545,10 @@
 		}
 
 		cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
-		if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
-			printk(KERN_INFO PFX "Power state transitions not supported\n");
+		if ((edx & P_STATE_TRANSITION_CAPABLE)
+			!= P_STATE_TRANSITION_CAPABLE) {
+			printk(KERN_INFO PFX
+				"Power state transitions not supported\n");
 			goto out;
 		}
 	} else { /* must be a HW Pstate capable processor */
@@ -539,7 +566,8 @@
 	return rc;
 }
 
-static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8 maxvid)
+static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst,
+		u8 maxvid)
 {
 	unsigned int j;
 	u8 lastfid = 0xff;
@@ -550,12 +578,14 @@
 			       j, pst[j].vid);
 			return -EINVAL;
 		}
-		if (pst[j].vid < data->rvo) {	/* vid + rvo >= 0 */
+		if (pst[j].vid < data->rvo) {
+			/* vid + rvo >= 0 */
 			printk(KERN_ERR FW_BUG PFX "0 vid exceeded with pstate"
 			       " %d\n", j);
 			return -ENODEV;
 		}
-		if (pst[j].vid < maxvid + data->rvo) {	/* vid + rvo >= maxvid */
+		if (pst[j].vid < maxvid + data->rvo) {
+			/* vid + rvo >= maxvid */
 			printk(KERN_ERR FW_BUG PFX "maxvid exceeded with pstate"
 			       " %d\n", j);
 			return -ENODEV;
@@ -579,23 +609,31 @@
 		return -EINVAL;
 	}
 	if (lastfid > LO_FID_TABLE_TOP)
-		printk(KERN_INFO FW_BUG PFX  "first fid not from lo freq table\n");
+		printk(KERN_INFO FW_BUG PFX
+			"first fid not from lo freq table\n");
 
 	return 0;
 }
 
+static void invalidate_entry(struct powernow_k8_data *data, unsigned int entry)
+{
+	data->powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
+}
+
 static void print_basics(struct powernow_k8_data *data)
 {
 	int j;
 	for (j = 0; j < data->numps; j++) {
-		if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
+		if (data->powernow_table[j].frequency !=
+				CPUFREQ_ENTRY_INVALID) {
 			if (cpu_family == CPU_HW_PSTATE) {
-				printk(KERN_INFO PFX "   %d : pstate %d (%d MHz)\n",
-					j,
+				printk(KERN_INFO PFX
+					"   %d : pstate %d (%d MHz)\n", j,
 					data->powernow_table[j].index,
 					data->powernow_table[j].frequency/1000);
 			} else {
-				printk(KERN_INFO PFX "   %d : fid 0x%x (%d MHz), vid 0x%x\n",
+				printk(KERN_INFO PFX
+					"   %d : fid 0x%x (%d MHz), vid 0x%x\n",
 					j,
 					data->powernow_table[j].index & 0xff,
 					data->powernow_table[j].frequency/1000,
@@ -604,20 +642,25 @@
 		}
 	}
 	if (data->batps)
-		printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps);
+		printk(KERN_INFO PFX "Only %d pstates on battery\n",
+				data->batps);
 }
 
-static int fill_powernow_table(struct powernow_k8_data *data, struct pst_s *pst, u8 maxvid)
+static int fill_powernow_table(struct powernow_k8_data *data,
+		struct pst_s *pst, u8 maxvid)
 {
 	struct cpufreq_frequency_table *powernow_table;
 	unsigned int j;
 
-	if (data->batps) {    /* use ACPI support to get full speed on mains power */
-		printk(KERN_WARNING PFX "Only %d pstates usable (use ACPI driver for full range\n", data->batps);
+	if (data->batps) {
+		/* use ACPI support to get full speed on mains power */
+		printk(KERN_WARNING PFX
+			"Only %d pstates usable (use ACPI driver for full "
+			"range\n", data->batps);
 		data->numps = data->batps;
 	}
 
-	for ( j=1; j<data->numps; j++ ) {
+	for (j = 1; j < data->numps; j++) {
 		if (pst[j-1].fid >= pst[j].fid) {
 			printk(KERN_ERR PFX "PST out of sequence\n");
 			return -EINVAL;
@@ -640,9 +683,11 @@
 	}
 
 	for (j = 0; j < data->numps; j++) {
+		int freq;
 		powernow_table[j].index = pst[j].fid; /* lower 8 bits */
 		powernow_table[j].index |= (pst[j].vid << 8); /* upper 8 bits */
-		powernow_table[j].frequency = find_khz_freq_from_fid(pst[j].fid);
+		freq = find_khz_freq_from_fid(pst[j].fid);
+		powernow_table[j].frequency = freq;
 	}
 	powernow_table[data->numps].frequency = CPUFREQ_TABLE_END;
 	powernow_table[data->numps].index = 0;
@@ -658,7 +703,8 @@
 		print_basics(data);
 
 	for (j = 0; j < data->numps; j++)
-		if ((pst[j].fid==data->currfid) && (pst[j].vid==data->currvid))
+		if ((pst[j].fid == data->currfid) &&
+		    (pst[j].vid == data->currvid))
 			return 0;
 
 	dprintk("currfid/vid do not match PST, ignoring\n");
@@ -698,7 +744,8 @@
 		}
 
 		data->vstable = psb->vstable;
-		dprintk("voltage stabilization time: %d(*20us)\n", data->vstable);
+		dprintk("voltage stabilization time: %d(*20us)\n",
+				data->vstable);
 
 		dprintk("flags2: 0x%x\n", psb->flags2);
 		data->rvo = psb->flags2 & 3;
@@ -713,11 +760,12 @@
 
 		dprintk("numpst: 0x%x\n", psb->num_tables);
 		cpst = psb->num_tables;
-		if ((psb->cpuid == 0x00000fc0) || (psb->cpuid == 0x00000fe0) ){
+		if ((psb->cpuid == 0x00000fc0) ||
+		    (psb->cpuid == 0x00000fe0)) {
 			thiscpuid = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
-			if ((thiscpuid == 0x00000fc0) || (thiscpuid == 0x00000fe0) ) {
+			if ((thiscpuid == 0x00000fc0) ||
+			    (thiscpuid == 0x00000fe0))
 				cpst = 1;
-			}
 		}
 		if (cpst != 1) {
 			printk(KERN_ERR FW_BUG PFX "numpst must be 1\n");
@@ -732,7 +780,8 @@
 
 		data->numps = psb->numps;
 		dprintk("numpstates: 0x%x\n", data->numps);
-		return fill_powernow_table(data, (struct pst_s *)(psb+1), maxvid);
+		return fill_powernow_table(data,
+				(struct pst_s *)(psb+1), maxvid);
 	}
 	/*
 	 * If you see this message, complain to BIOS manufacturer. If
@@ -745,28 +794,31 @@
 	 * BIOS and Kernel Developer's Guide, which is available on
 	 * www.amd.com
 	 */
-	printk(KERN_ERR PFX "BIOS error - no PSB or ACPI _PSS objects\n");
+	printk(KERN_ERR FW_BUG PFX "No PSB or ACPI _PSS objects\n");
 	return -ENODEV;
 }
 
-#ifdef CONFIG_X86_POWERNOW_K8_ACPI
-static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
+static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data,
+		unsigned int index)
 {
+	acpi_integer control;
+
 	if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE))
 		return;
 
-	data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK;
-	data->rvo = (data->acpi_data.states[index].control >> RVO_SHIFT) & RVO_MASK;
-	data->exttype = (data->acpi_data.states[index].control >> EXT_TYPE_SHIFT) & EXT_TYPE_MASK;
-	data->plllock = (data->acpi_data.states[index].control >> PLL_L_SHIFT) & PLL_L_MASK;
-	data->vidmvs = 1 << ((data->acpi_data.states[index].control >> MVS_SHIFT) & MVS_MASK);
-	data->vstable = (data->acpi_data.states[index].control >> VST_SHIFT) & VST_MASK;
-}
+	control = data->acpi_data.states[index].control; data->irt = (control
+			>> IRT_SHIFT) & IRT_MASK; data->rvo = (control >>
+				RVO_SHIFT) & RVO_MASK; data->exttype = (control
+					>> EXT_TYPE_SHIFT) & EXT_TYPE_MASK;
+	data->plllock = (control >> PLL_L_SHIFT) & PLL_L_MASK; data->vidmvs = 1
+		<< ((control >> MVS_SHIFT) & MVS_MASK); data->vstable =
+		(control >> VST_SHIFT) & VST_MASK; }
 
 static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 {
 	struct cpufreq_frequency_table *powernow_table;
 	int ret_val = -ENODEV;
+	acpi_integer space_id;
 
 	if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
 		dprintk("register performance failed: bad ACPI data\n");
@@ -779,11 +831,12 @@
 		goto err_out;
 	}
 
-	if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
-		(data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
+	space_id = data->acpi_data.control_register.space_id;
+	if ((space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
+		(space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
 		dprintk("Invalid control/status registers (%x - %x)\n",
 			data->acpi_data.control_register.space_id,
-			data->acpi_data.status_register.space_id);
+			space_id);
 		goto err_out;
 	}
 
@@ -802,7 +855,8 @@
 	if (ret_val)
 		goto err_out_mem;
 
-	powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END;
+	powernow_table[data->acpi_data.state_count].frequency =
+		CPUFREQ_TABLE_END;
 	powernow_table[data->acpi_data.state_count].index = 0;
 	data->powernow_table = powernow_table;
 
@@ -830,13 +884,15 @@
 err_out:
 	acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
 
-	/* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
+	/* data->acpi_data.state_count informs us at ->exit()
+	 * whether ACPI was used */
 	data->acpi_data.state_count = 0;
 
 	return ret_val;
 }
 
-static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
+static int fill_powernow_table_pstate(struct powernow_k8_data *data,
+		struct cpufreq_frequency_table *powernow_table)
 {
 	int i;
 	u32 hi = 0, lo = 0;
@@ -848,84 +904,101 @@
 
 		index = data->acpi_data.states[i].control & HW_PSTATE_MASK;
 		if (index > data->max_hw_pstate) {
-			printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index);
-			printk(KERN_ERR PFX "Please report to BIOS manufacturer\n");
-			powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+			printk(KERN_ERR PFX "invalid pstate %d - "
+					"bad value %d.\n", i, index);
+			printk(KERN_ERR PFX "Please report to BIOS "
+					"manufacturer\n");
+			invalidate_entry(data, i);
 			continue;
 		}
 		rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
 		if (!(hi & HW_PSTATE_VALID_MASK)) {
 			dprintk("invalid pstate %d, ignoring\n", index);
-			powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+			invalidate_entry(data, i);
 			continue;
 		}
 
 		powernow_table[i].index = index;
 
-		powernow_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000;
+		powernow_table[i].frequency =
+			data->acpi_data.states[i].core_frequency * 1000;
 	}
 	return 0;
 }
 
-static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
+static int fill_powernow_table_fidvid(struct powernow_k8_data *data,
+		struct cpufreq_frequency_table *powernow_table)
 {
 	int i;
 	int cntlofreq = 0;
+
 	for (i = 0; i < data->acpi_data.state_count; i++) {
 		u32 fid;
 		u32 vid;
+		u32 freq, index;
+		acpi_integer status, control;
 
 		if (data->exttype) {
-			fid = data->acpi_data.states[i].status & EXT_FID_MASK;
-			vid = (data->acpi_data.states[i].status >> VID_SHIFT) & EXT_VID_MASK;
+			status =  data->acpi_data.states[i].status;
+			fid = status & EXT_FID_MASK;
+			vid = (status >> VID_SHIFT) & EXT_VID_MASK;
 		} else {
-			fid = data->acpi_data.states[i].control & FID_MASK;
-			vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK;
+			control =  data->acpi_data.states[i].control;
+			fid = control & FID_MASK;
+			vid = (control >> VID_SHIFT) & VID_MASK;
 		}
 
 		dprintk("   %d : fid 0x%x, vid 0x%x\n", i, fid, vid);
 
-		powernow_table[i].index = fid; /* lower 8 bits */
-		powernow_table[i].index |= (vid << 8); /* upper 8 bits */
-		powernow_table[i].frequency = find_khz_freq_from_fid(fid);
+		index = fid | (vid<<8);
+		powernow_table[i].index = index;
+
+		freq = find_khz_freq_from_fid(fid);
+		powernow_table[i].frequency = freq;
 
 		/* verify frequency is OK */
-		if ((powernow_table[i].frequency > (MAX_FREQ * 1000)) ||
-			(powernow_table[i].frequency < (MIN_FREQ * 1000))) {
-			dprintk("invalid freq %u kHz, ignoring\n", powernow_table[i].frequency);
-			powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+		if ((freq > (MAX_FREQ * 1000)) || (freq < (MIN_FREQ * 1000))) {
+			dprintk("invalid freq %u kHz, ignoring\n", freq);
+			invalidate_entry(data, i);
 			continue;
 		}
 
-		/* verify voltage is OK - BIOSs are using "off" to indicate invalid */
+		/* verify voltage is OK -
+		 * BIOSs are using "off" to indicate invalid */
 		if (vid == VID_OFF) {
 			dprintk("invalid vid %u, ignoring\n", vid);
-			powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+			invalidate_entry(data, i);
 			continue;
 		}
 
 		/* verify only 1 entry from the lo frequency table */
 		if (fid < HI_FID_TABLE_BOTTOM) {
 			if (cntlofreq) {
-				/* if both entries are the same, ignore this one ... */
-				if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
-				    (powernow_table[i].index != powernow_table[cntlofreq].index)) {
-					printk(KERN_ERR PFX "Too many lo freq table entries\n");
+				/* if both entries are the same,
+				 * ignore this one ... */
+				if ((freq != powernow_table[cntlofreq].frequency) ||
+				    (index != powernow_table[cntlofreq].index)) {
+					printk(KERN_ERR PFX
+						"Too many lo freq table "
+						"entries\n");
 					return 1;
 				}
 
-				dprintk("double low frequency table entry, ignoring it.\n");
-				powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+				dprintk("double low frequency table entry, "
+						"ignoring it.\n");
+				invalidate_entry(data, i);
 				continue;
 			} else
 				cntlofreq = i;
 		}
 
-		if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
-			printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n",
-				powernow_table[i].frequency,
-				(unsigned int) (data->acpi_data.states[i].core_frequency * 1000));
-			powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+		if (freq != (data->acpi_data.states[i].core_frequency * 1000)) {
+			printk(KERN_INFO PFX "invalid freq entries "
+				"%u kHz vs. %u kHz\n", freq,
+				(unsigned int)
+				(data->acpi_data.states[i].core_frequency
+				 * 1000));
+			invalidate_entry(data, i);
 			continue;
 		}
 	}
@@ -935,7 +1008,8 @@
 static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
 {
 	if (data->acpi_data.state_count)
-		acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
+		acpi_processor_unregister_performance(&data->acpi_data,
+				data->cpu);
 	free_cpumask_var(data->acpi_data.shared_cpu_map);
 }
 
@@ -953,15 +1027,9 @@
 	return 1000 * max_latency;
 }
 
-#else
-static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { return -ENODEV; }
-static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) { return; }
-static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { return; }
-static int get_transition_latency(struct powernow_k8_data *data) { return 0; }
-#endif /* CONFIG_X86_POWERNOW_K8_ACPI */
-
 /* Take a frequency, and issue the fid/vid transition command */
-static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned int index)
+static int transition_frequency_fidvid(struct powernow_k8_data *data,
+		unsigned int index)
 {
 	u32 fid = 0;
 	u32 vid = 0;
@@ -989,7 +1057,8 @@
 		return 0;
 	}
 
-	if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
+	if ((fid < HI_FID_TABLE_BOTTOM) &&
+	    (data->currfid < HI_FID_TABLE_BOTTOM)) {
 		printk(KERN_ERR PFX
 		       "ignoring illegal change in lo freq table-%x to 0x%x\n",
 		       data->currfid, fid);
@@ -1017,7 +1086,8 @@
 }
 
 /* Take a frequency, and issue the hardware pstate transition command */
-static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned int index)
+static int transition_frequency_pstate(struct powernow_k8_data *data,
+		unsigned int index)
 {
 	u32 pstate = 0;
 	int res, i;
@@ -1029,7 +1099,8 @@
 	pstate = index & HW_PSTATE_MASK;
 	if (pstate > data->max_hw_pstate)
 		return 0;
-	freqs.old = find_khz_freq_from_pstate(data->powernow_table, data->currpstate);
+	freqs.old = find_khz_freq_from_pstate(data->powernow_table,
+			data->currpstate);
 	freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
 
 	for_each_cpu_mask_nr(i, *(data->available_cores)) {
@@ -1048,7 +1119,8 @@
 }
 
 /* Driver entry point to switch to the target frequency */
-static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
+static int powernowk8_target(struct cpufreq_policy *pol,
+		unsigned targfreq, unsigned relation)
 {
 	cpumask_t oldmask;
 	struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
@@ -1087,14 +1159,18 @@
 		dprintk("targ: curr fid 0x%x, vid 0x%x\n",
 		data->currfid, data->currvid);
 
-		if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
+		if ((checkvid != data->currvid) ||
+		    (checkfid != data->currfid)) {
 			printk(KERN_INFO PFX
-				"error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
-				checkfid, data->currfid, checkvid, data->currvid);
+				"error - out of sync, fix 0x%x 0x%x, "
+				"vid 0x%x 0x%x\n",
+				checkfid, data->currfid,
+				checkvid, data->currvid);
 		}
 	}
 
-	if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
+	if (cpufreq_frequency_table_target(pol, data->powernow_table,
+				targfreq, relation, &newstate))
 		goto err_out;
 
 	mutex_lock(&fidvid_mutex);
@@ -1114,7 +1190,8 @@
 	mutex_unlock(&fidvid_mutex);
 
 	if (cpu_family == CPU_HW_PSTATE)
-		pol->cur = find_khz_freq_from_pstate(data->powernow_table, newstate);
+		pol->cur = find_khz_freq_from_pstate(data->powernow_table,
+				newstate);
 	else
 		pol->cur = find_khz_freq_from_fid(data->currfid);
 	ret = 0;
@@ -1141,6 +1218,7 @@
 	struct powernow_k8_data *data;
 	cpumask_t oldmask;
 	int rc;
+	static int print_once;
 
 	if (!cpu_online(pol->cpu))
 		return -ENODEV;
@@ -1163,33 +1241,31 @@
 		 * an UP version, and is deprecated by AMD.
 		 */
 		if (num_online_cpus() != 1) {
-#ifndef CONFIG_ACPI_PROCESSOR
-			printk(KERN_ERR PFX "ACPI Processor support is required "
-			       "for SMP systems but is absent. Please load the "
-			       "ACPI Processor module before starting this "
-			       "driver.\n");
-#else
-			printk(KERN_ERR FW_BUG PFX "Your BIOS does not provide"
-			       " ACPI _PSS objects in a way that Linux "
-			       "understands. Please report this to the Linux "
-			       "ACPI maintainers and complain to your BIOS "
-			       "vendor.\n");
-#endif
-			kfree(data);
-			return -ENODEV;
+			/*
+			 * Replace this one with print_once as soon as such a
+			 * thing gets introduced
+			 */
+			if (!print_once) {
+				WARN_ONCE(1, KERN_ERR FW_BUG PFX "Your BIOS "
+					"does not provide ACPI _PSS objects "
+					"in a way that Linux understands. "
+					"Please report this to the Linux ACPI"
+					" maintainers and complain to your "
+					"BIOS vendor.\n");
+				print_once++;
+			}
+			goto err_out;
 		}
 		if (pol->cpu != 0) {
 			printk(KERN_ERR FW_BUG PFX "No ACPI _PSS objects for "
 			       "CPU other than CPU0. Complain to your BIOS "
 			       "vendor.\n");
-			kfree(data);
-			return -ENODEV;
+			goto err_out;
 		}
 		rc = find_psb_table(data);
-		if (rc) {
-			kfree(data);
-			return -ENODEV;
-		}
+		if (rc)
+			goto err_out;
+
 		/* Take a crude guess here.
 		 * That guess was in microseconds, so multiply with 1000 */
 		pol->cpuinfo.transition_latency = (
@@ -1204,16 +1280,16 @@
 
 	if (smp_processor_id() != pol->cpu) {
 		printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
-		goto err_out;
+		goto err_out_unmask;
 	}
 
 	if (pending_bit_stuck()) {
 		printk(KERN_ERR PFX "failing init, change pending bit set\n");
-		goto err_out;
+		goto err_out_unmask;
 	}
 
 	if (query_current_values_with_pending_wait(data))
-		goto err_out;
+		goto err_out_unmask;
 
 	if (cpu_family == CPU_OPTERON)
 		fidvid_msr_init();
@@ -1228,7 +1304,8 @@
 	data->available_cores = pol->cpus;
 
 	if (cpu_family == CPU_HW_PSTATE)
-		pol->cur = find_khz_freq_from_pstate(data->powernow_table, data->currpstate);
+		pol->cur = find_khz_freq_from_pstate(data->powernow_table,
+				data->currpstate);
 	else
 		pol->cur = find_khz_freq_from_fid(data->currfid);
 	dprintk("policy current frequency %d kHz\n", pol->cur);
@@ -1245,7 +1322,8 @@
 	cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
 
 	if (cpu_family == CPU_HW_PSTATE)
-		dprintk("cpu_init done, current pstate 0x%x\n", data->currpstate);
+		dprintk("cpu_init done, current pstate 0x%x\n",
+				data->currpstate);
 	else
 		dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n",
 			data->currfid, data->currvid);
@@ -1254,15 +1332,16 @@
 
 	return 0;
 
-err_out:
+err_out_unmask:
 	set_cpus_allowed_ptr(current, &oldmask);
 	powernow_k8_cpu_exit_acpi(data);
 
+err_out:
 	kfree(data);
 	return -ENODEV;
 }
 
-static int __devexit powernowk8_cpu_exit (struct cpufreq_policy *pol)
+static int __devexit powernowk8_cpu_exit(struct cpufreq_policy *pol)
 {
 	struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
 
@@ -1279,7 +1358,7 @@
 	return 0;
 }
 
-static unsigned int powernowk8_get (unsigned int cpu)
+static unsigned int powernowk8_get(unsigned int cpu)
 {
 	struct powernow_k8_data *data;
 	cpumask_t oldmask = current->cpus_allowed;
@@ -1315,7 +1394,7 @@
 	return khz;
 }
 
-static struct freq_attr* powernow_k8_attr[] = {
+static struct freq_attr *powernow_k8_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
 };
@@ -1360,7 +1439,8 @@
 	cpufreq_unregister_driver(&cpufreq_amd64_driver);
 }
 
-MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com>");
+MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and "
+		"Mark Langsdorf <mark.langsdorf@amd.com>");
 MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
 MODULE_LICENSE("GPL");
 
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
index 8ecc75b..6c6698f 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
@@ -45,11 +45,10 @@
 	 * frequency is in kHz */
 	struct cpufreq_frequency_table  *powernow_table;
 
-#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 	/* the acpi table needs to be kept. it's only available if ACPI was
 	 * used to determine valid frequency/vid/fid states */
 	struct acpi_processor_performance acpi_data;
-#endif
+
 	/* we need to keep track of associated cores, but let cpufreq
 	 * handle hotplug events - so just point at cpufreq pol->cpus
 	 * structure */
@@ -222,10 +221,8 @@
 
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
 
-#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
 static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
-#endif
 
 #ifdef CONFIG_SMP
 static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
diff --git a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c
index 42da9bd..435a996 100644
--- a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c
+++ b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c
@@ -19,17 +19,19 @@
 
 #include <linux/delay.h>
 #include <linux/cpufreq.h>
+#include <linux/timex.h>
+#include <linux/io.h>
 
 #include <asm/msr.h>
-#include <asm/timex.h>
-#include <asm/io.h>
 
 #define MMCR_BASE	0xfffef000	/* The default base address */
 #define OFFS_CPUCTL	0x2   /* CPU Control Register */
 
 static __u8 __iomem *cpuctl;
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "sc520_freq", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"sc520_freq", msg)
+#define PFX "sc520_freq: "
 
 static struct cpufreq_frequency_table sc520_freq_table[] = {
 	{0x01,	100000},
@@ -43,7 +45,8 @@
 
 	switch (clockspeed_reg & 0x03) {
 	default:
-		printk(KERN_ERR "sc520_freq: error: cpuctl register has unexpected value %02x\n", clockspeed_reg);
+		printk(KERN_ERR PFX "error: cpuctl register has unexpected "
+				"value %02x\n", clockspeed_reg);
 	case 0x01:
 		return 100000;
 	case 0x02:
@@ -51,7 +54,7 @@
 	}
 }
 
-static void sc520_freq_set_cpu_state (unsigned int state)
+static void sc520_freq_set_cpu_state(unsigned int state)
 {
 
 	struct cpufreq_freqs	freqs;
@@ -76,18 +79,19 @@
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 };
 
-static int sc520_freq_verify (struct cpufreq_policy *policy)
+static int sc520_freq_verify(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]);
 }
 
-static int sc520_freq_target (struct cpufreq_policy *policy,
+static int sc520_freq_target(struct cpufreq_policy *policy,
 			    unsigned int target_freq,
 			    unsigned int relation)
 {
 	unsigned int newstate = 0;
 
-	if (cpufreq_frequency_table_target(policy, sc520_freq_table, target_freq, relation, &newstate))
+	if (cpufreq_frequency_table_target(policy, sc520_freq_table,
+				target_freq, relation, &newstate))
 		return -EINVAL;
 
 	sc520_freq_set_cpu_state(newstate);
@@ -116,7 +120,7 @@
 
 	result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table);
 	if (result)
-		return (result);
+		return result;
 
 	cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu);
 
@@ -131,7 +135,7 @@
 }
 
 
-static struct freq_attr* sc520_freq_attr[] = {
+static struct freq_attr *sc520_freq_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
 };
@@ -155,13 +159,13 @@
 	int err;
 
 	/* Test if we have the right hardware */
-	if(c->x86_vendor != X86_VENDOR_AMD ||
-				c->x86 != 4 || c->x86_model != 9) {
+	if (c->x86_vendor != X86_VENDOR_AMD ||
+	    c->x86 != 4 || c->x86_model != 9) {
 		dprintk("no Elan SC520 processor found!\n");
 		return -ENODEV;
 	}
 	cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
-	if(!cpuctl) {
+	if (!cpuctl) {
 		printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
 		return -ENOMEM;
 	}
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
index dedc1e9..8bbb11a 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
@@ -39,7 +39,7 @@
 
 /* speedstep_processor
  */
-static unsigned int speedstep_processor = 0;
+static unsigned int speedstep_processor;
 
 static u32 pmbase;
 
@@ -54,7 +54,8 @@
 };
 
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-ich", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"speedstep-ich", msg)
 
 
 /**
@@ -62,7 +63,7 @@
  *
  * Returns: -ENODEV if no register could be found
  */
-static int speedstep_find_register (void)
+static int speedstep_find_register(void)
 {
 	if (!speedstep_chipset_dev)
 		return -ENODEV;
@@ -90,7 +91,7 @@
  *
  *   Tries to change the SpeedStep state.
  */
-static void speedstep_set_state (unsigned int state)
+static void speedstep_set_state(unsigned int state)
 {
 	u8 pm2_blk;
 	u8 value;
@@ -133,11 +134,11 @@
 
 	dprintk("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
 
-	if (state == (value & 0x1)) {
-		dprintk("change to %u MHz succeeded\n", (speedstep_get_processor_frequency(speedstep_processor) / 1000));
-	} else {
-		printk (KERN_ERR "cpufreq: change failed - I/O error\n");
-	}
+	if (state == (value & 0x1))
+		dprintk("change to %u MHz succeeded\n",
+			speedstep_get_frequency(speedstep_processor) / 1000);
+	else
+		printk(KERN_ERR "cpufreq: change failed - I/O error\n");
 
 	return;
 }
@@ -149,7 +150,7 @@
  *   Tries to activate the SpeedStep status and control registers.
  * Returns -EINVAL on an unsupported chipset, and zero on success.
  */
-static int speedstep_activate (void)
+static int speedstep_activate(void)
 {
 	u16 value = 0;
 
@@ -175,20 +176,18 @@
  * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected
  * chipset, or zero on failure.
  */
-static unsigned int speedstep_detect_chipset (void)
+static unsigned int speedstep_detect_chipset(void)
 {
 	speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82801DB_12,
-			      PCI_ANY_ID,
-			      PCI_ANY_ID,
+			      PCI_ANY_ID, PCI_ANY_ID,
 			      NULL);
 	if (speedstep_chipset_dev)
 		return 4; /* 4-M */
 
 	speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82801CA_12,
-			      PCI_ANY_ID,
-			      PCI_ANY_ID,
+			      PCI_ANY_ID, PCI_ANY_ID,
 			      NULL);
 	if (speedstep_chipset_dev)
 		return 3; /* 3-M */
@@ -196,8 +195,7 @@
 
 	speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82801BA_10,
-			      PCI_ANY_ID,
-			      PCI_ANY_ID,
+			      PCI_ANY_ID, PCI_ANY_ID,
 			      NULL);
 	if (speedstep_chipset_dev) {
 		/* speedstep.c causes lockups on Dell Inspirons 8000 and
@@ -208,8 +206,7 @@
 
 		hostbridge  = pci_get_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82815_MC,
-			      PCI_ANY_ID,
-			      PCI_ANY_ID,
+			      PCI_ANY_ID, PCI_ANY_ID,
 			      NULL);
 
 		if (!hostbridge)
@@ -236,7 +233,7 @@
 
 	cpus_allowed = current->cpus_allowed;
 	set_cpus_allowed_ptr(current, cpus);
-	speed = speedstep_get_processor_frequency(speedstep_processor);
+	speed = speedstep_get_frequency(speedstep_processor);
 	set_cpus_allowed_ptr(current, &cpus_allowed);
 	dprintk("detected %u kHz as current frequency\n", speed);
 	return speed;
@@ -251,11 +248,12 @@
  * speedstep_target - set a new CPUFreq policy
  * @policy: new policy
  * @target_freq: the target frequency
- * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
+ * @relation: how that frequency relates to achieved frequency
+ *	(CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
  *
  * Sets a new CPUFreq policy.
  */
-static int speedstep_target (struct cpufreq_policy *policy,
+static int speedstep_target(struct cpufreq_policy *policy,
 			     unsigned int target_freq,
 			     unsigned int relation)
 {
@@ -264,7 +262,8 @@
 	cpumask_t cpus_allowed;
 	int i;
 
-	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
+	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0],
+				target_freq, relation, &newstate))
 		return -EINVAL;
 
 	freqs.old = _speedstep_get(policy->cpus);
@@ -308,7 +307,7 @@
  * Limit must be within speedstep_low_freq and speedstep_high_freq, with
  * at least one border included.
  */
-static int speedstep_verify (struct cpufreq_policy *policy)
+static int speedstep_verify(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
 }
@@ -344,7 +343,8 @@
 		return -EIO;
 
 	dprintk("currently at %s speed setting - %i MHz\n",
-		(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high",
+		(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency)
+		? "low" : "high",
 		(speed / 1000));
 
 	/* cpuinfo and default policy values */
@@ -352,9 +352,9 @@
 
 	result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
 	if (result)
-		return (result);
+		return result;
 
-        cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
+	cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
 
 	return 0;
 }
@@ -366,7 +366,7 @@
 	return 0;
 }
 
-static struct freq_attr* speedstep_attr[] = {
+static struct freq_attr *speedstep_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
 };
@@ -396,13 +396,15 @@
 	/* detect processor */
 	speedstep_processor = speedstep_detect_processor();
 	if (!speedstep_processor) {
-		dprintk("Intel(R) SpeedStep(TM) capable processor not found\n");
+		dprintk("Intel(R) SpeedStep(TM) capable processor "
+				"not found\n");
 		return -ENODEV;
 	}
 
 	/* detect chipset */
 	if (!speedstep_detect_chipset()) {
-		dprintk("Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n");
+		dprintk("Intel(R) SpeedStep(TM) for this chipset not "
+				"(yet) available.\n");
 		return -ENODEV;
 	}
 
@@ -431,9 +433,11 @@
 }
 
 
-MODULE_AUTHOR ("Dave Jones <davej@redhat.com>, Dominik Brodowski <linux@brodo.de>");
-MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors on chipsets with ICH-M southbridges.");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>, "
+		"Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION("Speedstep driver for Intel mobile processors on chipsets "
+		"with ICH-M southbridges.");
+MODULE_LICENSE("GPL");
 
 module_init(speedstep_init);
 module_exit(speedstep_exit);
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
index cdac7d6..2e3c686 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
@@ -16,12 +16,16 @@
 #include <linux/slab.h>
 
 #include <asm/msr.h>
+#include <asm/tsc.h>
 #include "speedstep-lib.h"
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-lib", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"speedstep-lib", msg)
+
+#define PFX "speedstep-lib: "
 
 #ifdef CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK
-static int relaxed_check = 0;
+static int relaxed_check;
 #else
 #define relaxed_check 0
 #endif
@@ -30,14 +34,14 @@
  *                   GET PROCESSOR CORE SPEED IN KHZ                 *
  *********************************************************************/
 
-static unsigned int pentium3_get_frequency (unsigned int processor)
+static unsigned int pentium3_get_frequency(unsigned int processor)
 {
-        /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */
+	/* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */
 	struct {
 		unsigned int ratio;	/* Frequency Multiplier (x10) */
 		u8 bitmap;		/* power on configuration bits
 					[27, 25:22] (in MSR 0x2a) */
-	} msr_decode_mult [] = {
+	} msr_decode_mult[] = {
 		{ 30, 0x01 },
 		{ 35, 0x05 },
 		{ 40, 0x02 },
@@ -52,7 +56,7 @@
 		{ 85, 0x26 },
 		{ 90, 0x20 },
 		{ 100, 0x2b },
-		{ 0, 0xff }     /* error or unknown value */
+		{ 0, 0xff }	/* error or unknown value */
 	};
 
 	/* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */
@@ -60,7 +64,7 @@
 		unsigned int value;	/* Front Side Bus speed in MHz */
 		u8 bitmap;		/* power on configuration bits [18: 19]
 					(in MSR 0x2a) */
-	} msr_decode_fsb [] = {
+	} msr_decode_fsb[] = {
 		{  66, 0x0 },
 		{ 100, 0x2 },
 		{ 133, 0x1 },
@@ -85,7 +89,7 @@
 	}
 
 	/* decode the multiplier */
-	if (processor == SPEEDSTEP_PROCESSOR_PIII_C_EARLY) {
+	if (processor == SPEEDSTEP_CPU_PIII_C_EARLY) {
 		dprintk("workaround for early PIIIs\n");
 		msr_lo &= 0x03c00000;
 	} else
@@ -97,9 +101,10 @@
 		j++;
 	}
 
-	dprintk("speed is %u\n", (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100));
+	dprintk("speed is %u\n",
+		(msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100));
 
-	return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100);
+	return msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100;
 }
 
 
@@ -112,20 +117,23 @@
 
 	/* see table B-2 of 24547212.pdf */
 	if (msr_lo & 0x00040000) {
-		printk(KERN_DEBUG "speedstep-lib: PM - invalid FSB: 0x%x 0x%x\n", msr_lo, msr_tmp);
+		printk(KERN_DEBUG PFX "PM - invalid FSB: 0x%x 0x%x\n",
+				msr_lo, msr_tmp);
 		return 0;
 	}
 
 	msr_tmp = (msr_lo >> 22) & 0x1f;
-	dprintk("bits 22-26 are 0x%x, speed is %u\n", msr_tmp, (msr_tmp * 100 * 1000));
+	dprintk("bits 22-26 are 0x%x, speed is %u\n",
+			msr_tmp, (msr_tmp * 100 * 1000));
 
-	return (msr_tmp * 100 * 1000);
+	return msr_tmp * 100 * 1000;
 }
 
 static unsigned int pentium_core_get_frequency(void)
 {
 	u32 fsb = 0;
 	u32 msr_lo, msr_tmp;
+	int ret;
 
 	rdmsr(MSR_FSB_FREQ, msr_lo, msr_tmp);
 	/* see table B-2 of 25366920.pdf */
@@ -153,12 +161,15 @@
 	}
 
 	rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
-	dprintk("PCORE - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
+	dprintk("PCORE - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n",
+			msr_lo, msr_tmp);
 
 	msr_tmp = (msr_lo >> 22) & 0x1f;
-	dprintk("bits 22-26 are 0x%x, speed is %u\n", msr_tmp, (msr_tmp * fsb));
+	dprintk("bits 22-26 are 0x%x, speed is %u\n",
+			msr_tmp, (msr_tmp * fsb));
 
-	return (msr_tmp * fsb);
+	ret = (msr_tmp * fsb);
+	return ret;
 }
 
 
@@ -167,6 +178,16 @@
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 	u32 msr_lo, msr_hi, mult;
 	unsigned int fsb = 0;
+	unsigned int ret;
+	u8 fsb_code;
+
+	/* Pentium 4 Model 0 and 1 do not have the Core Clock Frequency
+	 * to System Bus Frequency Ratio Field in the Processor Frequency
+	 * Configuration Register of the MSR. Therefore the current
+	 * frequency cannot be calculated and has to be measured.
+	 */
+	if (c->x86_model < 2)
+		return cpu_khz;
 
 	rdmsr(0x2c, msr_lo, msr_hi);
 
@@ -177,62 +198,61 @@
 	 * revision #12 in Table B-1: MSRs in the Pentium 4 and
 	 * Intel Xeon Processors, on page B-4 and B-5.
 	 */
-	if (c->x86_model < 2)
+	fsb_code = (msr_lo >> 16) & 0x7;
+	switch (fsb_code) {
+	case 0:
 		fsb = 100 * 1000;
-	else {
-		u8 fsb_code = (msr_lo >> 16) & 0x7;
-		switch (fsb_code) {
-		case 0:
-			fsb = 100 * 1000;
-			break;
-		case 1:
-			fsb = 13333 * 10;
-			break;
-		case 2:
-			fsb = 200 * 1000;
-			break;
-		}
+		break;
+	case 1:
+		fsb = 13333 * 10;
+		break;
+	case 2:
+		fsb = 200 * 1000;
+		break;
 	}
 
 	if (!fsb)
-		printk(KERN_DEBUG "speedstep-lib: couldn't detect FSB speed. Please send an e-mail to <linux@brodo.de>\n");
+		printk(KERN_DEBUG PFX "couldn't detect FSB speed. "
+				"Please send an e-mail to <linux@brodo.de>\n");
 
 	/* Multiplier. */
 	mult = msr_lo >> 24;
 
-	dprintk("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n", fsb, mult, (fsb * mult));
+	dprintk("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n",
+			fsb, mult, (fsb * mult));
 
-	return (fsb * mult);
+	ret = (fsb * mult);
+	return ret;
 }
 
 
-unsigned int speedstep_get_processor_frequency(unsigned int processor)
+unsigned int speedstep_get_frequency(unsigned int processor)
 {
 	switch (processor) {
-	case SPEEDSTEP_PROCESSOR_PCORE:
+	case SPEEDSTEP_CPU_PCORE:
 		return pentium_core_get_frequency();
-	case SPEEDSTEP_PROCESSOR_PM:
+	case SPEEDSTEP_CPU_PM:
 		return pentiumM_get_frequency();
-	case SPEEDSTEP_PROCESSOR_P4D:
-	case SPEEDSTEP_PROCESSOR_P4M:
+	case SPEEDSTEP_CPU_P4D:
+	case SPEEDSTEP_CPU_P4M:
 		return pentium4_get_frequency();
-	case SPEEDSTEP_PROCESSOR_PIII_T:
-	case SPEEDSTEP_PROCESSOR_PIII_C:
-	case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
+	case SPEEDSTEP_CPU_PIII_T:
+	case SPEEDSTEP_CPU_PIII_C:
+	case SPEEDSTEP_CPU_PIII_C_EARLY:
 		return pentium3_get_frequency(processor);
 	default:
 		return 0;
 	};
 	return 0;
 }
-EXPORT_SYMBOL_GPL(speedstep_get_processor_frequency);
+EXPORT_SYMBOL_GPL(speedstep_get_frequency);
 
 
 /*********************************************************************
  *                 DETECT SPEEDSTEP-CAPABLE PROCESSOR                *
  *********************************************************************/
 
-unsigned int speedstep_detect_processor (void)
+unsigned int speedstep_detect_processor(void)
 {
 	struct cpuinfo_x86 *c = &cpu_data(0);
 	u32 ebx, msr_lo, msr_hi;
@@ -261,7 +281,7 @@
 			 * sample has ebx = 0x0f, production has 0x0e.
 			 */
 			if ((ebx == 0x0e) || (ebx == 0x0f))
-				return SPEEDSTEP_PROCESSOR_P4M;
+				return SPEEDSTEP_CPU_P4M;
 			break;
 		case 7:
 			/*
@@ -272,7 +292,7 @@
 			 * samples are only of B-stepping...
 			 */
 			if (ebx == 0x0e)
-				return SPEEDSTEP_PROCESSOR_P4M;
+				return SPEEDSTEP_CPU_P4M;
 			break;
 		case 9:
 			/*
@@ -288,10 +308,13 @@
 			 * M-P4-Ms may have either ebx=0xe or 0xf [see above]
 			 * M-P4/533 have either ebx=0xe or 0xf. [25317607.pdf]
 			 * also, M-P4M HTs have ebx=0x8, too
-			 * For now, they are distinguished by the model_id string
+			 * For now, they are distinguished by the model_id
+			 * string
 			 */
-			if ((ebx == 0x0e) || (strstr(c->x86_model_id,"Mobile Intel(R) Pentium(R) 4") != NULL))
-				return SPEEDSTEP_PROCESSOR_P4M;
+			if ((ebx == 0x0e) ||
+				(strstr(c->x86_model_id,
+				    "Mobile Intel(R) Pentium(R) 4") != NULL))
+				return SPEEDSTEP_CPU_P4M;
 			break;
 		default:
 			break;
@@ -301,7 +324,8 @@
 
 	switch (c->x86_model) {
 	case 0x0B: /* Intel PIII [Tualatin] */
-		/* cpuid_ebx(1) is 0x04 for desktop PIII, 0x06 for mobile PIII-M */
+		/* cpuid_ebx(1) is 0x04 for desktop PIII,
+		 * 0x06 for mobile PIII-M */
 		ebx = cpuid_ebx(0x00000001);
 		dprintk("ebx is %x\n", ebx);
 
@@ -313,14 +337,15 @@
 		/* So far all PIII-M processors support SpeedStep. See
 		 * Intel's 24540640.pdf of June 2003
 		 */
-		return SPEEDSTEP_PROCESSOR_PIII_T;
+		return SPEEDSTEP_CPU_PIII_T;
 
 	case 0x08: /* Intel PIII [Coppermine] */
 
 		/* all mobile PIII Coppermines have FSB 100 MHz
 		 * ==> sort out a few desktop PIIIs. */
 		rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi);
-		dprintk("Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi);
+		dprintk("Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n",
+				msr_lo, msr_hi);
 		msr_lo &= 0x00c0000;
 		if (msr_lo != 0x0080000)
 			return 0;
@@ -332,13 +357,15 @@
 		 * bit 56 or 57 is set
 		 */
 		rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi);
-		dprintk("Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi);
-		if ((msr_hi & (1<<18)) && (relaxed_check ? 1 : (msr_hi & (3<<24)))) {
+		dprintk("Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n",
+				msr_lo, msr_hi);
+		if ((msr_hi & (1<<18)) &&
+		    (relaxed_check ? 1 : (msr_hi & (3<<24)))) {
 			if (c->x86_mask == 0x01) {
 				dprintk("early PIII version\n");
-				return SPEEDSTEP_PROCESSOR_PIII_C_EARLY;
+				return SPEEDSTEP_CPU_PIII_C_EARLY;
 			} else
-				return SPEEDSTEP_PROCESSOR_PIII_C;
+				return SPEEDSTEP_CPU_PIII_C;
 		}
 
 	default:
@@ -369,7 +396,7 @@
 	dprintk("trying to determine both speeds\n");
 
 	/* get current speed */
-	prev_speed = speedstep_get_processor_frequency(processor);
+	prev_speed = speedstep_get_frequency(processor);
 	if (!prev_speed)
 		return -EIO;
 
@@ -379,7 +406,7 @@
 
 	/* switch to low state */
 	set_state(SPEEDSTEP_LOW);
-	*low_speed = speedstep_get_processor_frequency(processor);
+	*low_speed = speedstep_get_frequency(processor);
 	if (!*low_speed) {
 		ret = -EIO;
 		goto out;
@@ -398,7 +425,7 @@
 	if (transition_latency)
 		do_gettimeofday(&tv2);
 
-	*high_speed = speedstep_get_processor_frequency(processor);
+	*high_speed = speedstep_get_frequency(processor);
 	if (!*high_speed) {
 		ret = -EIO;
 		goto out;
@@ -426,9 +453,12 @@
 		/* check if the latency measurement is too high or too low
 		 * and set it to a safe value (500uSec) in that case
 		 */
-		if (*transition_latency > 10000000 || *transition_latency < 50000) {
-			printk (KERN_WARNING "speedstep: frequency transition measured seems out of "
-					"range (%u nSec), falling back to a safe one of %u nSec.\n",
+		if (*transition_latency > 10000000 ||
+		    *transition_latency < 50000) {
+			printk(KERN_WARNING PFX "frequency transition "
+					"measured seems out of range (%u "
+					"nSec), falling back to a safe one of"
+					"%u nSec.\n",
 					*transition_latency, 500000);
 			*transition_latency = 500000;
 		}
@@ -436,15 +466,16 @@
 
 out:
 	local_irq_restore(flags);
-	return (ret);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(speedstep_get_freqs);
 
 #ifdef CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK
 module_param(relaxed_check, int, 0444);
-MODULE_PARM_DESC(relaxed_check, "Don't do all checks for speedstep capability.");
+MODULE_PARM_DESC(relaxed_check,
+		"Don't do all checks for speedstep capability.");
 #endif
 
-MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
-MODULE_DESCRIPTION ("Library for Intel SpeedStep 1 or 2 cpufreq drivers.");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION("Library for Intel SpeedStep 1 or 2 cpufreq drivers.");
+MODULE_LICENSE("GPL");
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.h b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.h
index b11bcc6..2b6c04e 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.h
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.h
@@ -12,17 +12,17 @@
 
 /* processors */
 
-#define SPEEDSTEP_PROCESSOR_PIII_C_EARLY	0x00000001  /* Coppermine core */
-#define SPEEDSTEP_PROCESSOR_PIII_C		0x00000002  /* Coppermine core */
-#define SPEEDSTEP_PROCESSOR_PIII_T		0x00000003  /* Tualatin core */
-#define SPEEDSTEP_PROCESSOR_P4M			0x00000004  /* P4-M  */
+#define SPEEDSTEP_CPU_PIII_C_EARLY	0x00000001  /* Coppermine core */
+#define SPEEDSTEP_CPU_PIII_C		0x00000002  /* Coppermine core */
+#define SPEEDSTEP_CPU_PIII_T		0x00000003  /* Tualatin core */
+#define SPEEDSTEP_CPU_P4M		0x00000004  /* P4-M  */
 
 /* the following processors are not speedstep-capable and are not auto-detected
  * in speedstep_detect_processor(). However, their speed can be detected using
- * the speedstep_get_processor_frequency() call. */
-#define SPEEDSTEP_PROCESSOR_PM			0xFFFFFF03  /* Pentium M  */
-#define SPEEDSTEP_PROCESSOR_P4D			0xFFFFFF04  /* desktop P4  */
-#define SPEEDSTEP_PROCESSOR_PCORE		0xFFFFFF05  /* Core */
+ * the speedstep_get_frequency() call. */
+#define SPEEDSTEP_CPU_PM		0xFFFFFF03  /* Pentium M  */
+#define SPEEDSTEP_CPU_P4D		0xFFFFFF04  /* desktop P4  */
+#define SPEEDSTEP_CPU_PCORE		0xFFFFFF05  /* Core */
 
 /* speedstep states -- only two of them */
 
@@ -34,7 +34,7 @@
 extern unsigned int speedstep_detect_processor (void);
 
 /* detect the current speed (in khz) of the processor */
-extern unsigned int speedstep_get_processor_frequency(unsigned int processor);
+extern unsigned int speedstep_get_frequency(unsigned int processor);
 
 
 /* detect the low and high speeds of the processor. The callback
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
index 8a85c93..befea08 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
@@ -19,8 +19,8 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <asm/ist.h>
-#include <asm/io.h>
 
 #include "speedstep-lib.h"
 
@@ -30,12 +30,12 @@
  * If user gives it, these are used.
  *
  */
-static int smi_port = 0;
-static int smi_cmd = 0;
-static unsigned int smi_sig = 0;
+static int smi_port;
+static int smi_cmd;
+static unsigned int smi_sig;
 
 /* info about the processor */
-static unsigned int speedstep_processor = 0;
+static unsigned int speedstep_processor;
 
 /*
  * There are only two frequency states for each processor. Values
@@ -56,12 +56,13 @@
  * of DMA activity going on? */
 #define SMI_TRIES 5
 
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-smi", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+		"speedstep-smi", msg)
 
 /**
  * speedstep_smi_ownership
  */
-static int speedstep_smi_ownership (void)
+static int speedstep_smi_ownership(void)
 {
 	u32 command, result, magic, dummy;
 	u32 function = GET_SPEEDSTEP_OWNER;
@@ -70,16 +71,18 @@
 	command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
 	magic = virt_to_phys(magic_data);
 
-	dprintk("trying to obtain ownership with command %x at port %x\n", command, smi_port);
+	dprintk("trying to obtain ownership with command %x at port %x\n",
+			command, smi_port);
 
 	__asm__ __volatile__(
 		"push %%ebp\n"
 		"out %%al, (%%dx)\n"
 		"pop %%ebp\n"
-		: "=D" (result), "=a" (dummy), "=b" (dummy), "=c" (dummy), "=d" (dummy),
-			"=S" (dummy)
+		: "=D" (result),
+		  "=a" (dummy), "=b" (dummy), "=c" (dummy), "=d" (dummy),
+		  "=S" (dummy)
 		: "a" (command), "b" (function), "c" (0), "d" (smi_port),
-			"D" (0), "S" (magic)
+		  "D" (0), "S" (magic)
 		: "memory"
 	);
 
@@ -97,10 +100,10 @@
  * even hangs [cf. bugme.osdl.org # 1422] on earlier systems. Empirical testing
  * shows that the latter occurs if !(ist_info.event & 0xFFFF).
  */
-static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
+static int speedstep_smi_get_freqs(unsigned int *low, unsigned int *high)
 {
 	u32 command, result = 0, edi, high_mhz, low_mhz, dummy;
-	u32 state=0;
+	u32 state = 0;
 	u32 function = GET_SPEEDSTEP_FREQS;
 
 	if (!(ist_info.event & 0xFFFF)) {
@@ -110,17 +113,25 @@
 
 	command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
 
-	dprintk("trying to determine frequencies with command %x at port %x\n", command, smi_port);
+	dprintk("trying to determine frequencies with command %x at port %x\n",
+			command, smi_port);
 
 	__asm__ __volatile__(
 		"push %%ebp\n"
 		"out %%al, (%%dx)\n"
 		"pop %%ebp"
-		: "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi), "=S" (dummy)
-		: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0)
+		: "=a" (result),
+		  "=b" (high_mhz),
+		  "=c" (low_mhz),
+		  "=d" (state), "=D" (edi), "=S" (dummy)
+		: "a" (command),
+		  "b" (function),
+		  "c" (state),
+		  "d" (smi_port), "S" (0), "D" (0)
 	);
 
-	dprintk("result %x, low_freq %u, high_freq %u\n", result, low_mhz, high_mhz);
+	dprintk("result %x, low_freq %u, high_freq %u\n",
+			result, low_mhz, high_mhz);
 
 	/* abort if results are obviously incorrect... */
 	if ((high_mhz + low_mhz) < 600)
@@ -137,26 +148,30 @@
  * @state: processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
  *
  */
-static int speedstep_get_state (void)
+static int speedstep_get_state(void)
 {
-	u32 function=GET_SPEEDSTEP_STATE;
+	u32 function = GET_SPEEDSTEP_STATE;
 	u32 result, state, edi, command, dummy;
 
 	command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
 
-	dprintk("trying to determine current setting with command %x at port %x\n", command, smi_port);
+	dprintk("trying to determine current setting with command %x "
+		"at port %x\n", command, smi_port);
 
 	__asm__ __volatile__(
 		"push %%ebp\n"
 		"out %%al, (%%dx)\n"
 		"pop %%ebp\n"
-		: "=a" (result), "=b" (state), "=D" (edi), "=c" (dummy), "=d" (dummy), "=S" (dummy)
-		: "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0), "D" (0)
+		: "=a" (result),
+		  "=b" (state), "=D" (edi),
+		  "=c" (dummy), "=d" (dummy), "=S" (dummy)
+		: "a" (command), "b" (function), "c" (0),
+		  "d" (smi_port), "S" (0), "D" (0)
 	);
 
 	dprintk("state is %x, result is %x\n", state, result);
 
-	return (state & 1);
+	return state & 1;
 }
 
 
@@ -165,11 +180,11 @@
  * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
  *
  */
-static void speedstep_set_state (unsigned int state)
+static void speedstep_set_state(unsigned int state)
 {
 	unsigned int result = 0, command, new_state, dummy;
 	unsigned long flags;
-	unsigned int function=SET_SPEEDSTEP_STATE;
+	unsigned int function = SET_SPEEDSTEP_STATE;
 	unsigned int retry = 0;
 
 	if (state > 0x1)
@@ -180,11 +195,14 @@
 
 	command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
 
-	dprintk("trying to set frequency to state %u with command %x at port %x\n", state, command, smi_port);
+	dprintk("trying to set frequency to state %u "
+		"with command %x at port %x\n",
+		state, command, smi_port);
 
 	do {
 		if (retry) {
-			dprintk("retry %u, previous result %u, waiting...\n", retry, result);
+			dprintk("retry %u, previous result %u, waiting...\n",
+					retry, result);
 			mdelay(retry * 50);
 		}
 		retry++;
@@ -192,20 +210,26 @@
 			"push %%ebp\n"
 			"out %%al, (%%dx)\n"
 			"pop %%ebp"
-			: "=b" (new_state), "=D" (result), "=c" (dummy), "=a" (dummy),
-				"=d" (dummy), "=S" (dummy)
-			: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0)
+			: "=b" (new_state), "=D" (result),
+			  "=c" (dummy), "=a" (dummy),
+			  "=d" (dummy), "=S" (dummy)
+			: "a" (command), "b" (function), "c" (state),
+			  "d" (smi_port), "S" (0), "D" (0)
 			);
 	} while ((new_state != state) && (retry <= SMI_TRIES));
 
 	/* enable IRQs */
 	local_irq_restore(flags);
 
-	if (new_state == state) {
-		dprintk("change to %u MHz succeeded after %u tries with result %u\n", (speedstep_freqs[new_state].frequency / 1000), retry, result);
-	} else {
-		printk(KERN_ERR "cpufreq: change to state %u failed with new_state %u and result %u\n", state, new_state, result);
-	}
+	if (new_state == state)
+		dprintk("change to %u MHz succeeded after %u tries "
+			"with result %u\n",
+			(speedstep_freqs[new_state].frequency / 1000),
+			retry, result);
+	else
+		printk(KERN_ERR "cpufreq: change to state %u "
+			"failed with new_state %u and result %u\n",
+			state, new_state, result);
 
 	return;
 }
@@ -219,13 +243,14 @@
  *
  * Sets a new CPUFreq policy/freq.
  */
-static int speedstep_target (struct cpufreq_policy *policy,
+static int speedstep_target(struct cpufreq_policy *policy,
 			unsigned int target_freq, unsigned int relation)
 {
 	unsigned int newstate = 0;
 	struct cpufreq_freqs freqs;
 
-	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
+	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0],
+				target_freq, relation, &newstate))
 		return -EINVAL;
 
 	freqs.old = speedstep_freqs[speedstep_get_state()].frequency;
@@ -250,7 +275,7 @@
  * Limit must be within speedstep_low_freq and speedstep_high_freq, with
  * at least one border included.
  */
-static int speedstep_verify (struct cpufreq_policy *policy)
+static int speedstep_verify(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
 }
@@ -259,7 +284,8 @@
 static int speedstep_cpu_init(struct cpufreq_policy *policy)
 {
 	int result;
-	unsigned int speed,state;
+	unsigned int speed, state;
+	unsigned int *low, *high;
 
 	/* capability check */
 	if (policy->cpu != 0)
@@ -272,19 +298,23 @@
 	}
 
 	/* detect low and high frequency */
-	result = speedstep_smi_get_freqs(&speedstep_freqs[SPEEDSTEP_LOW].frequency,
-				&speedstep_freqs[SPEEDSTEP_HIGH].frequency);
+	low = &speedstep_freqs[SPEEDSTEP_LOW].frequency;
+	high = &speedstep_freqs[SPEEDSTEP_HIGH].frequency;
+
+	result = speedstep_smi_get_freqs(low, high);
 	if (result) {
-		/* fall back to speedstep_lib.c dection mechanism: try both states out */
-		dprintk("could not detect low and high frequencies by SMI call.\n");
+		/* fall back to speedstep_lib.c dection mechanism:
+		 * try both states out */
+		dprintk("could not detect low and high frequencies "
+				"by SMI call.\n");
 		result = speedstep_get_freqs(speedstep_processor,
-				&speedstep_freqs[SPEEDSTEP_LOW].frequency,
-				&speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+				low, high,
 				NULL,
 				&speedstep_set_state);
 
 		if (result) {
-			dprintk("could not detect two different speeds -- aborting.\n");
+			dprintk("could not detect two different speeds"
+					" -- aborting.\n");
 			return result;
 		} else
 			dprintk("workaround worked.\n");
@@ -295,7 +325,8 @@
 	speed = speedstep_freqs[state].frequency;
 
 	dprintk("currently at %s speed setting - %i MHz\n",
-		(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high",
+		(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency)
+		? "low" : "high",
 		(speed / 1000));
 
 	/* cpuinfo and default policy values */
@@ -304,7 +335,7 @@
 
 	result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
 	if (result)
-		return (result);
+		return result;
 
 	cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
 
@@ -321,7 +352,7 @@
 {
 	if (cpu)
 		return -ENODEV;
-	return speedstep_get_processor_frequency(speedstep_processor);
+	return speedstep_get_frequency(speedstep_processor);
 }
 
 
@@ -335,7 +366,7 @@
 	return result;
 }
 
-static struct freq_attr* speedstep_attr[] = {
+static struct freq_attr *speedstep_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
 };
@@ -364,21 +395,23 @@
 	speedstep_processor = speedstep_detect_processor();
 
 	switch (speedstep_processor) {
-	case SPEEDSTEP_PROCESSOR_PIII_T:
-	case SPEEDSTEP_PROCESSOR_PIII_C:
-	case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
+	case SPEEDSTEP_CPU_PIII_T:
+	case SPEEDSTEP_CPU_PIII_C:
+	case SPEEDSTEP_CPU_PIII_C_EARLY:
 		break;
 	default:
 		speedstep_processor = 0;
 	}
 
 	if (!speedstep_processor) {
-		dprintk ("No supported Intel CPU detected.\n");
+		dprintk("No supported Intel CPU detected.\n");
 		return -ENODEV;
 	}
 
-	dprintk("signature:0x%.8lx, command:0x%.8lx, event:0x%.8lx, perf_level:0x%.8lx.\n",
-		ist_info.signature, ist_info.command, ist_info.event, ist_info.perf_level);
+	dprintk("signature:0x%.8lx, command:0x%.8lx, "
+		"event:0x%.8lx, perf_level:0x%.8lx.\n",
+		ist_info.signature, ist_info.command,
+		ist_info.event, ist_info.perf_level);
 
 	/* Error if no IST-SMI BIOS or no PARM
 		 sig= 'ISGE' aka 'Intel Speedstep Gate E' */
@@ -416,17 +449,20 @@
 	cpufreq_unregister_driver(&speedstep_driver);
 }
 
-module_param(smi_port,  int, 0444);
-module_param(smi_cmd,   int, 0444);
-module_param(smi_sig,  uint, 0444);
+module_param(smi_port, int, 0444);
+module_param(smi_cmd,  int, 0444);
+module_param(smi_sig, uint, 0444);
 
-MODULE_PARM_DESC(smi_port, "Override the BIOS-given IST port with this value -- Intel's default setting is 0xb2");
-MODULE_PARM_DESC(smi_cmd, "Override the BIOS-given IST command with this value -- Intel's default setting is 0x82");
-MODULE_PARM_DESC(smi_sig, "Set to 1 to fake the IST signature when using the SMI interface.");
+MODULE_PARM_DESC(smi_port, "Override the BIOS-given IST port with this value "
+		"-- Intel's default setting is 0xb2");
+MODULE_PARM_DESC(smi_cmd, "Override the BIOS-given IST command with this value "
+		"-- Intel's default setting is 0x82");
+MODULE_PARM_DESC(smi_sig, "Set to 1 to fake the IST signature when using the "
+		"SMI interface.");
 
-MODULE_AUTHOR ("Hiroshi Miura");
-MODULE_DESCRIPTION ("Speedstep driver for IST applet SMI interface.");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Hiroshi Miura");
+MODULE_DESCRIPTION("Speedstep driver for IST applet SMI interface.");
+MODULE_LICENSE("GPL");
 
 module_init(speedstep_init);
 module_exit(speedstep_exit);
diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
index 169a120..87b67e3 100644
--- a/arch/x86/kernel/ds.c
+++ b/arch/x86/kernel/ds.c
@@ -729,7 +729,7 @@
 
 	spin_unlock_irqrestore(&ds_lock, irq);
 
-	ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_bts);
+	ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_pebs);
 	ds_resume_pebs(tracer);
 
 	return tracer;
@@ -1029,5 +1029,4 @@
 
 void ds_exit_thread(struct task_struct *tsk)
 {
-	WARN_ON(tsk->thread.ds_ctx);
 }
diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c
index 1119d24..eb1ef3b 100644
--- a/arch/x86/kernel/efi.c
+++ b/arch/x86/kernel/efi.c
@@ -467,7 +467,7 @@
 	efi_memory_desc_t *md;
 	efi_status_t status;
 	unsigned long size;
-	u64 end, systab, addr, npages;
+	u64 end, systab, addr, npages, end_pfn;
 	void *p, *va;
 
 	efi.systab = NULL;
@@ -479,7 +479,10 @@
 		size = md->num_pages << EFI_PAGE_SHIFT;
 		end = md->phys_addr + size;
 
-		if (PFN_UP(end) <= max_low_pfn_mapped)
+		end_pfn = PFN_UP(end);
+		if (end_pfn <= max_low_pfn_mapped
+		    || (end_pfn > (1UL << (32 - PAGE_SHIFT))
+			&& end_pfn <= max_pfn_mapped))
 			va = __va(md->phys_addr);
 		else
 			va = efi_ioremap(md->phys_addr, size);
diff --git a/arch/x86/kernel/efi_64.c b/arch/x86/kernel/efi_64.c
index 652c528..cb783b9 100644
--- a/arch/x86/kernel/efi_64.c
+++ b/arch/x86/kernel/efi_64.c
@@ -99,24 +99,11 @@
 
 void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size)
 {
-	static unsigned pages_mapped __initdata;
-	unsigned i, pages;
-	unsigned long offset;
+	unsigned long last_map_pfn;
 
-	pages = PFN_UP(phys_addr + size) - PFN_DOWN(phys_addr);
-	offset = phys_addr & ~PAGE_MASK;
-	phys_addr &= PAGE_MASK;
-
-	if (pages_mapped + pages > MAX_EFI_IO_PAGES)
+	last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);
+	if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size)
 		return NULL;
 
-	for (i = 0; i < pages; i++) {
-		__set_fixmap(FIX_EFI_IO_MAP_FIRST_PAGE - pages_mapped,
-			     phys_addr, PAGE_KERNEL);
-		phys_addr += PAGE_SIZE;
-		pages_mapped++;
-	}
-
-	return (void __iomem *)__fix_to_virt(FIX_EFI_IO_MAP_FIRST_PAGE - \
-					     (pages_mapped - pages)) + offset;
+	return (void __iomem *)__va(phys_addr);
 }
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index b0f61f0..f2f8540 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -136,7 +136,7 @@
 #ifdef CONFIG_X86_32
 	if (!HAVE_HWFP) {
 		memset(tsk->thread.xstate, 0, xstate_size);
-		finit();
+		finit_task(tsk);
 		set_stopped_child_used_math(tsk);
 		return 0;
 	}
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index e948b28..4558dd3 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -193,6 +193,9 @@
 	kprobe_opcode_t opcode;
 	kprobe_opcode_t *orig_opcodes = opcodes;
 
+	if (search_exception_tables(opcodes))
+		return 0;	/* Page fault may occur on this address. */
+
 retry:
 	if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
 		return 0;
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 2b46eb4..4526b3a 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -217,6 +217,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
 		},
 	},
+	{	/* Handle problems with rebooting on Dell XPS710 */
+		.callback = set_bios_reboot,
+		.ident = "Dell XPS710",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"),
+		},
+	},
 	{ }
 };
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c461f6d..6a8811a 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -770,6 +770,9 @@
 
 	finish_e820_parsing();
 
+	if (efi_enabled)
+		efi_init();
+
 	dmi_scan_machine();
 
 	dmi_check_system(bad_bios_dmi_table);
@@ -789,8 +792,6 @@
 	insert_resource(&iomem_resource, &data_resource);
 	insert_resource(&iomem_resource, &bss_resource);
 
-	if (efi_enabled)
-		efi_init();
 
 #ifdef CONFIG_X86_32
 	if (ppro_with_ram_bug()) {
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 599e581..b8e7aaf 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -273,30 +273,43 @@
  * use the TSC value at the transitions to calculate a pretty
  * good value for the TSC frequencty.
  */
-static inline int pit_expect_msb(unsigned char val)
+static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap)
 {
-	int count = 0;
+	int count;
+	u64 tsc = 0;
 
 	for (count = 0; count < 50000; count++) {
 		/* Ignore LSB */
 		inb(0x42);
 		if (inb(0x42) != val)
 			break;
+		tsc = get_cycles();
 	}
-	return count > 50;
+	*deltap = get_cycles() - tsc;
+	*tscp = tsc;
+
+	/*
+	 * We require _some_ success, but the quality control
+	 * will be based on the error terms on the TSC values.
+	 */
+	return count > 5;
 }
 
 /*
- * How many MSB values do we want to see? We aim for a
- * 15ms calibration, which assuming a 2us counter read
- * error should give us roughly 150 ppm precision for
- * the calibration.
+ * How many MSB values do we want to see? We aim for
+ * a maximum error rate of 500ppm (in practice the
+ * real error is much smaller), but refuse to spend
+ * more than 25ms on it.
  */
-#define QUICK_PIT_MS 15
-#define QUICK_PIT_ITERATIONS (QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
+#define MAX_QUICK_PIT_MS 25
+#define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
 
 static unsigned long quick_pit_calibrate(void)
 {
+	int i;
+	u64 tsc, delta;
+	unsigned long d1, d2;
+
 	/* Set the Gate high, disable speaker */
 	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
 
@@ -315,45 +328,52 @@
 	outb(0xff, 0x42);
 	outb(0xff, 0x42);
 
-	if (pit_expect_msb(0xff)) {
-		int i;
-		u64 t1, t2, delta;
-		unsigned char expect = 0xfe;
+	/*
+	 * The PIT starts counting at the next edge, so we
+	 * need to delay for a microsecond. The easiest way
+	 * to do that is to just read back the 16-bit counter
+	 * once from the PIT.
+	 */
+	inb(0x42);
+	inb(0x42);
 
-		t1 = get_cycles();
-		for (i = 0; i < QUICK_PIT_ITERATIONS; i++, expect--) {
-			if (!pit_expect_msb(expect))
-				goto failed;
+	if (pit_expect_msb(0xff, &tsc, &d1)) {
+		for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) {
+			if (!pit_expect_msb(0xff-i, &delta, &d2))
+				break;
+
+			/*
+			 * Iterate until the error is less than 500 ppm
+			 */
+			delta -= tsc;
+			if (d1+d2 < delta >> 11)
+				goto success;
 		}
-		t2 = get_cycles();
-
-		/*
-		 * Make sure we can rely on the second TSC timestamp:
-		 */
-		if (!pit_expect_msb(expect))
-			goto failed;
-
-		/*
-		 * Ok, if we get here, then we've seen the
-		 * MSB of the PIT decrement QUICK_PIT_ITERATIONS
-		 * times, and each MSB had many hits, so we never
-		 * had any sudden jumps.
-		 *
-		 * As a result, we can depend on there not being
-		 * any odd delays anywhere, and the TSC reads are
-		 * reliable.
-		 *
-		 * kHz = ticks / time-in-seconds / 1000;
-		 * kHz = (t2 - t1) / (QPI * 256 / PIT_TICK_RATE) / 1000
-		 * kHz = ((t2 - t1) * PIT_TICK_RATE) / (QPI * 256 * 1000)
-		 */
-		delta = (t2 - t1)*PIT_TICK_RATE;
-		do_div(delta, QUICK_PIT_ITERATIONS*256*1000);
-		printk("Fast TSC calibration using PIT\n");
-		return delta;
 	}
-failed:
+	printk("Fast TSC calibration failed\n");
 	return 0;
+
+success:
+	/*
+	 * Ok, if we get here, then we've seen the
+	 * MSB of the PIT decrement 'i' times, and the
+	 * error has shrunk to less than 500 ppm.
+	 *
+	 * As a result, we can depend on there not being
+	 * any odd delays anywhere, and the TSC reads are
+	 * reliable (within the error). We also adjust the
+	 * delta to the middle of the error bars, just
+	 * because it looks nicer.
+	 *
+	 * kHz = ticks / time-in-seconds / 1000;
+	 * kHz = (t2 - t1) / (I * 256 / PIT_TICK_RATE) / 1000
+	 * kHz = ((t2 - t1) * PIT_TICK_RATE) / (I * 256 * 1000)
+	 */
+	delta += (long)(d2 - d1)/2;
+	delta *= PIT_TICK_RATE;
+	do_div(delta, i*256*1000);
+	printk("Fast TSC calibration using PIT\n");
+	return delta;
 }
 
 /**
@@ -523,8 +543,6 @@
 	return tsc_pit_min;
 }
 
-#ifdef CONFIG_X86_32
-/* Only called from the Powernow K7 cpu freq driver */
 int recalibrate_cpu_khz(void)
 {
 #ifndef CONFIG_SMP
@@ -546,7 +564,6 @@
 
 EXPORT_SYMBOL(recalibrate_cpu_khz);
 
-#endif /* CONFIG_X86_32 */
 
 /* Accelerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 92f1c6f..960a8d9 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -343,6 +343,11 @@
 		 * flush_tlb_user() for both user and kernel mappings unless
 		 * the Page Global Enable (PGE) feature bit is set. */
 		*dx |= 0x00002000;
+		/* We also lie, and say we're family id 5.  6 or greater
+		 * leads to a rdmsr in early_init_intel which we can't handle.
+		 * Family ID is returned as bits 8-12 in ax. */
+		*ax &= 0xFFFFF0FF;
+		*ax |= 0x00000500;
 		break;
 	case 0x80000000:
 		/* Futureproof this a little: if they ask how much extended
@@ -589,19 +594,21 @@
 		/* Some systems map "vectors" to interrupts weirdly.  Lguest has
 		 * a straightforward 1 to 1 mapping, so force that here. */
 		__get_cpu_var(vector_irq)[vector] = i;
-		if (vector != SYSCALL_VECTOR) {
-			set_intr_gate(vector,
-				      interrupt[vector-FIRST_EXTERNAL_VECTOR]);
-			set_irq_chip_and_handler_name(i, &lguest_irq_controller,
-						      handle_level_irq,
-						      "level");
-		}
+		if (vector != SYSCALL_VECTOR)
+			set_intr_gate(vector, interrupt[i]);
 	}
 	/* This call is required to set up for 4k stacks, where we have
 	 * separate stacks for hard and soft interrupts. */
 	irq_ctx_init(smp_processor_id());
 }
 
+void lguest_setup_irq(unsigned int irq)
+{
+	irq_to_desc_alloc_cpu(irq, 0);
+	set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
+				      handle_level_irq, "level");
+}
+
 /*
  * Time.
  *
diff --git a/arch/x86/math-emu/fpu_aux.c b/arch/x86/math-emu/fpu_aux.c
index 491e737..aa09870 100644
--- a/arch/x86/math-emu/fpu_aux.c
+++ b/arch/x86/math-emu/fpu_aux.c
@@ -30,20 +30,29 @@
 }
 
 /* Needs to be externally visible */
-void finit(void)
+void finit_task(struct task_struct *tsk)
 {
-	control_word = 0x037f;
-	partial_status = 0;
-	top = 0;		/* We don't keep top in the status word internally. */
-	fpu_tag_word = 0xffff;
+	struct i387_soft_struct *soft = &tsk->thread.xstate->soft;
+	struct address *oaddr, *iaddr;
+	soft->cwd = 0x037f;
+	soft->swd = 0;
+	soft->ftop = 0;	/* We don't keep top in the status word internally. */
+	soft->twd = 0xffff;
 	/* The behaviour is different from that detailed in
 	   Section 15.1.6 of the Intel manual */
-	operand_address.offset = 0;
-	operand_address.selector = 0;
-	instruction_address.offset = 0;
-	instruction_address.selector = 0;
-	instruction_address.opcode = 0;
-	no_ip_update = 1;
+	oaddr = (struct address *)&soft->foo;
+	oaddr->offset = 0;
+	oaddr->selector = 0;
+	iaddr = (struct address *)&soft->fip;
+	iaddr->offset = 0;
+	iaddr->selector = 0;
+	iaddr->opcode = 0;
+	soft->no_update = 1;
+}
+
+void finit(void)
+{
+	finit_task(current);
 }
 
 /*
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c
index 9f20503..6a518dd 100644
--- a/arch/x86/mm/kmmio.c
+++ b/arch/x86/mm/kmmio.c
@@ -451,23 +451,24 @@
 
 static void remove_kmmio_fault_pages(struct rcu_head *head)
 {
-	struct kmmio_delayed_release *dr = container_of(
-						head,
-						struct kmmio_delayed_release,
-						rcu);
+	struct kmmio_delayed_release *dr =
+		container_of(head, struct kmmio_delayed_release, rcu);
 	struct kmmio_fault_page *p = dr->release_list;
 	struct kmmio_fault_page **prevp = &dr->release_list;
 	unsigned long flags;
+
 	spin_lock_irqsave(&kmmio_lock, flags);
 	while (p) {
-		if (!p->count)
+		if (!p->count) {
 			list_del_rcu(&p->list);
-		else
+			prevp = &p->release_next;
+		} else {
 			*prevp = p->release_next;
-		prevp = &p->release_next;
+		}
 		p = p->release_next;
 	}
 	spin_unlock_irqrestore(&kmmio_lock, flags);
+
 	/* This is the real RCU destroy call. */
 	call_rcu(&dr->rcu, rcu_free_kmmio_fault_pages);
 }
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 7be47d1..7233bd7 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -515,6 +515,17 @@
 	 * primary protection behavior:
 	 */
 	__set_pmd_pte(kpte, address, mk_pte(base, __pgprot(_KERNPG_TABLE)));
+
+	/*
+	 * Intel Atom errata AAH41 workaround.
+	 *
+	 * The real fix should be in hw or in a microcode update, but
+	 * we also probabilistically try to reduce the window of having
+	 * a large TLB mixed with 4K TLBs while instruction fetches are
+	 * going on.
+	 */
+	__flush_tlb_all();
+
 	base = NULL;
 
 out_unlock:
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 6c873dc..9812008 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -103,9 +103,6 @@
 	help
 	Can we use information of configuration file?
 
-config HIGHMEM
-	bool "High memory support"
-
 endmenu
 
 menu "Platform options"
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 9606d2b..4ec1633 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -44,6 +44,8 @@
 #include <asm/setup.h>
 #include <asm/param.h>
 
+#include <platform/hardware.h>
+
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
 #endif
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index c7a021d..c44f830 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -30,6 +30,7 @@
 #include <linux/stringify.h>
 #include <linux/kallsyms.h>
 #include <linux/delay.h>
+#include <linux/hardirq.h>
 
 #include <asm/ptrace.h>
 #include <asm/timex.h>
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index 33f366b..bdd860d 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -14,6 +14,7 @@
 
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 #include <asm/hardirq.h>
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
index efed889..25d46c8 100644
--- a/arch/xtensa/platforms/iss/console.c
+++ b/arch/xtensa/platforms/iss/console.c
@@ -140,16 +140,14 @@
 }
 
 
-static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+static int rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
 	char buf[2];
 
-	if (!tty)
-		return;
-
 	buf[0] = ch;
 	buf[1] = '\0';		/* Is this NULL necessary? */
 	__simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0);
+	return 1;
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
diff --git a/block/blk-merge.c b/block/blk-merge.c
index a104593..5a244f0 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -39,14 +39,13 @@
 }
 
 static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
-					     struct bio *bio,
-					     unsigned int *seg_size_ptr)
+					     struct bio *bio)
 {
 	unsigned int phys_size;
 	struct bio_vec *bv, *bvprv = NULL;
 	int cluster, i, high, highprv = 1;
 	unsigned int seg_size, nr_phys_segs;
-	struct bio *fbio;
+	struct bio *fbio, *bbio;
 
 	if (!bio)
 		return 0;
@@ -87,26 +86,20 @@
 			seg_size = bv->bv_len;
 			highprv = high;
 		}
+		bbio = bio;
 	}
 
-	if (seg_size_ptr)
-		*seg_size_ptr = seg_size;
+	if (nr_phys_segs == 1 && seg_size > fbio->bi_seg_front_size)
+		fbio->bi_seg_front_size = seg_size;
+	if (seg_size > bbio->bi_seg_back_size)
+		bbio->bi_seg_back_size = seg_size;
 
 	return nr_phys_segs;
 }
 
 void blk_recalc_rq_segments(struct request *rq)
 {
-	unsigned int seg_size = 0, phys_segs;
-
-	phys_segs = __blk_recalc_rq_segments(rq->q, rq->bio, &seg_size);
-
-	if (phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size)
-		rq->bio->bi_seg_front_size = seg_size;
-	if (seg_size > rq->biotail->bi_seg_back_size)
-		rq->biotail->bi_seg_back_size = seg_size;
-
-	rq->nr_phys_segments = phys_segs;
+	rq->nr_phys_segments = __blk_recalc_rq_segments(rq->q, rq->bio);
 }
 
 void blk_recount_segments(struct request_queue *q, struct bio *bio)
@@ -114,7 +107,7 @@
 	struct bio *nxt = bio->bi_next;
 
 	bio->bi_next = NULL;
-	bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, NULL);
+	bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio);
 	bio->bi_next = nxt;
 	bio->bi_flags |= (1 << BIO_SEG_VALID);
 }
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 8dde4fc..74d0e62 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -56,6 +56,7 @@
 	tristate
 	select CRYPTO_ALGAPI2
 	select CRYPTO_RNG2
+	select CRYPTO_WORKQUEUE
 
 config CRYPTO_HASH
 	tristate
@@ -75,6 +76,10 @@
 	tristate
 	select CRYPTO_ALGAPI2
 
+config CRYPTO_PCOMP
+	tristate
+	select CRYPTO_ALGAPI2
+
 config CRYPTO_MANAGER
 	tristate "Cryptographic algorithm manager"
 	select CRYPTO_MANAGER2
@@ -87,6 +92,7 @@
 	select CRYPTO_AEAD2
 	select CRYPTO_HASH2
 	select CRYPTO_BLKCIPHER2
+	select CRYPTO_PCOMP
 
 config CRYPTO_GF128MUL
 	tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
@@ -106,11 +112,15 @@
 	help
 	  These are 'Null' algorithms, used by IPsec, which do nothing.
 
+config CRYPTO_WORKQUEUE
+       tristate
+
 config CRYPTO_CRYPTD
 	tristate "Software async crypto daemon"
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_HASH
 	select CRYPTO_MANAGER
+	select CRYPTO_WORKQUEUE
 	help
 	  This is a generic software asynchronous crypto daemon that
 	  converts an arbitrary synchronous software crypto algorithm
@@ -470,6 +480,31 @@
 
 	  See <http://csrc.nist.gov/encryption/aes/> for more information.
 
+config CRYPTO_AES_NI_INTEL
+	tristate "AES cipher algorithms (AES-NI)"
+	depends on (X86 || UML_X86) && 64BIT
+	select CRYPTO_AES_X86_64
+	select CRYPTO_CRYPTD
+	select CRYPTO_ALGAPI
+	help
+	  Use Intel AES-NI instructions for AES algorithm.
+
+	  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.
+
+	  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
@@ -714,6 +749,15 @@
 
 	  You will most probably want this if using IPSec.
 
+config CRYPTO_ZLIB
+	tristate "Zlib compression algorithm"
+	select CRYPTO_PCOMP
+	select ZLIB_INFLATE
+	select ZLIB_DEFLATE
+	select NLATTR
+	help
+	  This is the zlib algorithm.
+
 config CRYPTO_LZO
 	tristate "LZO compression algorithm"
 	select CRYPTO_ALGAPI
diff --git a/crypto/Makefile b/crypto/Makefile
index 46b08bf..673d9f7 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -5,6 +5,8 @@
 obj-$(CONFIG_CRYPTO) += crypto.o
 crypto-objs := api.o cipher.o digest.o compress.o
 
+obj-$(CONFIG_CRYPTO_WORKQUEUE) += crypto_wq.o
+
 obj-$(CONFIG_CRYPTO_FIPS) += fips.o
 
 crypto_algapi-$(CONFIG_PROC_FS) += proc.o
@@ -25,6 +27,8 @@
 crypto_hash-objs += shash.o
 obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 
+obj-$(CONFIG_CRYPTO_PCOMP) += pcompress.o
+
 cryptomgr-objs := algboss.o testmgr.o
 
 obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
@@ -70,6 +74,7 @@
 obj-$(CONFIG_CRYPTO_SEED) += seed.o
 obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
+obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
 obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index 94140b3..e11ce37 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -282,6 +282,25 @@
 					  alg->cra_ablkcipher.ivsize))
 		return alg;
 
+	crypto_mod_put(alg);
+	alg = crypto_alg_mod_lookup(name, type | CRYPTO_ALG_TESTED,
+				    mask & ~CRYPTO_ALG_TESTED);
+	if (IS_ERR(alg))
+		return alg;
+
+	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+	    CRYPTO_ALG_TYPE_GIVCIPHER) {
+		if ((alg->cra_flags ^ type ^ ~mask) & CRYPTO_ALG_TESTED) {
+			crypto_mod_put(alg);
+			alg = ERR_PTR(-ENOENT);
+		}
+		return alg;
+	}
+
+	BUG_ON(!((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+		 CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
+					     alg->cra_ablkcipher.ivsize));
+
 	return ERR_PTR(crypto_givcipher_default(alg, type, mask));
 }
 
diff --git a/crypto/aead.c b/crypto/aead.c
index 3a6f3f5..d9aa733 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -422,6 +422,22 @@
 	if (!alg->cra_aead.ivsize)
 		return alg;
 
+	crypto_mod_put(alg);
+	alg = crypto_alg_mod_lookup(name, type | CRYPTO_ALG_TESTED,
+				    mask & ~CRYPTO_ALG_TESTED);
+	if (IS_ERR(alg))
+		return alg;
+
+	if (alg->cra_type == &crypto_aead_type) {
+		if ((alg->cra_flags ^ type ^ ~mask) & CRYPTO_ALG_TESTED) {
+			crypto_mod_put(alg);
+			alg = ERR_PTR(-ENOENT);
+		}
+		return alg;
+	}
+
+	BUG_ON(!alg->cra_aead.ivsize);
+
 	return ERR_PTR(crypto_nivaead_default(alg, type, mask));
 }
 
diff --git a/crypto/algboss.c b/crypto/algboss.c
index 4601e426..6906f92 100644
--- a/crypto/algboss.c
+++ b/crypto/algboss.c
@@ -10,7 +10,7 @@
  *
  */
 
-#include <linux/crypto.h>
+#include <crypto/internal/aead.h>
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/init.h>
@@ -206,8 +206,7 @@
 	u32 type = param->type;
 	int err = 0;
 
-	if (!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
-	      CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV))
+	if (type & CRYPTO_ALG_TESTED)
 		goto skiptest;
 
 	err = alg_test(param->driver, param->alg, type, CRYPTO_ALG_TESTED);
@@ -223,6 +222,7 @@
 {
 	struct task_struct *thread;
 	struct crypto_test_param *param;
+	u32 type;
 
 	if (!try_module_get(THIS_MODULE))
 		goto err;
@@ -233,7 +233,19 @@
 
 	memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver));
 	memcpy(param->alg, alg->cra_name, sizeof(param->alg));
-	param->type = alg->cra_flags;
+	type = alg->cra_flags;
+
+	/* This piece of crap needs to disappear into per-type test hooks. */
+	if ((!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
+	       CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) &&
+	     ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+	      CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
+					  alg->cra_ablkcipher.ivsize)) ||
+	    (!((type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) &&
+	     alg->cra_type == &crypto_nivaead_type && alg->cra_aead.ivsize))
+		type |= CRYPTO_ALG_TESTED;
+
+	param->type = type;
 
 	thread = kthread_run(cryptomgr_test, param, "cryptomgr_test");
 	if (IS_ERR(thread))
diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c
index 0fac8ff..d80ed4c 100644
--- a/crypto/ansi_cprng.c
+++ b/crypto/ansi_cprng.c
@@ -132,9 +132,15 @@
 			 */
 			if (!memcmp(ctx->rand_data, ctx->last_rand_data,
 					DEFAULT_BLK_SZ)) {
+				if (fips_enabled) {
+					panic("cprng %p Failed repetition check!\n",
+						ctx);
+				}
+
 				printk(KERN_ERR
 					"ctx %p Failed repetition check!\n",
 					ctx);
+
 				ctx->flags |= PRNG_NEED_RESET;
 				return -EINVAL;
 			}
@@ -338,7 +344,16 @@
 
 	spin_lock_init(&ctx->prng_lock);
 
-	return reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL);
+	if (reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL) < 0)
+		return -EINVAL;
+
+	/*
+	 * after allocation, we should always force the user to reset
+	 * so they don't inadvertently use the insecure default values
+	 * without specifying them intentially
+	 */
+	ctx->flags |= PRNG_NEED_RESET;
+	return 0;
 }
 
 static void cprng_exit(struct crypto_tfm *tfm)
diff --git a/crypto/api.c b/crypto/api.c
index 38a2bc0..314dab9 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -255,7 +255,7 @@
 	struct crypto_alg *larval;
 	int ok;
 
-	if (!(mask & CRYPTO_ALG_TESTED)) {
+	if (!((type | mask) & CRYPTO_ALG_TESTED)) {
 		type |= CRYPTO_ALG_TESTED;
 		mask |= CRYPTO_ALG_TESTED;
 	}
@@ -464,8 +464,8 @@
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_base);
 
-struct crypto_tfm *crypto_create_tfm(struct crypto_alg *alg,
-				     const struct crypto_type *frontend)
+void *crypto_create_tfm(struct crypto_alg *alg,
+			const struct crypto_type *frontend)
 {
 	char *mem;
 	struct crypto_tfm *tfm = NULL;
@@ -499,9 +499,9 @@
 		crypto_shoot_alg(alg);
 	kfree(mem);
 out_err:
-	tfm = ERR_PTR(err);
+	mem = ERR_PTR(err);
 out:
-	return tfm;
+	return mem;
 }
 EXPORT_SYMBOL_GPL(crypto_create_tfm);
 
@@ -525,12 +525,11 @@
  *
  *	In case of error the return value is an error pointer.
  */
-struct crypto_tfm *crypto_alloc_tfm(const char *alg_name,
-				    const struct crypto_type *frontend,
-				    u32 type, u32 mask)
+void *crypto_alloc_tfm(const char *alg_name,
+		       const struct crypto_type *frontend, u32 type, u32 mask)
 {
 	struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask);
-	struct crypto_tfm *tfm;
+	void *tfm;
 	int err;
 
 	type &= frontend->maskclear;
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index d70a41c..90d26c9 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -521,7 +521,7 @@
 	int err;
 
 	type = crypto_skcipher_type(type);
-	mask = crypto_skcipher_mask(mask) | CRYPTO_ALG_GENIV;
+	mask = crypto_skcipher_mask(mask)| CRYPTO_ALG_GENIV;
 
 	alg = crypto_alg_mod_lookup(name, type, mask);
 	if (IS_ERR(alg))
diff --git a/crypto/chainiv.c b/crypto/chainiv.c
index 7c37a49..ba200b0 100644
--- a/crypto/chainiv.c
+++ b/crypto/chainiv.c
@@ -15,6 +15,7 @@
 
 #include <crypto/internal/skcipher.h>
 #include <crypto/rng.h>
+#include <crypto/crypto_wq.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -133,7 +134,7 @@
 			goto out;
 	}
 
-	queued = schedule_work(&ctx->postponed);
+	queued = queue_work(kcrypto_wq, &ctx->postponed);
 	BUG_ON(!queued);
 
 out:
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index d29e06b..d14b226 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -12,30 +12,31 @@
 
 #include <crypto/algapi.h>
 #include <crypto/internal/hash.h>
+#include <crypto/cryptd.h>
+#include <crypto/crypto_wq.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/module.h>
-#include <linux/mutex.h>
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/spinlock.h>
 
-#define CRYPTD_MAX_QLEN 100
+#define CRYPTD_MAX_CPU_QLEN 100
 
-struct cryptd_state {
-	spinlock_t lock;
-	struct mutex mutex;
+struct cryptd_cpu_queue {
 	struct crypto_queue queue;
-	struct task_struct *task;
+	struct work_struct work;
+};
+
+struct cryptd_queue {
+	struct cryptd_cpu_queue *cpu_queue;
 };
 
 struct cryptd_instance_ctx {
 	struct crypto_spawn spawn;
-	struct cryptd_state *state;
+	struct cryptd_queue *queue;
 };
 
 struct cryptd_blkcipher_ctx {
@@ -54,11 +55,85 @@
 	crypto_completion_t complete;
 };
 
-static inline struct cryptd_state *cryptd_get_state(struct crypto_tfm *tfm)
+static void cryptd_queue_worker(struct work_struct *work);
+
+static int cryptd_init_queue(struct cryptd_queue *queue,
+			     unsigned int max_cpu_qlen)
+{
+	int cpu;
+	struct cryptd_cpu_queue *cpu_queue;
+
+	queue->cpu_queue = alloc_percpu(struct cryptd_cpu_queue);
+	if (!queue->cpu_queue)
+		return -ENOMEM;
+	for_each_possible_cpu(cpu) {
+		cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
+		crypto_init_queue(&cpu_queue->queue, max_cpu_qlen);
+		INIT_WORK(&cpu_queue->work, cryptd_queue_worker);
+	}
+	return 0;
+}
+
+static void cryptd_fini_queue(struct cryptd_queue *queue)
+{
+	int cpu;
+	struct cryptd_cpu_queue *cpu_queue;
+
+	for_each_possible_cpu(cpu) {
+		cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
+		BUG_ON(cpu_queue->queue.qlen);
+	}
+	free_percpu(queue->cpu_queue);
+}
+
+static int cryptd_enqueue_request(struct cryptd_queue *queue,
+				  struct crypto_async_request *request)
+{
+	int cpu, err;
+	struct cryptd_cpu_queue *cpu_queue;
+
+	cpu = get_cpu();
+	cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
+	err = crypto_enqueue_request(&cpu_queue->queue, request);
+	queue_work_on(cpu, kcrypto_wq, &cpu_queue->work);
+	put_cpu();
+
+	return err;
+}
+
+/* Called in workqueue context, do one real cryption work (via
+ * req->complete) and reschedule itself if there are more work to
+ * do. */
+static void cryptd_queue_worker(struct work_struct *work)
+{
+	struct cryptd_cpu_queue *cpu_queue;
+	struct crypto_async_request *req, *backlog;
+
+	cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
+	/* Only handle one request at a time to avoid hogging crypto
+	 * workqueue. preempt_disable/enable is used to prevent
+	 * being preempted by cryptd_enqueue_request() */
+	preempt_disable();
+	backlog = crypto_get_backlog(&cpu_queue->queue);
+	req = crypto_dequeue_request(&cpu_queue->queue);
+	preempt_enable();
+
+	if (!req)
+		return;
+
+	if (backlog)
+		backlog->complete(backlog, -EINPROGRESS);
+	req->complete(req, 0);
+
+	if (cpu_queue->queue.qlen)
+		queue_work(kcrypto_wq, &cpu_queue->work);
+}
+
+static inline struct cryptd_queue *cryptd_get_queue(struct crypto_tfm *tfm)
 {
 	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
 	struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
-	return ictx->state;
+	return ictx->queue;
 }
 
 static int cryptd_blkcipher_setkey(struct crypto_ablkcipher *parent,
@@ -130,19 +205,13 @@
 {
 	struct cryptd_blkcipher_request_ctx *rctx = ablkcipher_request_ctx(req);
 	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
-	struct cryptd_state *state =
-		cryptd_get_state(crypto_ablkcipher_tfm(tfm));
-	int err;
+	struct cryptd_queue *queue;
 
+	queue = cryptd_get_queue(crypto_ablkcipher_tfm(tfm));
 	rctx->complete = req->base.complete;
 	req->base.complete = complete;
 
-	spin_lock_bh(&state->lock);
-	err = ablkcipher_enqueue_request(&state->queue, req);
-	spin_unlock_bh(&state->lock);
-
-	wake_up_process(state->task);
-	return err;
+	return cryptd_enqueue_request(queue, &req->base);
 }
 
 static int cryptd_blkcipher_encrypt_enqueue(struct ablkcipher_request *req)
@@ -176,21 +245,12 @@
 static void cryptd_blkcipher_exit_tfm(struct crypto_tfm *tfm)
 {
 	struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(tfm);
-	struct cryptd_state *state = cryptd_get_state(tfm);
-	int active;
-
-	mutex_lock(&state->mutex);
-	active = ablkcipher_tfm_in_queue(&state->queue,
-					 __crypto_ablkcipher_cast(tfm));
-	mutex_unlock(&state->mutex);
-
-	BUG_ON(active);
 
 	crypto_free_blkcipher(ctx->child);
 }
 
 static struct crypto_instance *cryptd_alloc_instance(struct crypto_alg *alg,
-						     struct cryptd_state *state)
+						     struct cryptd_queue *queue)
 {
 	struct crypto_instance *inst;
 	struct cryptd_instance_ctx *ctx;
@@ -213,7 +273,7 @@
 	if (err)
 		goto out_free_inst;
 
-	ctx->state = state;
+	ctx->queue = queue;
 
 	memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
 
@@ -231,7 +291,7 @@
 }
 
 static struct crypto_instance *cryptd_alloc_blkcipher(
-	struct rtattr **tb, struct cryptd_state *state)
+	struct rtattr **tb, struct cryptd_queue *queue)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
@@ -241,7 +301,7 @@
 	if (IS_ERR(alg))
 		return ERR_CAST(alg);
 
-	inst = cryptd_alloc_instance(alg, state);
+	inst = cryptd_alloc_instance(alg, queue);
 	if (IS_ERR(inst))
 		goto out_put_alg;
 
@@ -289,15 +349,6 @@
 static void cryptd_hash_exit_tfm(struct crypto_tfm *tfm)
 {
 	struct cryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm);
-	struct cryptd_state *state = cryptd_get_state(tfm);
-	int active;
-
-	mutex_lock(&state->mutex);
-	active = ahash_tfm_in_queue(&state->queue,
-				__crypto_ahash_cast(tfm));
-	mutex_unlock(&state->mutex);
-
-	BUG_ON(active);
 
 	crypto_free_hash(ctx->child);
 }
@@ -323,19 +374,13 @@
 {
 	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-	struct cryptd_state *state =
-		cryptd_get_state(crypto_ahash_tfm(tfm));
-	int err;
+	struct cryptd_queue *queue =
+		cryptd_get_queue(crypto_ahash_tfm(tfm));
 
 	rctx->complete = req->base.complete;
 	req->base.complete = complete;
 
-	spin_lock_bh(&state->lock);
-	err = ahash_enqueue_request(&state->queue, req);
-	spin_unlock_bh(&state->lock);
-
-	wake_up_process(state->task);
-	return err;
+	return cryptd_enqueue_request(queue, &req->base);
 }
 
 static void cryptd_hash_init(struct crypto_async_request *req_async, int err)
@@ -468,7 +513,7 @@
 }
 
 static struct crypto_instance *cryptd_alloc_hash(
-	struct rtattr **tb, struct cryptd_state *state)
+	struct rtattr **tb, struct cryptd_queue *queue)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
@@ -478,7 +523,7 @@
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
-	inst = cryptd_alloc_instance(alg, state);
+	inst = cryptd_alloc_instance(alg, queue);
 	if (IS_ERR(inst))
 		goto out_put_alg;
 
@@ -502,7 +547,7 @@
 	return inst;
 }
 
-static struct cryptd_state state;
+static struct cryptd_queue queue;
 
 static struct crypto_instance *cryptd_alloc(struct rtattr **tb)
 {
@@ -514,9 +559,9 @@
 
 	switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
 	case CRYPTO_ALG_TYPE_BLKCIPHER:
-		return cryptd_alloc_blkcipher(tb, &state);
+		return cryptd_alloc_blkcipher(tb, &queue);
 	case CRYPTO_ALG_TYPE_DIGEST:
-		return cryptd_alloc_hash(tb, &state);
+		return cryptd_alloc_hash(tb, &queue);
 	}
 
 	return ERR_PTR(-EINVAL);
@@ -537,82 +582,58 @@
 	.module = THIS_MODULE,
 };
 
-static inline int cryptd_create_thread(struct cryptd_state *state,
-				       int (*fn)(void *data), const char *name)
+struct cryptd_ablkcipher *cryptd_alloc_ablkcipher(const char *alg_name,
+						  u32 type, u32 mask)
 {
-	spin_lock_init(&state->lock);
-	mutex_init(&state->mutex);
-	crypto_init_queue(&state->queue, CRYPTD_MAX_QLEN);
+	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
+	struct crypto_ablkcipher *tfm;
 
-	state->task = kthread_run(fn, state, name);
-	if (IS_ERR(state->task))
-		return PTR_ERR(state->task);
+	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
+		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
+		return ERR_PTR(-EINVAL);
+	tfm = crypto_alloc_ablkcipher(cryptd_alg_name, type, mask);
+	if (IS_ERR(tfm))
+		return ERR_CAST(tfm);
+	if (crypto_ablkcipher_tfm(tfm)->__crt_alg->cra_module != THIS_MODULE) {
+		crypto_free_ablkcipher(tfm);
+		return ERR_PTR(-EINVAL);
+	}
 
-	return 0;
+	return __cryptd_ablkcipher_cast(tfm);
 }
+EXPORT_SYMBOL_GPL(cryptd_alloc_ablkcipher);
 
-static inline void cryptd_stop_thread(struct cryptd_state *state)
+struct crypto_blkcipher *cryptd_ablkcipher_child(struct cryptd_ablkcipher *tfm)
 {
-	BUG_ON(state->queue.qlen);
-	kthread_stop(state->task);
+	struct cryptd_blkcipher_ctx *ctx = crypto_ablkcipher_ctx(&tfm->base);
+	return ctx->child;
 }
+EXPORT_SYMBOL_GPL(cryptd_ablkcipher_child);
 
-static int cryptd_thread(void *data)
+void cryptd_free_ablkcipher(struct cryptd_ablkcipher *tfm)
 {
-	struct cryptd_state *state = data;
-	int stop;
-
-	current->flags |= PF_NOFREEZE;
-
-	do {
-		struct crypto_async_request *req, *backlog;
-
-		mutex_lock(&state->mutex);
-		__set_current_state(TASK_INTERRUPTIBLE);
-
-		spin_lock_bh(&state->lock);
-		backlog = crypto_get_backlog(&state->queue);
-		req = crypto_dequeue_request(&state->queue);
-		spin_unlock_bh(&state->lock);
-
-		stop = kthread_should_stop();
-
-		if (stop || req) {
-			__set_current_state(TASK_RUNNING);
-			if (req) {
-				if (backlog)
-					backlog->complete(backlog,
-							  -EINPROGRESS);
-				req->complete(req, 0);
-			}
-		}
-
-		mutex_unlock(&state->mutex);
-
-		schedule();
-	} while (!stop);
-
-	return 0;
+	crypto_free_ablkcipher(&tfm->base);
 }
+EXPORT_SYMBOL_GPL(cryptd_free_ablkcipher);
 
 static int __init cryptd_init(void)
 {
 	int err;
 
-	err = cryptd_create_thread(&state, cryptd_thread, "cryptd");
+	err = cryptd_init_queue(&queue, CRYPTD_MAX_CPU_QLEN);
 	if (err)
 		return err;
 
 	err = crypto_register_template(&cryptd_tmpl);
 	if (err)
-		kthread_stop(state.task);
+		cryptd_fini_queue(&queue);
 
 	return err;
 }
 
 static void __exit cryptd_exit(void)
 {
-	cryptd_stop_thread(&state);
+	cryptd_fini_queue(&queue);
 	crypto_unregister_template(&cryptd_tmpl);
 }
 
diff --git a/crypto/crypto_wq.c b/crypto/crypto_wq.c
new file mode 100644
index 0000000..fdcf624
--- /dev/null
+++ b/crypto/crypto_wq.c
@@ -0,0 +1,38 @@
+/*
+ * Workqueue for crypto subsystem
+ *
+ * Copyright (c) 2009 Intel Corp.
+ *   Author: Huang Ying <ying.huang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <linux/workqueue.h>
+#include <crypto/algapi.h>
+#include <crypto/crypto_wq.h>
+
+struct workqueue_struct *kcrypto_wq;
+EXPORT_SYMBOL_GPL(kcrypto_wq);
+
+static int __init crypto_wq_init(void)
+{
+	kcrypto_wq = create_workqueue("crypto");
+	if (unlikely(!kcrypto_wq))
+		return -ENOMEM;
+	return 0;
+}
+
+static void __exit crypto_wq_exit(void)
+{
+	destroy_workqueue(kcrypto_wq);
+}
+
+module_init(crypto_wq_init);
+module_exit(crypto_wq_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Workqueue for crypto subsystem");
diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c
index ecbeaa1..a90d260 100644
--- a/crypto/gf128mul.c
+++ b/crypto/gf128mul.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2006, Rik Snel <rsnel@cube.dyndns.org>
  *
  * Based on Dr Brian Gladman's (GPL'd) work published at
- * http://fp.gladman.plus.com/cryptography_technology/index.htm
+ * http://gladman.plushost.co.uk/oldsite/cryptography_technology/index.php
  * See the original copyright notice below.
  *
  * This program is free software; you can redistribute it and/or modify it
diff --git a/crypto/internal.h b/crypto/internal.h
index 3c19a27..fc76e1f 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -109,8 +109,10 @@
 void crypto_shoot_alg(struct crypto_alg *alg);
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask);
-struct crypto_tfm *crypto_create_tfm(struct crypto_alg *alg,
-				     const struct crypto_type *frontend);
+void *crypto_create_tfm(struct crypto_alg *alg,
+			const struct crypto_type *frontend);
+void *crypto_alloc_tfm(const char *alg_name,
+		       const struct crypto_type *frontend, u32 type, u32 mask);
 
 int crypto_register_instance(struct crypto_template *tmpl,
 			     struct crypto_instance *inst);
diff --git a/crypto/pcompress.c b/crypto/pcompress.c
new file mode 100644
index 0000000..ca9a4af
--- /dev/null
+++ b/crypto/pcompress.c
@@ -0,0 +1,97 @@
+/*
+ * Cryptographic API.
+ *
+ * Partial (de)compression operations.
+ *
+ * Copyright 2008 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/crypto.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+
+#include <crypto/compress.h>
+
+#include "internal.h"
+
+
+static int crypto_pcomp_init(struct crypto_tfm *tfm, u32 type, u32 mask)
+{
+	return 0;
+}
+
+static unsigned int crypto_pcomp_extsize(struct crypto_alg *alg,
+					 const struct crypto_type *frontend)
+{
+	return alg->cra_ctxsize;
+}
+
+static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm,
+				 const struct crypto_type *frontend)
+{
+	return 0;
+}
+
+static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
+	__attribute__ ((unused));
+static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
+{
+	seq_printf(m, "type         : pcomp\n");
+}
+
+static const struct crypto_type crypto_pcomp_type = {
+	.extsize	= crypto_pcomp_extsize,
+	.init		= crypto_pcomp_init,
+	.init_tfm	= crypto_pcomp_init_tfm,
+#ifdef CONFIG_PROC_FS
+	.show		= crypto_pcomp_show,
+#endif
+	.maskclear	= ~CRYPTO_ALG_TYPE_MASK,
+	.maskset	= CRYPTO_ALG_TYPE_MASK,
+	.type		= CRYPTO_ALG_TYPE_PCOMPRESS,
+	.tfmsize	= offsetof(struct crypto_pcomp, base),
+};
+
+struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name, u32 type,
+					u32 mask)
+{
+	return crypto_alloc_tfm(alg_name, &crypto_pcomp_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_pcomp);
+
+int crypto_register_pcomp(struct pcomp_alg *alg)
+{
+	struct crypto_alg *base = &alg->base;
+
+	base->cra_type = &crypto_pcomp_type;
+	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+	base->cra_flags |= CRYPTO_ALG_TYPE_PCOMPRESS;
+
+	return crypto_register_alg(base);
+}
+EXPORT_SYMBOL_GPL(crypto_register_pcomp);
+
+int crypto_unregister_pcomp(struct pcomp_alg *alg)
+{
+	return crypto_unregister_alg(&alg->base);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_pcomp);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Partial (de)compression type");
+MODULE_AUTHOR("Sony Corporation");
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index caa3542..6349d83 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -2,7 +2,7 @@
  * Cryptographic API.
  *
  * SHA-256, as specified in
- * http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
+ * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
  *
  * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
  *
diff --git a/crypto/shash.c b/crypto/shash.c
index d5a2b61..7a65973 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -18,15 +18,10 @@
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 
-static const struct crypto_type crypto_shash_type;
-
-static inline struct crypto_shash *__crypto_shash_cast(struct crypto_tfm *tfm)
-{
-	return container_of(tfm, struct crypto_shash, base);
-}
-
 #include "internal.h"
 
+static const struct crypto_type crypto_shash_type;
+
 static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
 				  unsigned int keylen)
 {
@@ -282,8 +277,7 @@
 	if (!crypto_mod_get(calg))
 		return -EAGAIN;
 
-	shash = __crypto_shash_cast(crypto_create_tfm(
-		calg, &crypto_shash_type));
+	shash = crypto_create_tfm(calg, &crypto_shash_type);
 	if (IS_ERR(shash)) {
 		crypto_mod_put(calg);
 		return PTR_ERR(shash);
@@ -391,8 +385,7 @@
 	if (!crypto_mod_get(calg))
 		return -EAGAIN;
 
-	shash = __crypto_shash_cast(crypto_create_tfm(
-		calg, &crypto_shash_type));
+	shash = crypto_create_tfm(calg, &crypto_shash_type);
 	if (IS_ERR(shash)) {
 		crypto_mod_put(calg);
 		return PTR_ERR(shash);
@@ -442,8 +435,6 @@
 static int crypto_shash_init_tfm(struct crypto_tfm *tfm,
 				 const struct crypto_type *frontend)
 {
-	if (frontend->type != CRYPTO_ALG_TYPE_SHASH)
-		return -EINVAL;
 	return 0;
 }
 
@@ -482,8 +473,7 @@
 struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
 					u32 mask)
 {
-	return __crypto_shash_cast(
-		crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask));
+	return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask);
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_shash);
 
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 28a45a1..c3c9124 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -53,7 +53,7 @@
 	"cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
 	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
 	"camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320",
-	"lzo", "cts", NULL
+	"lzo", "cts", "zlib", NULL
 };
 
 static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
@@ -661,6 +661,10 @@
 		tcrypt_test("ecb(seed)");
 		break;
 
+	case 44:
+		tcrypt_test("zlib");
+		break;
+
 	case 100:
 		tcrypt_test("hmac(md5)");
 		break;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index a75f11f..b50c3c6 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -72,6 +72,13 @@
 	} comp, decomp;
 };
 
+struct pcomp_test_suite {
+	struct {
+		struct pcomp_testvec *vecs;
+		unsigned int count;
+	} comp, decomp;
+};
+
 struct hash_test_suite {
 	struct hash_testvec *vecs;
 	unsigned int count;
@@ -86,6 +93,7 @@
 		struct aead_test_suite aead;
 		struct cipher_test_suite cipher;
 		struct comp_test_suite comp;
+		struct pcomp_test_suite pcomp;
 		struct hash_test_suite hash;
 	} suite;
 };
@@ -898,6 +906,159 @@
 	return ret;
 }
 
+static int test_pcomp(struct crypto_pcomp *tfm,
+		      struct pcomp_testvec *ctemplate,
+		      struct pcomp_testvec *dtemplate, int ctcount,
+		      int dtcount)
+{
+	const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm));
+	unsigned int i;
+	char result[COMP_BUF_SIZE];
+	int error;
+
+	for (i = 0; i < ctcount; i++) {
+		struct comp_request req;
+
+		error = crypto_compress_setup(tfm, ctemplate[i].params,
+					      ctemplate[i].paramsize);
+		if (error) {
+			pr_err("alg: pcomp: compression setup failed on test "
+			       "%d for %s: error=%d\n", i + 1, algo, error);
+			return error;
+		}
+
+		error = crypto_compress_init(tfm);
+		if (error) {
+			pr_err("alg: pcomp: compression init failed on test "
+			       "%d for %s: error=%d\n", i + 1, algo, error);
+			return error;
+		}
+
+		memset(result, 0, sizeof(result));
+
+		req.next_in = ctemplate[i].input;
+		req.avail_in = ctemplate[i].inlen / 2;
+		req.next_out = result;
+		req.avail_out = ctemplate[i].outlen / 2;
+
+		error = crypto_compress_update(tfm, &req);
+		if (error && (error != -EAGAIN || req.avail_in)) {
+			pr_err("alg: pcomp: compression update failed on test "
+			       "%d for %s: error=%d\n", i + 1, algo, error);
+			return error;
+		}
+
+		/* Add remaining input data */
+		req.avail_in += (ctemplate[i].inlen + 1) / 2;
+
+		error = crypto_compress_update(tfm, &req);
+		if (error && (error != -EAGAIN || req.avail_in)) {
+			pr_err("alg: pcomp: compression update failed on test "
+			       "%d for %s: error=%d\n", i + 1, algo, error);
+			return error;
+		}
+
+		/* Provide remaining output space */
+		req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2;
+
+		error = crypto_compress_final(tfm, &req);
+		if (error) {
+			pr_err("alg: pcomp: compression final failed on test "
+			       "%d for %s: error=%d\n", i + 1, algo, error);
+			return error;
+		}
+
+		if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) {
+			pr_err("alg: comp: Compression test %d failed for %s: "
+			       "output len = %d (expected %d)\n", i + 1, algo,
+			       COMP_BUF_SIZE - req.avail_out,
+			       ctemplate[i].outlen);
+			return -EINVAL;
+		}
+
+		if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) {
+			pr_err("alg: pcomp: Compression test %d failed for "
+			       "%s\n", i + 1, algo);
+			hexdump(result, ctemplate[i].outlen);
+			return -EINVAL;
+		}
+	}
+
+	for (i = 0; i < dtcount; i++) {
+		struct comp_request req;
+
+		error = crypto_decompress_setup(tfm, dtemplate[i].params,
+						dtemplate[i].paramsize);
+		if (error) {
+			pr_err("alg: pcomp: decompression setup failed on "
+			       "test %d for %s: error=%d\n", i + 1, algo,
+			       error);
+			return error;
+		}
+
+		error = crypto_decompress_init(tfm);
+		if (error) {
+			pr_err("alg: pcomp: decompression init failed on test "
+			       "%d for %s: error=%d\n", i + 1, algo, error);
+			return error;
+		}
+
+		memset(result, 0, sizeof(result));
+
+		req.next_in = dtemplate[i].input;
+		req.avail_in = dtemplate[i].inlen / 2;
+		req.next_out = result;
+		req.avail_out = dtemplate[i].outlen / 2;
+
+		error = crypto_decompress_update(tfm, &req);
+		if (error  && (error != -EAGAIN || req.avail_in)) {
+			pr_err("alg: pcomp: decompression update failed on "
+			       "test %d for %s: error=%d\n", i + 1, algo,
+			       error);
+			return error;
+		}
+
+		/* Add remaining input data */
+		req.avail_in += (dtemplate[i].inlen + 1) / 2;
+
+		error = crypto_decompress_update(tfm, &req);
+		if (error  && (error != -EAGAIN || req.avail_in)) {
+			pr_err("alg: pcomp: decompression update failed on "
+			       "test %d for %s: error=%d\n", i + 1, algo,
+			       error);
+			return error;
+		}
+
+		/* Provide remaining output space */
+		req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2;
+
+		error = crypto_decompress_final(tfm, &req);
+		if (error  && (error != -EAGAIN || req.avail_in)) {
+			pr_err("alg: pcomp: decompression final failed on "
+			       "test %d for %s: error=%d\n", i + 1, algo,
+			       error);
+			return error;
+		}
+
+		if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) {
+			pr_err("alg: comp: Decompression test %d failed for "
+			       "%s: output len = %d (expected %d)\n", i + 1,
+			       algo, COMP_BUF_SIZE - req.avail_out,
+			       dtemplate[i].outlen);
+			return -EINVAL;
+		}
+
+		if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) {
+			pr_err("alg: pcomp: Decompression test %d failed for "
+			       "%s\n", i + 1, algo);
+			hexdump(result, dtemplate[i].outlen);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
 			 u32 type, u32 mask)
 {
@@ -1007,6 +1168,28 @@
 	return err;
 }
 
+static int alg_test_pcomp(const struct alg_test_desc *desc, const char *driver,
+			  u32 type, u32 mask)
+{
+	struct crypto_pcomp *tfm;
+	int err;
+
+	tfm = crypto_alloc_pcomp(driver, type, mask);
+	if (IS_ERR(tfm)) {
+		pr_err("alg: pcomp: Failed to load transform for %s: %ld\n",
+		       driver, PTR_ERR(tfm));
+		return PTR_ERR(tfm);
+	}
+
+	err = test_pcomp(tfm, desc->suite.pcomp.comp.vecs,
+			 desc->suite.pcomp.decomp.vecs,
+			 desc->suite.pcomp.comp.count,
+			 desc->suite.pcomp.decomp.count);
+
+	crypto_free_pcomp(tfm);
+	return err;
+}
+
 static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
 			 u32 type, u32 mask)
 {
@@ -1835,6 +2018,21 @@
 				}
 			}
 		}
+	}, {
+		.alg = "zlib",
+		.test = alg_test_pcomp,
+		.suite = {
+			.pcomp = {
+				.comp = {
+					.vecs = zlib_comp_tv_template,
+					.count = ZLIB_COMP_TEST_VECTORS
+				},
+				.decomp = {
+					.vecs = zlib_decomp_tv_template,
+					.count = ZLIB_DECOMP_TEST_VECTORS
+				}
+			}
+		}
 	}
 };
 
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 132953e..526f00a 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -15,6 +15,11 @@
 #ifndef _CRYPTO_TESTMGR_H
 #define _CRYPTO_TESTMGR_H
 
+#include <linux/netlink.h>
+#include <linux/zlib.h>
+
+#include <crypto/compress.h>
+
 #define MAX_DIGEST_SIZE		64
 #define MAX_TAP			8
 
@@ -8347,10 +8352,19 @@
 	char output[COMP_BUF_SIZE];
 };
 
+struct pcomp_testvec {
+	void *params;
+	unsigned int paramsize;
+	int inlen, outlen;
+	char input[COMP_BUF_SIZE];
+	char output[COMP_BUF_SIZE];
+};
+
 /*
  * Deflate test vectors (null-terminated strings).
  * Params: winbits=-11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL.
  */
+
 #define DEFLATE_COMP_TEST_VECTORS 2
 #define DEFLATE_DECOMP_TEST_VECTORS 2
 
@@ -8426,6 +8440,139 @@
 	},
 };
 
+#define ZLIB_COMP_TEST_VECTORS 2
+#define ZLIB_DECOMP_TEST_VECTORS 2
+
+static const struct {
+	struct nlattr nla;
+	int val;
+} deflate_comp_params[] = {
+	{
+		.nla = {
+			.nla_len	= NLA_HDRLEN + sizeof(int),
+			.nla_type	= ZLIB_COMP_LEVEL,
+		},
+		.val			= Z_DEFAULT_COMPRESSION,
+	}, {
+		.nla = {
+			.nla_len	= NLA_HDRLEN + sizeof(int),
+			.nla_type	= ZLIB_COMP_METHOD,
+		},
+		.val			= Z_DEFLATED,
+	}, {
+		.nla = {
+			.nla_len	= NLA_HDRLEN + sizeof(int),
+			.nla_type	= ZLIB_COMP_WINDOWBITS,
+		},
+		.val			= -11,
+	}, {
+		.nla = {
+			.nla_len	= NLA_HDRLEN + sizeof(int),
+			.nla_type	= ZLIB_COMP_MEMLEVEL,
+		},
+		.val			= MAX_MEM_LEVEL,
+	}, {
+		.nla = {
+			.nla_len	= NLA_HDRLEN + sizeof(int),
+			.nla_type	= ZLIB_COMP_STRATEGY,
+		},
+		.val			= Z_DEFAULT_STRATEGY,
+	}
+};
+
+static const struct {
+	struct nlattr nla;
+	int val;
+} deflate_decomp_params[] = {
+	{
+		.nla = {
+			.nla_len	= NLA_HDRLEN + sizeof(int),
+			.nla_type	= ZLIB_DECOMP_WINDOWBITS,
+		},
+		.val			= -11,
+	}
+};
+
+static struct pcomp_testvec zlib_comp_tv_template[] = {
+	{
+		.params = &deflate_comp_params,
+		.paramsize = sizeof(deflate_comp_params),
+		.inlen	= 70,
+		.outlen	= 38,
+		.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",
+	}, {
+		.params = &deflate_comp_params,
+		.paramsize = sizeof(deflate_comp_params),
+		.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	= "\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",
+	},
+};
+
+static struct pcomp_testvec zlib_decomp_tv_template[] = {
+	{
+		.params = &deflate_decomp_params,
+		.paramsize = sizeof(deflate_decomp_params),
+		.inlen	= 122,
+		.outlen	= 191,
+		.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.",
+	}, {
+		.params = &deflate_decomp_params,
+		.paramsize = sizeof(deflate_decomp_params),
+		.inlen	= 38,
+		.outlen	= 70,
+		.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 ",
+	},
+};
+
 /*
  * LZO test vectors (null-terminated strings).
  */
diff --git a/crypto/zlib.c b/crypto/zlib.c
new file mode 100644
index 0000000..33609ba
--- /dev/null
+++ b/crypto/zlib.c
@@ -0,0 +1,378 @@
+/*
+ * Cryptographic API.
+ *
+ * Zlib algorithm
+ *
+ * Copyright 2008 Sony Corporation
+ *
+ * Based on deflate.c, which is
+ * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * FIXME: deflate transforms will require up to a total of about 436k of kernel
+ * memory on i386 (390k for compression, the rest for decompression), as the
+ * current zlib kernel code uses a worst case pre-allocation system by default.
+ * This needs to be fixed so that the amount of memory required is properly
+ * related to the winbits and memlevel parameters.
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/zlib.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/net.h>
+#include <linux/slab.h>
+
+#include <crypto/internal/compress.h>
+
+#include <net/netlink.h>
+
+
+struct zlib_ctx {
+	struct z_stream_s comp_stream;
+	struct z_stream_s decomp_stream;
+	int decomp_windowBits;
+};
+
+
+static void zlib_comp_exit(struct zlib_ctx *ctx)
+{
+	struct z_stream_s *stream = &ctx->comp_stream;
+
+	if (stream->workspace) {
+		zlib_deflateEnd(stream);
+		vfree(stream->workspace);
+		stream->workspace = NULL;
+	}
+}
+
+static void zlib_decomp_exit(struct zlib_ctx *ctx)
+{
+	struct z_stream_s *stream = &ctx->decomp_stream;
+
+	if (stream->workspace) {
+		zlib_inflateEnd(stream);
+		kfree(stream->workspace);
+		stream->workspace = NULL;
+	}
+}
+
+static int zlib_init(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static void zlib_exit(struct crypto_tfm *tfm)
+{
+	struct zlib_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	zlib_comp_exit(ctx);
+	zlib_decomp_exit(ctx);
+}
+
+
+static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
+			       unsigned int len)
+{
+	struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+	struct z_stream_s *stream = &ctx->comp_stream;
+	struct nlattr *tb[ZLIB_COMP_MAX + 1];
+	size_t workspacesize;
+	int ret;
+
+	ret = nla_parse(tb, ZLIB_COMP_MAX, params, len, NULL);
+	if (ret)
+		return ret;
+
+	zlib_comp_exit(ctx);
+
+	workspacesize = zlib_deflate_workspacesize();
+	stream->workspace = vmalloc(workspacesize);
+	if (!stream->workspace)
+		return -ENOMEM;
+
+	memset(stream->workspace, 0, workspacesize);
+	ret = zlib_deflateInit2(stream,
+				tb[ZLIB_COMP_LEVEL]
+					? nla_get_u32(tb[ZLIB_COMP_LEVEL])
+					: Z_DEFAULT_COMPRESSION,
+				tb[ZLIB_COMP_METHOD]
+					? nla_get_u32(tb[ZLIB_COMP_METHOD])
+					: Z_DEFLATED,
+				tb[ZLIB_COMP_WINDOWBITS]
+					? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
+					: MAX_WBITS,
+				tb[ZLIB_COMP_MEMLEVEL]
+					? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
+					: DEF_MEM_LEVEL,
+				tb[ZLIB_COMP_STRATEGY]
+					? nla_get_u32(tb[ZLIB_COMP_STRATEGY])
+					: Z_DEFAULT_STRATEGY);
+	if (ret != Z_OK) {
+		vfree(stream->workspace);
+		stream->workspace = NULL;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int zlib_compress_init(struct crypto_pcomp *tfm)
+{
+	int ret;
+	struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+	struct z_stream_s *stream = &dctx->comp_stream;
+
+	ret = zlib_deflateReset(stream);
+	if (ret != Z_OK)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int zlib_compress_update(struct crypto_pcomp *tfm,
+				struct comp_request *req)
+{
+	int ret;
+	struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+	struct z_stream_s *stream = &dctx->comp_stream;
+
+	pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
+	stream->next_in = req->next_in;
+	stream->avail_in = req->avail_in;
+	stream->next_out = req->next_out;
+	stream->avail_out = req->avail_out;
+
+	ret = zlib_deflate(stream, Z_NO_FLUSH);
+	switch (ret) {
+	case Z_OK:
+		break;
+
+	case Z_BUF_ERROR:
+		pr_debug("zlib_deflate could not make progress\n");
+		return -EAGAIN;
+
+	default:
+		pr_debug("zlib_deflate failed %d\n", ret);
+		return -EINVAL;
+	}
+
+	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+		 stream->avail_in, stream->avail_out,
+		 req->avail_in - stream->avail_in,
+		 req->avail_out - stream->avail_out);
+	req->next_in = stream->next_in;
+	req->avail_in = stream->avail_in;
+	req->next_out = stream->next_out;
+	req->avail_out = stream->avail_out;
+	return 0;
+}
+
+static int zlib_compress_final(struct crypto_pcomp *tfm,
+			       struct comp_request *req)
+{
+	int ret;
+	struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+	struct z_stream_s *stream = &dctx->comp_stream;
+
+	pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
+	stream->next_in = req->next_in;
+	stream->avail_in = req->avail_in;
+	stream->next_out = req->next_out;
+	stream->avail_out = req->avail_out;
+
+	ret = zlib_deflate(stream, Z_FINISH);
+	if (ret != Z_STREAM_END) {
+		pr_debug("zlib_deflate failed %d\n", ret);
+		return -EINVAL;
+	}
+
+	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+		 stream->avail_in, stream->avail_out,
+		 req->avail_in - stream->avail_in,
+		 req->avail_out - stream->avail_out);
+	req->next_in = stream->next_in;
+	req->avail_in = stream->avail_in;
+	req->next_out = stream->next_out;
+	req->avail_out = stream->avail_out;
+	return 0;
+}
+
+
+static int zlib_decompress_setup(struct crypto_pcomp *tfm, void *params,
+				 unsigned int len)
+{
+	struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+	struct z_stream_s *stream = &ctx->decomp_stream;
+	struct nlattr *tb[ZLIB_DECOMP_MAX + 1];
+	int ret = 0;
+
+	ret = nla_parse(tb, ZLIB_DECOMP_MAX, params, len, NULL);
+	if (ret)
+		return ret;
+
+	zlib_decomp_exit(ctx);
+
+	ctx->decomp_windowBits = tb[ZLIB_DECOMP_WINDOWBITS]
+				 ? nla_get_u32(tb[ZLIB_DECOMP_WINDOWBITS])
+				 : DEF_WBITS;
+
+	stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
+	if (!stream->workspace)
+		return -ENOMEM;
+
+	ret = zlib_inflateInit2(stream, ctx->decomp_windowBits);
+	if (ret != Z_OK) {
+		kfree(stream->workspace);
+		stream->workspace = NULL;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int zlib_decompress_init(struct crypto_pcomp *tfm)
+{
+	int ret;
+	struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+	struct z_stream_s *stream = &dctx->decomp_stream;
+
+	ret = zlib_inflateReset(stream);
+	if (ret != Z_OK)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int zlib_decompress_update(struct crypto_pcomp *tfm,
+				  struct comp_request *req)
+{
+	int ret;
+	struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+	struct z_stream_s *stream = &dctx->decomp_stream;
+
+	pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
+	stream->next_in = req->next_in;
+	stream->avail_in = req->avail_in;
+	stream->next_out = req->next_out;
+	stream->avail_out = req->avail_out;
+
+	ret = zlib_inflate(stream, Z_SYNC_FLUSH);
+	switch (ret) {
+	case Z_OK:
+	case Z_STREAM_END:
+		break;
+
+	case Z_BUF_ERROR:
+		pr_debug("zlib_inflate could not make progress\n");
+		return -EAGAIN;
+
+	default:
+		pr_debug("zlib_inflate failed %d\n", ret);
+		return -EINVAL;
+	}
+
+	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+		 stream->avail_in, stream->avail_out,
+		 req->avail_in - stream->avail_in,
+		 req->avail_out - stream->avail_out);
+	req->next_in = stream->next_in;
+	req->avail_in = stream->avail_in;
+	req->next_out = stream->next_out;
+	req->avail_out = stream->avail_out;
+	return 0;
+}
+
+static int zlib_decompress_final(struct crypto_pcomp *tfm,
+				 struct comp_request *req)
+{
+	int ret;
+	struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+	struct z_stream_s *stream = &dctx->decomp_stream;
+
+	pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
+	stream->next_in = req->next_in;
+	stream->avail_in = req->avail_in;
+	stream->next_out = req->next_out;
+	stream->avail_out = req->avail_out;
+
+	if (dctx->decomp_windowBits < 0) {
+		ret = zlib_inflate(stream, Z_SYNC_FLUSH);
+		/*
+		 * Work around a bug in zlib, which sometimes wants to taste an
+		 * extra byte when being used in the (undocumented) raw deflate
+		 * mode. (From USAGI).
+		 */
+		if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
+			const void *saved_next_in = stream->next_in;
+			u8 zerostuff = 0;
+
+			stream->next_in = &zerostuff;
+			stream->avail_in = 1;
+			ret = zlib_inflate(stream, Z_FINISH);
+			stream->next_in = saved_next_in;
+			stream->avail_in = 0;
+		}
+	} else
+		ret = zlib_inflate(stream, Z_FINISH);
+	if (ret != Z_STREAM_END) {
+		pr_debug("zlib_inflate failed %d\n", ret);
+		return -EINVAL;
+	}
+
+	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+		 stream->avail_in, stream->avail_out,
+		 req->avail_in - stream->avail_in,
+		 req->avail_out - stream->avail_out);
+	req->next_in = stream->next_in;
+	req->avail_in = stream->avail_in;
+	req->next_out = stream->next_out;
+	req->avail_out = stream->avail_out;
+	return 0;
+}
+
+
+static struct pcomp_alg zlib_alg = {
+	.compress_setup		= zlib_compress_setup,
+	.compress_init		= zlib_compress_init,
+	.compress_update	= zlib_compress_update,
+	.compress_final		= zlib_compress_final,
+	.decompress_setup	= zlib_decompress_setup,
+	.decompress_init	= zlib_decompress_init,
+	.decompress_update	= zlib_decompress_update,
+	.decompress_final	= zlib_decompress_final,
+
+	.base			= {
+		.cra_name	= "zlib",
+		.cra_flags	= CRYPTO_ALG_TYPE_PCOMPRESS,
+		.cra_ctxsize	= sizeof(struct zlib_ctx),
+		.cra_module	= THIS_MODULE,
+		.cra_init	= zlib_init,
+		.cra_exit	= zlib_exit,
+	}
+};
+
+static int __init zlib_mod_init(void)
+{
+	return crypto_register_pcomp(&zlib_alg);
+}
+
+static void __exit zlib_mod_fini(void)
+{
+	crypto_unregister_pcomp(&zlib_alg);
+}
+
+module_init(zlib_mod_init);
+module_exit(zlib_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Zlib Compression Algorithm");
+MODULE_AUTHOR("Sony Corporation");
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 765fd1c..bee64b7 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -758,8 +758,7 @@
 	acpi_status status = AE_OK;
 	extern acpi_status acpi_os_initialize1(void);
 
-
-	status = acpi_os_initialize1();
+	acpi_os_initialize1();
 
 	status =
 	    acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
@@ -769,12 +768,6 @@
 		goto error1;
 	}
 
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR PREFIX
-		       "Unable to initialize ACPI OS objects\n");
-		goto error1;
-	}
-
 	/*
 	 * ACPI 2.0 requires the EC driver to be loaded and work before
 	 * the EC device is found in the namespace (i.e. before acpi_initialize_objects()
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 35094f2..7af7db1 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -977,7 +977,7 @@
 		sizeof(struct dock_station *));
 
 	/* we want the dock device to send uevents */
-	dock_device->dev.uevent_suppress = 0;
+	dev_set_uevent_suppress(&dock_device->dev, 0);
 
 	if (is_dock(handle))
 		dock_station->flags |= DOCK_IS_DOCK;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index c5e292a..3a0d8ef 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -277,7 +277,7 @@
 	int pxm, node = -1;
 
 	pxm = acpi_get_pxm(handle);
-	if (pxm >= 0)
+	if (pxm >= 0 && pxm < MAX_PXM_DOMAINS)
 		node = acpi_map_pxm_to_node(pxm);
 
 	return node;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index b3193ec..1e35f34 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1317,54 +1317,6 @@
 	return AE_SUPPORT;
 }
 
-#ifdef	CONFIG_X86
-
-struct aml_port_desc {
-	uint	start;
-	uint	end;
-	char*   name;
-	char	warned;
-};
-
-static struct aml_port_desc aml_invalid_port_list[] = {
-	{0x20, 0x21, "PIC0", 0},
-	{0xA0, 0xA1, "PIC1", 0},
-	{0x4D0, 0x4D1, "ELCR", 0}
-};
-
-/*
- * valid_aml_io_address()
- *
- * if valid, return true
- * else invalid, warn once, return false
- */
-static bool valid_aml_io_address(uint address, uint length)
-{
-	int i;
-	int entries = sizeof(aml_invalid_port_list) / sizeof(struct aml_port_desc);
-
-	for (i = 0; i < entries; ++i) {
-		if ((address >= aml_invalid_port_list[i].start &&
-			address <= aml_invalid_port_list[i].end) ||
-			(address + length >= aml_invalid_port_list[i].start &&
-			address  + length <= aml_invalid_port_list[i].end))
-		{
-			if (!aml_invalid_port_list[i].warned)
-			{
-				printk(KERN_ERR "ACPI: Denied BIOS AML access"
-					" to invalid port 0x%x+0x%x (%s)\n",
-					address, length,
-					aml_invalid_port_list[i].name);
-				aml_invalid_port_list[i].warned = 1;
-			}
-			return false;	/* invalid */
-		}
-	}
-	return true;	/* valid */
-}
-#else
-static inline bool valid_aml_io_address(uint address, uint length) { return true; }
-#endif
 /******************************************************************************
  *
  * FUNCTION:    acpi_os_validate_address
@@ -1394,8 +1346,6 @@
 
 	switch (space_id) {
 	case ACPI_ADR_SPACE_SYSTEM_IO:
-		if (!valid_aml_io_address(address, length))
-			return AE_AML_ILLEGAL_ADDRESS;
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
 		/* Only interference checks against SystemIO and SytemMemory
 		   are needed */
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 5192666..00456fc 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -378,6 +378,22 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
 		},
 	},
+	{
+	.callback = init_old_suspend_ordering,
+	.ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."),
+		DMI_MATCH(DMI_BOARD_NAME, "M2N8L"),
+		},
+	},
+	{
+	.callback = init_set_sci_en_on_resume,
+	.ident = "Toshiba Satellite L300",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"),
+		},
+	},
 	{},
 };
 #endif /* CONFIG_SUSPEND */
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 00c46e0..3d763fd 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -210,7 +210,7 @@
 	dev->dev.release = amba_device_release;
 	dev->dev.bus = &amba_bustype;
 	dev->dev.dma_mask = &dev->dma_mask;
-	dev->res.name = dev->dev.bus_id;
+	dev->res.name = dev_name(&dev->dev);
 
 	if (!dev->dev.coherent_dma_mask && dev->dma_mask)
 		dev_warn(&dev->dev, "coherent dma mask is unset\n");
@@ -294,7 +294,7 @@
 	if (d->parent)
 		r &= d->parent == dev->parent;
 	if (d->busid)
-		r &= strcmp(dev->bus_id, d->busid) == 0;
+		r &= strcmp(dev_name(dev), d->busid) == 0;
 
 	if (r) {
 		get_device(dev);
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index a603bbf..788bba2 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -404,7 +404,7 @@
 	/* board_ahci */
 	{
 		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= 0x1f, /* pio0-4 */
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
@@ -412,7 +412,7 @@
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
 		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= 0x1f, /* pio0-4 */
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_vt8251_ops,
 	},
@@ -420,7 +420,7 @@
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
 		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= 0x1f, /* pio0-4 */
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
@@ -430,7 +430,7 @@
 				 AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
 				 AHCI_HFLAG_SECT255),
 		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= 0x1f, /* pio0-4 */
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_sb600_ops,
 	},
@@ -440,7 +440,7 @@
 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
-		.pio_mask	= 0x1f, /* pio0-4 */
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
@@ -448,7 +448,7 @@
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
 		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= 0x1f, /* pio0-4 */
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_sb600_ops,
 	},
@@ -456,7 +456,7 @@
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_YES_NCQ),
 		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= 0x1f, /* pio0-4 */
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
@@ -464,7 +464,7 @@
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_PMP),
 		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= 0x1f, /* pio0-4 */
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
@@ -582,18 +582,18 @@
 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci },		/* MCP79 */
 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci },		/* MCP79 */
 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci },		/* MCP79 */
-	{ PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci },		/* MCP7B */
-	{ PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci },		/* MCP89 */
+	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci },		/* MCP89 */
 
 	/* SiS */
 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
@@ -1348,7 +1348,7 @@
 	writel(message[1], mmio + hpriv->em_loc+4);
 
 	/* save off new led state for port/slot */
-	emp->led_state = message[1];
+	emp->led_state = state;
 
 	/*
 	 * tell hardware to transmit the message
@@ -2565,6 +2565,15 @@
 			/* PCI slot number of the controller */
 			.driver_data = (void *)0x1FUL,
 		},
+		{
+			.ident = "HP Compaq 6720s",
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
+			},
+			/* PCI slot number of the controller */
+			.driver_data = (void *)0x1FUL,
+		},
 
 		{ }	/* terminate list */
 	};
@@ -2647,8 +2656,8 @@
 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
 
-	if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
-		pci_intx(pdev, 1);
+	if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
+		pci_enable_msi(pdev);
 
 	/* save initial config */
 	ahci_save_initial_config(pdev, hpriv);
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index dc48a63..ecfd22b 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -118,8 +118,8 @@
 	u16 command;
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &generic_port_ops
 	};
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 54961c0..e5cbe80 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -446,34 +446,34 @@
 	[piix_pata_mwdma] = 	/* PIIX3 MWDMA only */
 	{
 		.flags		= PIIX_PATA_FLAGS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
 		.port_ops	= &piix_pata_ops,
 	},
 
 	[piix_pata_33] =	/* PIIX4 at 33MHz */
 	{
 		.flags		= PIIX_PATA_FLAGS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
-		.udma_mask	= ATA_UDMA_MASK_40C,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+		.udma_mask	= ATA_UDMA2,
 		.port_ops	= &piix_pata_ops,
 	},
 
 	[ich_pata_33] = 	/* ICH0 - ICH at 33Mhz*/
 	{
 		.flags		= PIIX_PATA_FLAGS,
-		.pio_mask 	= 0x1f,	/* pio 0-4 */
-		.mwdma_mask	= 0x06, /* Check: maybe 0x07  */
-		.udma_mask	= ATA_UDMA2, /* UDMA33 */
+		.pio_mask 	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok  */
+		.udma_mask	= ATA_UDMA2,
 		.port_ops	= &ich_pata_ops,
 	},
 
 	[ich_pata_66] = 	/* ICH controllers up to 66MHz */
 	{
 		.flags		= PIIX_PATA_FLAGS,
-		.pio_mask 	= 0x1f,	/* pio 0-4 */
-		.mwdma_mask	= 0x06, /* MWDMA0 is broken on chip */
+		.pio_mask 	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */
 		.udma_mask	= ATA_UDMA4,
 		.port_ops	= &ich_pata_ops,
 	},
@@ -481,17 +481,17 @@
 	[ich_pata_100] =
 	{
 		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x06, /* mwdma1-2 */
-		.udma_mask	= ATA_UDMA5, /* udma0-5 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA12_ONLY,
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &ich_pata_ops,
 	},
 
 	[ich5_sata] =
 	{
 		.flags		= PIIX_SATA_FLAGS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
@@ -499,8 +499,8 @@
 	[ich6_sata] =
 	{
 		.flags		= PIIX_SATA_FLAGS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
@@ -508,8 +508,8 @@
 	[ich6m_sata] =
 	{
 		.flags		= PIIX_SATA_FLAGS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
@@ -517,8 +517,8 @@
 	[ich8_sata] =
 	{
 		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
@@ -526,8 +526,8 @@
 	[ich8_2port_sata] =
 	{
 		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
@@ -535,8 +535,8 @@
 	[tolapai_sata] =
 	{
 		.flags		= PIIX_SATA_FLAGS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
@@ -544,8 +544,8 @@
 	[ich8m_apple_sata] =
 	{
 		.flags		= PIIX_SATA_FLAGS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
@@ -553,9 +553,9 @@
 	[piix_pata_vmw] =
 	{
 		.flags		= PIIX_PATA_FLAGS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
-		.udma_mask	= ATA_UDMA_MASK_40C,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+		.udma_mask	= ATA_UDMA2,
 		.port_ops	= &piix_vmw_ops,
 	},
 
@@ -1289,6 +1289,39 @@
 	return map;
 }
 
+static bool piix_no_sidpr(struct ata_host *host)
+{
+	struct pci_dev *pdev = to_pci_dev(host->dev);
+
+	/*
+	 * Samsung DB-P70 only has three ATA ports exposed and
+	 * curiously the unconnected first port reports link online
+	 * while not responding to SRST protocol causing excessive
+	 * detection delay.
+	 *
+	 * Unfortunately, the system doesn't carry enough DMI
+	 * information to identify the machine but does have subsystem
+	 * vendor and device set.  As it's unclear whether the
+	 * subsystem vendor/device is used only for this specific
+	 * board, the port can't be disabled solely with the
+	 * information; however, turning off SIDPR access works around
+	 * the problem.  Turn it off.
+	 *
+	 * This problem is reported in bnc#441240.
+	 *
+	 * https://bugzilla.novell.com/show_bug.cgi?id=441420
+	 */
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 &&
+	    pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
+	    pdev->subsystem_device == 0xb049) {
+		dev_printk(KERN_WARNING, host->dev,
+			   "Samsung DB-P70 detected, disabling SIDPR\n");
+		return true;
+	}
+
+	return false;
+}
+
 static int __devinit piix_init_sidpr(struct ata_host *host)
 {
 	struct pci_dev *pdev = to_pci_dev(host->dev);
@@ -1302,6 +1335,10 @@
 		if (hpriv->map[i] == IDE)
 			return 0;
 
+	/* is it blacklisted? */
+	if (piix_no_sidpr(host))
+		return 0;
+
 	if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
 		return 0;
 
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 9fbf059..e7ea77c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -57,6 +57,7 @@
 #include <linux/scatterlist.h>
 #include <linux/io.h>
 #include <linux/async.h>
+#include <linux/log2.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
@@ -1322,14 +1323,16 @@
 {
 	if (ata_id_has_lba(id)) {
 		if (ata_id_has_lba48(id))
-			return ata_id_u64(id, 100);
+			return ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
 		else
-			return ata_id_u32(id, 60);
+			return ata_id_u32(id, ATA_ID_LBA_CAPACITY);
 	} else {
 		if (ata_id_current_chs_valid(id))
-			return ata_id_u32(id, 57);
+			return id[ATA_ID_CUR_CYLS] * id[ATA_ID_CUR_HEADS] *
+			       id[ATA_ID_CUR_SECTORS];
 		else
-			return id[1] * id[3] * id[6];
+			return id[ATA_ID_CYLS] * id[ATA_ID_HEADS] *
+			       id[ATA_ID_SECTORS];
 	}
 }
 
@@ -2387,6 +2390,7 @@
 	dev->cylinders = 0;
 	dev->heads = 0;
 	dev->sectors = 0;
+	dev->multi_count = 0;
 
 	/*
 	 * common ATA, ATAPI feature tests
@@ -2424,8 +2428,15 @@
 
 		dev->n_sectors = ata_id_n_sectors(id);
 
-		if (dev->id[59] & 0x100)
-			dev->multi_count = dev->id[59] & 0xff;
+		/* get current R/W Multiple count setting */
+		if ((dev->id[47] >> 8) == 0x80 && (dev->id[59] & 0x100)) {
+			unsigned int max = dev->id[47] & 0xff;
+			unsigned int cnt = dev->id[59] & 0xff;
+			/* only recognize/allow powers of two here */
+			if (is_power_of_2(max) && is_power_of_2(cnt))
+				if (cnt <= max)
+					dev->multi_count = cnt;
+		}
 
 		if (ata_id_has_lba(id)) {
 			const char *lba_desc;
@@ -4612,7 +4623,7 @@
 	VPRINTK("unmapping %u sg elements\n", qc->n_elem);
 
 	if (qc->n_elem)
-		dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
+		dma_unmap_sg(ap->dev, sg, qc->orig_n_elem, dir);
 
 	qc->flags &= ~ATA_QCFLAG_DMAMAP;
 	qc->sg = NULL;
@@ -4727,7 +4738,7 @@
 		return -1;
 
 	DPRINTK("%d sg elements mapped\n", n_elem);
-
+	qc->orig_n_elem = qc->n_elem;
 	qc->n_elem = n_elem;
 	qc->flags |= ATA_QCFLAG_DMAMAP;
 
@@ -6707,6 +6718,7 @@
 EXPORT_SYMBOL_GPL(ata_do_dev_read_id);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
+EXPORT_SYMBOL_GPL(ata_pio_queue_task);
 EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
 EXPORT_SYMBOL_GPL(ata_timing_find_mode);
 EXPORT_SYMBOL_GPL(ata_timing_compute);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index ce2ef04..0183131 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -547,7 +547,7 @@
 
 	/* For new EH, all qcs are finished in one of three ways -
 	 * normal completion, error completion, and SCSI timeout.
-	 * Both cmpletions can race against SCSI timeout.  When normal
+	 * Both completions can race against SCSI timeout.  When normal
 	 * completion wins, the qc never reaches EH.  When error
 	 * completion wins, the qc has ATA_QCFLAG_FAILED set.
 	 *
@@ -562,7 +562,19 @@
 		int nr_timedout = 0;
 
 		spin_lock_irqsave(ap->lock, flags);
+		
+		/* This must occur under the ap->lock as we don't want
+		   a polled recovery to race the real interrupt handler
+		   
+		   The lost_interrupt handler checks for any completed but
+		   non-notified command and completes much like an IRQ handler.
+		   
+		   We then fall into the error recovery code which will treat
+		   this as if normal completion won the race */
 
+		if (ap->ops->lost_interrupt)
+			ap->ops->lost_interrupt(ap);
+			
 		list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
 			struct ata_queued_cmd *qc;
 
@@ -606,6 +618,9 @@
 		ap->eh_tries = ATA_EH_MAX_TRIES;
 	} else
 		spin_unlock_wait(ap->lock);
+		
+	/* If we timed raced normal completion and there is nothing to
+	   recover nr_timedout == 0 why exactly are we doing error recovery ? */
 
  repeat:
 	/* invoke error handler */
@@ -2423,11 +2438,14 @@
 		}
 
 		/* prereset() might have cleared ATA_EH_RESET.  If so,
-		 * bang classes and return.
+		 * bang classes, thaw and return.
 		 */
 		if (reset && !(ehc->i.action & ATA_EH_RESET)) {
 			ata_for_each_dev(dev, link, ALL)
 				classes[dev->devno] = ATA_DEV_NONE;
+			if ((ap->pflags & ATA_PFLAG_FROZEN) &&
+			    ata_is_host_link(link))
+				ata_eh_thaw_port(ap);
 			rc = 0;
 			goto out;
 		}
@@ -2901,7 +2919,7 @@
 	int i;
 
 	for (i = 0; i < ATA_EH_UA_TRIES; i++) {
-		u8 sense_buffer[SCSI_SENSE_BUFFERSIZE];
+		u8 *sense_buffer = dev->link->ap->sector_buf;
 		u8 sense_key = 0;
 		unsigned int err_mask;
 
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 714cb04..8332e97 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -52,6 +52,7 @@
 	.softreset		= ata_sff_softreset,
 	.hardreset		= sata_sff_hardreset,
 	.postreset		= ata_sff_postreset,
+	.drain_fifo		= ata_sff_drain_fifo,
 	.error_handler		= ata_sff_error_handler,
 	.post_internal_cmd	= ata_sff_post_internal_cmd,
 
@@ -64,6 +65,8 @@
 	.sff_irq_on		= ata_sff_irq_on,
 	.sff_irq_clear		= ata_sff_irq_clear,
 
+	.lost_interrupt		= ata_sff_lost_interrupt,
+
 	.port_start		= ata_sff_port_start,
 };
 EXPORT_SYMBOL_GPL(ata_sff_port_ops);
@@ -1646,7 +1649,7 @@
  *	RETURNS:
  *	One if interrupt was handled, zero if not (shared irq).
  */
-inline unsigned int ata_sff_host_intr(struct ata_port *ap,
+unsigned int ata_sff_host_intr(struct ata_port *ap,
 				      struct ata_queued_cmd *qc)
 {
 	struct ata_eh_info *ehi = &ap->link.eh_info;
@@ -1775,6 +1778,48 @@
 EXPORT_SYMBOL_GPL(ata_sff_interrupt);
 
 /**
+ *	ata_sff_lost_interrupt	-	Check for an apparent lost interrupt
+ *	@ap: port that appears to have timed out
+ *
+ *	Called from the libata error handlers when the core code suspects
+ *	an interrupt has been lost. If it has complete anything we can and
+ *	then return. Interface must support altstatus for this faster
+ *	recovery to occur.
+ *
+ *	Locking:
+ *	Caller holds host lock
+ */
+
+void ata_sff_lost_interrupt(struct ata_port *ap)
+{
+	u8 status;
+	struct ata_queued_cmd *qc;
+
+	/* Only one outstanding command per SFF channel */
+	qc = ata_qc_from_tag(ap, ap->link.active_tag);
+	/* Check we have a live one.. */
+	if (qc == NULL ||  !(qc->flags & ATA_QCFLAG_ACTIVE))
+		return;
+	/* We cannot lose an interrupt on a polled command */
+	if (qc->tf.flags & ATA_TFLAG_POLLING)
+		return;
+	/* See if the controller thinks it is still busy - if so the command
+	   isn't a lost IRQ but is still in progress */
+	status = ata_sff_altstatus(ap);
+	if (status & ATA_BUSY)
+		return;
+
+	/* There was a command running, we are no longer busy and we have
+	   no interrupt. */
+	ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n",
+								status);
+	/* Run the host interrupt logic as if the interrupt had not been
+	   lost */
+	ata_sff_host_intr(ap, qc);
+}
+EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt);
+
+/**
  *	ata_sff_freeze - Freeze SFF controller port
  *	@ap: port to freeze
  *
@@ -2066,6 +2111,7 @@
 	iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
 	udelay(20);	/* FIXME: flush */
 	iowrite8(ap->ctl, ioaddr->ctl_addr);
+	ap->last_ctl = ap->ctl;
 
 	/* wait the port to become ready */
 	return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
@@ -2190,12 +2236,47 @@
 	}
 
 	/* set up device control */
-	if (ap->ioaddr.ctl_addr)
+	if (ap->ioaddr.ctl_addr) {
 		iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+		ap->last_ctl = ap->ctl;
+	}
 }
 EXPORT_SYMBOL_GPL(ata_sff_postreset);
 
 /**
+ *	ata_sff_drain_fifo - Stock FIFO drain logic for SFF controllers
+ *	@qc: command
+ *
+ *	Drain the FIFO and device of any stuck data following a command
+ *	failing to complete. In some cases this is neccessary before a
+ *	reset will recover the device.
+ *
+ */
+
+void ata_sff_drain_fifo(struct ata_queued_cmd *qc)
+{
+	int count;
+	struct ata_port *ap;
+
+	/* We only need to flush incoming data when a command was running */
+	if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
+		return;
+
+	ap = qc->ap;
+	/* Drain up to 64K of data before we give up this recovery method */
+	for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
+						&& count < 32768; count++)
+		ioread16(ap->ioaddr.data_addr);
+
+	/* Can become DEBUG later */
+	if (count)
+		ata_port_printk(ap, KERN_DEBUG,
+			"drained %d bytes to clear DRQ.\n", count);
+
+}
+EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);
+
+/**
  *	ata_sff_error_handler - Stock error handler for BMDMA controller
  *	@ap: port to handle error for
  *
@@ -2236,7 +2317,8 @@
 		 * really a timeout event, adjust error mask and
 		 * cancel frozen state.
 		 */
-		if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) {
+		if (qc->err_mask == AC_ERR_TIMEOUT
+						&& (host_stat & ATA_DMA_ERR)) {
 			qc->err_mask = AC_ERR_HOST_BUS;
 			thaw = 1;
 		}
@@ -2247,6 +2329,13 @@
 	ata_sff_sync(ap);		/* FIXME: We don't need this */
 	ap->ops->sff_check_status(ap);
 	ap->ops->sff_irq_clear(ap);
+	/* We *MUST* do FIFO draining before we issue a reset as several
+	 * devices helpfully clear their internal state and will lock solid
+	 * if we touch the data port post reset. Pass qc in case anyone wants
+	 *  to do different PIO/DMA recovery or has per command fixups
+	 */
+	if (ap->ops->drain_fifo)
+		ap->ops->drain_fifo(qc);
 
 	spin_unlock_irqrestore(ap->lock, flags);
 
@@ -2534,6 +2623,7 @@
 	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);
+		ap->last_ctl = ap->ctl;
 	}
 
 	DPRINTK("EXIT\n");
@@ -2955,4 +3045,3 @@
 EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
 
 #endif /* CONFIG_PCI */
-
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index cea8014..89a1e00 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -79,8 +79,6 @@
 			   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_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,
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index 8b77a98..d8f35fe 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -246,9 +246,9 @@
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
 
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
-		.udma_mask 	= 0x7f,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask 	= ATA_UDMA6,
 
 		.port_ops	= &pacpi_ops,
 	};
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index eb99dbe..751b7ea 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -492,53 +492,53 @@
 {
 	static const struct ata_port_info info_early = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
+		.pio_mask = ATA_PIO4,
 		.port_ops = &ali_early_port_ops
 	};
 	/* Revision 0x20 added DMA */
 	static const struct ata_port_info info_20 = {
 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.port_ops = &ali_20_port_ops
 	};
 	/* Revision 0x20 with support logic added UDMA */
 	static const struct ata_port_info info_20_udma = {
 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
-		.udma_mask = 0x07,	/* UDMA33 */
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
+		.udma_mask = ATA_UDMA2,
 		.port_ops = &ali_20_port_ops
 	};
 	/* Revision 0xC2 adds UDMA66 */
 	static const struct ata_port_info info_c2 = {
 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA4,
 		.port_ops = &ali_c2_port_ops
 	};
 	/* Revision 0xC3 is UDMA66 for now */
 	static const struct ata_port_info info_c3 = {
 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA4,
 		.port_ops = &ali_c2_port_ops
 	};
 	/* Revision 0xC4 is UDMA100 */
 	static const struct ata_port_info info_c4 = {
 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &ali_c4_port_ops
 	};
 	/* Revision 0xC5 is UDMA133 with LBA48 DMA */
 	static const struct ata_port_info info_c5 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA6,
 		.port_ops = &ali_c5_port_ops
 	};
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 115b1cd..33a74f1 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -455,74 +455,74 @@
 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 */
+		{	/* 0: AMD 7401 - no swdma */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,	/* No SWDMA */
-			.udma_mask = 0x07,	/* UDMA 33 */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA2,
 			.port_ops = &amd33_port_ops
 		},
 		{	/* 1: Early AMD7409 - no swdma */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = ATA_UDMA4,	/* UDMA 66 */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA4,
 			.port_ops = &amd66_port_ops
 		},
-		{	/* 2: AMD 7409, no swdma errata */
+		{	/* 2: AMD 7409 */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = ATA_UDMA4,	/* UDMA 66 */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA4,
 			.port_ops = &amd66_port_ops
 		},
 		{	/* 3: AMD 7411 */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA5,
 			.port_ops = &amd100_port_ops
 		},
 		{	/* 4: AMD 7441 */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA5,
 			.port_ops = &amd100_port_ops
 		},
-		{	/* 5: AMD 8111*/
+		{	/* 5: AMD 8111 - no swdma */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = ATA_UDMA6,	/* UDMA 133, no swdma */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA6,
 			.port_ops = &amd133_port_ops
 		},
-		{	/* 6: AMD 8111 UDMA 100 (Serenade) */
+		{	/* 6: AMD 8111 UDMA 100 (Serenade) - no swdma */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = ATA_UDMA5,	/* UDMA 100, no swdma */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA5,
 			.port_ops = &amd133_port_ops
 		},
 		{	/* 7: Nvidia Nforce */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA5,
 			.port_ops = &nv100_port_ops
 		},
-		{	/* 8: Nvidia Nforce2 and later */
+		{	/* 8: Nvidia Nforce2 and later - no swdma */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = ATA_UDMA6,	/* UDMA 133, no swdma */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA6,
 			.port_ops = &nv133_port_ops
 		},
 		{	/* 9: AMD CS5536 (Geode companion) */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA5,
 			.port_ops = &amd100_port_ops
 		}
 	};
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 6b3092c..d332cfd 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -12,7 +12,6 @@
  *		performance Alessandro Zummo <alessandro.zummo@towertech.it>
  *
  *	TODO
- *	850 serialization once the core supports it
  *	Investigate no_dsc on 850R
  *	Clock detect
  */
@@ -29,7 +28,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_artop"
-#define DRV_VERSION	"0.4.4"
+#define DRV_VERSION	"0.4.5"
 
 /*
  *	The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -283,6 +282,31 @@
 	pci_write_config_byte(pdev, 0x44 + ap->port_no, ultra);
 }
 
+/**
+ *	artop_6210_qc_defer	-	implement serialization
+ *	@qc: command
+ *
+ *	Issue commands per host on this chip.
+ */
+
+static int artop6210_qc_defer(struct ata_queued_cmd *qc)
+{
+	struct ata_host *host = qc->ap->host;
+	struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
+	int rc;
+
+	/* First apply the usual rules */
+	rc = ata_std_qc_defer(qc);
+	if (rc != 0)
+		return rc;
+
+	/* Now apply serialization rules. Only allow a command if the
+	   other channel state machine is idle */
+	if (alt && alt->qc_active)
+		return	ATA_DEFER_PORT;
+	return 0;
+}
+
 static struct scsi_host_template artop_sht = {
 	ATA_BMDMA_SHT(DRV_NAME),
 };
@@ -293,6 +317,7 @@
 	.set_piomode		= artop6210_set_piomode,
 	.set_dmamode		= artop6210_set_dmamode,
 	.prereset		= artop6210_pre_reset,
+	.qc_defer		= artop6210_qc_defer,
 };
 
 static struct ata_port_operations artop6260_ops = {
@@ -323,29 +348,29 @@
 	static int printed_version;
 	static const struct ata_port_info info_6210 = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask 	= ATA_UDMA2,
 		.port_ops	= &artop6210_ops,
 	};
 	static const struct ata_port_info info_626x = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask 	= ATA_UDMA4,
 		.port_ops	= &artop6260_ops,
 	};
 	static const struct ata_port_info info_628x = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask 	= ATA_UDMA5,
 		.port_ops	= &artop6260_ops,
 	};
 	static const struct ata_port_info info_628x_fast = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask 	= ATA_UDMA6,
 		.port_ops	= &artop6260_ops,
 	};
@@ -362,12 +387,8 @@
 
 	if (id->driver_data == 0) {	/* 6210 variant */
 		ppi[0] = &info_6210;
-		ppi[1] = &ata_dummy_port_info;
 		/* BIOS may have left us in UDMA, clear it before libata probe */
 		pci_write_config_byte(pdev, 0x54, 0);
-		/* For the moment (also lacks dsc) */
-		printk(KERN_WARNING "ARTOP 6210 requires serialize functionality not yet supported by libata.\n");
-		printk(KERN_WARNING "Secondary ATA ports will not be activated.\n");
 	}
 	else if (id->driver_data == 1)	/* 6260 */
 		ppi[0] = &info_626x;
diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c
index ab61095..5c129f9 100644
--- a/drivers/ata/pata_at32.c
+++ b/drivers/ata/pata_at32.c
@@ -67,7 +67,9 @@
  *
  * Alter PIO_MASK below according to table to set maximal PIO mode.
  */
-#define PIO_MASK (0x1f)
+enum {
+  PIO_MASK = ATA_PIO4,
+};
 
 /*
  * Struct containing private information about device.
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 506adde..bec0b8a 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -220,9 +220,9 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x06,	/* No MWDMA0 support */
-		.udma_mask = 0x3F,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA12_ONLY,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &atiixp_port_ops
 	};
 	static const struct pci_bits atiixp_enable_bits[] = {
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index 1050fed..c4b47a3 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1502,7 +1502,7 @@
 		.flags		= ATA_FLAG_SLAVE_POSS
 				| ATA_FLAG_MMIO
 				| ATA_FLAG_NO_LEGACY,
-		.pio_mask	= 0x1f,	/* pio0-4 */
+		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= 0,
 		.udma_mask	= 0,
 		.port_ops	= &bfin_pata_ops,
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index 34a3942..5acf9fa 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -211,7 +211,7 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
+		.pio_mask = ATA_PIO4,
 		.port_ops = &cmd640_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 3167d8f..f98dffe 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -299,40 +299,40 @@
 	static const struct ata_port_info cmd_info[6] = {
 		{	/* CMD 643 - no UDMA */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.port_ops = &cmd64x_port_ops
 		},
 		{	/* CMD 646 with broken UDMA */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.port_ops = &cmd64x_port_ops
 		},
 		{	/* CMD 646 with working UDMA */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.udma_mask = ATA_UDMA2,
 			.port_ops = &cmd64x_port_ops
 		},
 		{	/* CMD 646 rev 1  */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.port_ops = &cmd646r1_port_ops
 		},
 		{	/* CMD 648 */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.udma_mask = ATA_UDMA4,
 			.port_ops = &cmd648_port_ops
 		},
 		{	/* CMD 649 */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.udma_mask = ATA_UDMA5,
 			.port_ops = &cmd648_port_ops
 		}
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 1186bcd..db6a969 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -158,7 +158,7 @@
 	static const unsigned int ctl_port[] = { 0x3F6, 0x376 };
 	struct ata_port_info pi = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,
+		.pio_mask	= ATA_PIO4,
 		.port_ops	= &cs5520_port_ops,
 	};
 	const struct ata_port_info *ppi[2];
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index bba4533..c974b05 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -298,15 +298,15 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
-		.udma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
+		.udma_mask = ATA_UDMA2,
 		.port_ops = &cs5530_port_ops
 	};
 	/* The docking connector doesn't do UDMA, and it seems not MWDMA */
 	static const struct ata_port_info info_palmax_secondary = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
+		.pio_mask = ATA_PIO4,
 		.port_ops = &cs5530_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index 8b236af..d33aa28 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -181,8 +181,8 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA4,
 		.port_ops = &cs5535_port_ops
 	};
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
index afed929..6da4cb4 100644
--- a/drivers/ata/pata_cs5536.c
+++ b/drivers/ata/pata_cs5536.c
@@ -241,8 +241,8 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &cs5536_port_ops,
 	};
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index d546425..8fb040b 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -124,8 +124,8 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.port_ops = &cy82c693_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index ac6392e..2085e0a 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -251,9 +251,9 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma1-2 */
-		.udma_mask 	= 0x0f, /* UDMA 66 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask 	= ATA_UDMA4,
 		.port_ops	= &efar_ops,
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 65c28e5..d7f2da1 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -336,8 +336,8 @@
 {
 	static const struct ata_port_info info_hpt366 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA4,
 		.port_ops = &hpt366_port_ops
 	};
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 4216399..81ab5700 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -753,55 +753,55 @@
 	/* HPT370 - UDMA100 */
 	static const struct ata_port_info info_hpt370 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt370_port_ops
 	};
 	/* HPT370A - UDMA100 */
 	static const struct ata_port_info info_hpt370a = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt370a_port_ops
 	};
 	/* HPT370 - UDMA100 */
 	static const struct ata_port_info info_hpt370_33 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt370_port_ops
 	};
 	/* HPT370A - UDMA100 */
 	static const struct ata_port_info info_hpt370a_33 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt370a_port_ops
 	};
 	/* HPT371, 372 and friends - UDMA133 */
 	static const struct ata_port_info info_hpt372 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA6,
 		.port_ops = &hpt372_port_ops
 	};
 	/* 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,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.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,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt374_fn1_port_ops
 	};
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index d5c9fd7..3d59fe0 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -441,8 +441,8 @@
 	/* HPT372N and friends - UDMA133 */
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA6,
 		.port_ops = &hpt3x2n_port_ops
 	};
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index f19cc64..7e31025 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -188,11 +188,11 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
+		.pio_mask = ATA_PIO4,
 #if defined(CONFIG_PATA_HPT3X3_DMA)
 		/* Further debug needed */
-		.mwdma_mask = 0x07,
-		.udma_mask = 0x07,
+		.mwdma_mask = ATA_MWDMA2,
+		.udma_mask = ATA_UDMA2,
 #endif
 		.port_ops = &hpt3x3_port_ops
 	};
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index cf9e984..e7347db 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -297,7 +297,7 @@
 
 	if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
 		state->dma = ec->dma;
-		info->mwdma_mask = 0x07;	/* MW0..2 */
+		info->mwdma_mask = ATA_MWDMA2;
 	}
 
 	return 0;
@@ -473,7 +473,7 @@
 	for (i = 0; i < info->nr_ports; i++) {
 		struct ata_port *ap = host->ports[i];
 
-		ap->pio_mask = 0x1f;
+		ap->pio_mask = ATA_PIO4;
 		ap->mwdma_mask = info->mwdma_mask;
 		ap->flags |= ATA_FLAG_SLAVE_POSS;
 		ap->ops = &pata_icside_port_ops;
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 15cdb91..4bceb88 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -17,7 +17,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_isapnp"
-#define DRV_VERSION "0.2.2"
+#define DRV_VERSION "0.2.5"
 
 static struct scsi_host_template isapnp_sht = {
 	ATA_PIO_SHT(DRV_NAME),
@@ -28,6 +28,13 @@
 	.cable_detect	= ata_cable_40wire,
 };
 
+static struct ata_port_operations isapnp_noalt_port_ops = {
+	.inherits	= &ata_sff_port_ops,
+	.cable_detect	= ata_cable_40wire,
+	/* No altstatus so we don't want to use the lost interrupt poll */
+	.lost_interrupt = ATA_OP_NULL,
+};
+
 /**
  *	isapnp_init_one		-	attach an isapnp interface
  *	@idev: PnP device
@@ -65,8 +72,8 @@
 
 	ap = host->ports[0];
 
-	ap->ops = &isapnp_port_ops;
-	ap->pio_mask = 1;
+	ap->ops = &isapnp_noalt_port_ops;
+	ap->pio_mask = ATA_PIO0;
 	ap->flags |= ATA_FLAG_SLAVE_POSS;
 
 	ap->ioaddr.cmd_addr = cmd_addr;
@@ -76,6 +83,7 @@
 					   pnp_port_start(idev, 1), 1);
 		ap->ioaddr.altstatus_addr = ctl_addr;
 		ap->ioaddr.ctl_addr = ctl_addr;
+		ap->ops = &isapnp_port_ops;
 	}
 
 	ata_sff_std_ports(&ap->ioaddr);
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index c113d7c..f156da8 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -262,8 +262,8 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask 	= ATA_UDMA4, /* FIXME: want UDMA 100? */
 		.port_ops	= &it8213_ops,
 	};
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index b05b86a..188bc2f 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -875,29 +875,29 @@
 
 	static const struct ata_port_info info_smart = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA6,
 		.port_ops = &it821x_smart_port_ops
 	};
 	static const struct ata_port_info info_passthru = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA6,
 		.port_ops = &it821x_passthru_port_ops
 	};
 	static const struct ata_port_info info_rdc = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA6,
 		.port_ops = &it821x_rdc_port_ops
 	};
 	static const struct ata_port_info info_rdc_11 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		/* No UDMA */
 		.port_ops = &it821x_rdc_port_ops
 	};
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index b173c15..19fdecf 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -176,7 +176,7 @@
 	ap = host->ports[0];
 
 	ap->ops	= &ixp4xx_port_ops;
-	ap->pio_mask = 0x1f; /* PIO4 */
+	ap->pio_mask = ATA_PIO4;
 	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
 
 	ixp4xx_setup_port(ap, data, cs0->start, cs1->start);
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 38cf1ab..3a1474a 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -136,8 +136,8 @@
 	static const struct ata_port_info info = {
 		.flags	= ATA_FLAG_SLAVE_POSS,
 
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask 	= ATA_UDMA5,
 
 		.port_ops	= &jmicron_ops,
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index e3bc1b4..3f830f0 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -129,7 +129,7 @@
 static int winbond;		/* Set to probe Winbond controllers,
 					give I/O port if non standard */
 static int autospeed;		/* Chip present which snoops speed changes */
-static int pio_mask = 0x1F;	/* PIO range for autospeed devices */
+static int pio_mask = ATA_PIO4;	/* PIO range for autospeed devices */
 static int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */
 
 /**
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index 76e399b..2096fb7 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -126,8 +126,8 @@
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
 
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask 	= ATA_UDMA5,
 
 		.port_ops	= &marvell_ops,
@@ -136,8 +136,8 @@
 		/* Slave possible as its magically mapped not real */
 		.flags		= ATA_FLAG_SLAVE_POSS,
 
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask 	= ATA_UDMA6,
 
 		.port_ops	= &marvell_ops,
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 50ae6d1..68d27bc7 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -737,10 +737,10 @@
 	 */
 	prop = of_get_property(op->node, "mwdma-mode", &proplen);
 	if ((prop) && (proplen >= 4))
-		mwdma_mask = 0x7 & ((1 << (*prop + 1)) - 1);
+		mwdma_mask = ATA_MWDMA2 & ((1 << (*prop + 1)) - 1);
 	prop = of_get_property(op->node, "udma-mode", &proplen);
 	if ((prop) && (proplen >= 4))
-		udma_mask = 0x7 & ((1 << (*prop + 1)) - 1);
+		udma_mask = ATA_UDMA2 & ((1 << (*prop + 1)) - 1);
 
 	ata_irq = irq_of_parse_and_map(op->node, 0);
 	if (ata_irq == NO_IRQ) {
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index aa576ca..b21f002 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -200,7 +200,7 @@
 	   the MPIIX your box goes castors up */
 
 	ap->ops = &mpiix_port_ops;
-	ap->pio_mask = 0x1F;
+	ap->pio_mask = ATA_PIO4;
 	ap->flags |= ATA_FLAG_SLAVE_POSS;
 
 	ap->ioaddr.cmd_addr = cmd_addr;
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 9dc05e1..bdb2369 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -51,8 +51,8 @@
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		/* Actually we don't really care about these as the
 		   firmware deals with it */
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask 	= ATA_UDMA5, /* UDMA 133 */
 		.port_ops	= &netcell_ops,
 	};
diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
index 4dd9a3b..0fb6b1b1 100644
--- a/drivers/ata/pata_ninja32.c
+++ b/drivers/ata/pata_ninja32.c
@@ -136,7 +136,7 @@
 	if (!base)
 		return -ENOMEM;
 	ap->ops = &ninja32_port_ops;
-	ap->pio_mask = 0x1F;
+	ap->pio_mask = ATA_PIO4;
 	ap->flags |= ATA_FLAG_SLAVE_POSS;
 
 	ap->ioaddr.cmd_addr = base + 0x10;
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 40d411c..ca53fac 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -144,7 +144,7 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x0F,
+		.pio_mask = ATA_PIO3,
 		.port_ops = &ns87410_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
index 89bf5f8..773b159 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -346,8 +346,8 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.port_ops	= &ns87415_pata_ops,
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
@@ -355,8 +355,8 @@
 #if defined(CONFIG_SUPERIO)
 	static const struct ata_port_info info87560 = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.port_ops	= &ns87560_pata_ops,
 	};
 
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index 0fe4ef3..efe2c19 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -871,7 +871,7 @@
 	ap->private_data = cf_port;
 	cf_port->ap = ap;
 	ap->ops = &octeon_cf_ops;
-	ap->pio_mask = 0x7f; /* Support PIO 0-6 */
+	ap->pio_mask = ATA_PIO6;
 	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY
 		  | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING;
 
@@ -900,7 +900,7 @@
 		ap->ioaddr.ctl_addr	= cs1 + (6 << 1) + 1;
 		octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16;
 
-		ap->mwdma_mask	= 0x1f; /* Support MWDMA 0-4 */
+		ap->mwdma_mask	= ATA_MWDMA4;
 		irq = platform_get_irq(pdev, 0);
 		irq_handler = octeon_cf_interrupt;
 
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 2c1a91c..84ac503 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -238,8 +238,8 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma1-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.port_ops	= &oldpiix_pata_ops,
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index e4fa4d5..99eddda 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -163,7 +163,7 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
+		.pio_mask = ATA_PIO4,
 		.port_ops = &opti_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 93bb6e9..86885a4 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -399,15 +399,15 @@
 {
 	static const struct ata_port_info info_82c700 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.port_ops = &optidma_port_ops
 	};
 	static const struct ata_port_info info_82c700_udma = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
-		.udma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
+		.udma_mask = ATA_UDMA2,
 		.port_ops = &optiplus_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info_82c700, NULL };
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 64b2e22..f4d009e 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -42,7 +42,7 @@
 
 
 #define DRV_NAME "pata_pcmcia"
-#define DRV_VERSION "0.3.3"
+#define DRV_VERSION "0.3.5"
 
 /*
  *	Private data structure to glue stuff together
@@ -126,6 +126,37 @@
 	return buflen;
 }
 
+/**
+ *	pcmcia_8bit_drain_fifo - Stock FIFO drain logic for SFF controllers
+ *	@qc: command
+ *
+ *	Drain the FIFO and device of any stuck data following a command
+ *	failing to complete. In some cases this is neccessary before a
+ *	reset will recover the device.
+ *
+ */
+ 
+void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)
+{
+	int count;
+	struct ata_port *ap;
+
+	/* We only need to flush incoming data when a command was running */
+	if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
+		return;
+
+	ap = qc->ap;
+
+	/* Drain up to 64K of data before we give up this recovery method */
+	for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
+							&& count++ < 65536;)
+		ioread8(ap->ioaddr.data_addr);
+
+	if (count)
+		ata_port_printk(ap, KERN_WARNING, "drained %d bytes to clear DRQ.\n",
+								count);
+
+}
 
 static struct scsi_host_template pcmcia_sht = {
 	ATA_PIO_SHT(DRV_NAME),
@@ -143,6 +174,7 @@
 	.sff_data_xfer	= ata_data_xfer_8bit,
 	.cable_detect	= ata_cable_40wire,
 	.set_mode	= pcmcia_set_mode_8bit,
+	.drain_fifo	= pcmcia_8bit_drain_fifo,
 };
 
 #define CS_CHECK(fn, ret) \
@@ -299,7 +331,7 @@
 		ap = host->ports[p];
 
 		ap->ops = ops;
-		ap->pio_mask = 1;		/* ISA so PIO 0 cycles */
+		ap->pio_mask = ATA_PIO0;	/* ISA so PIO 0 cycles */
 		ap->flags |= ATA_FLAG_SLAVE_POSS;
 		ap->ioaddr.cmd_addr = io_addr + 0x10 * p;
 		ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p;
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index e94efcc..ca5cad0 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -152,18 +152,18 @@
 	{
 		.flags		= ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
 		                  ATA_FLAG_MMIO,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= ATA_UDMA5, /* udma0-5 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &pdc2027x_pata100_ops,
 	},
 	/* PDC_UDMA_133 */
 	{
 		.flags		= ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
                         	  ATA_FLAG_MMIO,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= ATA_UDMA6, /* udma0-6 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc2027x_pata133_ops,
 	},
 };
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index 799a6a0..5fedb3d 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -291,22 +291,22 @@
 	static const struct ata_port_info info[3] = {
 		{
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.udma_mask = ATA_UDMA2,
 			.port_ops = &pdc2024x_port_ops
 		},
 		{
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.udma_mask = ATA_UDMA4,
 			.port_ops = &pdc2026x_port_ops
 		},
 		{
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.udma_mask = ATA_UDMA5,
 			.port_ops = &pdc2026x_port_ops
 		}
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index f1b26f7..45879dc 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -212,11 +212,11 @@
 
 	if (type == 6580) {
 		ap->ops = &qdi6580_port_ops;
-		ap->pio_mask = 0x1F;
+		ap->pio_mask = ATA_PIO4;
 		ap->flags |= ATA_FLAG_SLAVE_POSS;
 	} else {
 		ap->ops = &qdi6500_port_ops;
-		ap->pio_mask = 0x07;	/* Actually PIO3 !IORDY is possible */
+		ap->pio_mask = ATA_PIO2; /* Actually PIO3 !IORDY is possible */
 		ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY;
 	}
 
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index 695d44a..4401b33 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -216,9 +216,9 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma1-2 */
-		.udma_mask	= 0x14, /* UDMA33/66 only */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA12_ONLY,
+		.udma_mask	= ATA_UDMA24_ONLY,
 		.port_ops	= &radisys_pata_ops,
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
index ebfcda2..8e3cdef 100644
--- a/drivers/ata/pata_rb532_cf.c
+++ b/drivers/ata/pata_rb532_cf.c
@@ -48,63 +48,11 @@
 struct rb532_cf_info {
 	void __iomem	*iobase;
 	unsigned int	gpio_line;
-	int		frozen;
 	unsigned int	irq;
 };
 
 /* ------------------------------------------------------------------------ */
 
-static inline void rb532_pata_finish_io(struct ata_port *ap)
-{
-	struct ata_host *ah = ap->host;
-	struct rb532_cf_info *info = ah->private_data;
-
-	/* FIXME: Keep previous delay. If this is merely a fence then
-	   ata_sff_sync might be sufficient. */
-	ata_sff_dma_pause(ap);
-	ndelay(RB500_CF_IO_DELAY);
-}
-
-static void rb532_pata_exec_command(struct ata_port *ap,
-				const struct ata_taskfile *tf)
-{
-	writeb(tf->command, ap->ioaddr.command_addr);
-	rb532_pata_finish_io(ap);
-}
-
-static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
-				unsigned int buflen, int write_data)
-{
-	struct ata_port *ap = adev->link->ap;
-	void __iomem *ioaddr = ap->ioaddr.data_addr;
-	int retlen = buflen;
-
-	if (write_data) {
-		for (; buflen > 0; buflen--, buf++)
-			writeb(*buf, ioaddr);
-	} else {
-		for (; buflen > 0; buflen--, buf++)
-			*buf = readb(ioaddr);
-	}
-
-	rb532_pata_finish_io(adev->link->ap);
-	return retlen;
-}
-
-static void rb532_pata_freeze(struct ata_port *ap)
-{
-	struct rb532_cf_info *info = ap->host->private_data;
-
-	info->frozen = 1;
-}
-
-static void rb532_pata_thaw(struct ata_port *ap)
-{
-	struct rb532_cf_info *info = ap->host->private_data;
-
-	info->frozen = 0;
-}
-
 static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
 {
 	struct ata_host *ah = dev_instance;
@@ -112,8 +60,7 @@
 
 	if (gpio_get_value(info->gpio_line)) {
 		set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
-		if (!info->frozen)
-			ata_sff_interrupt(info->irq, dev_instance);
+		ata_sff_interrupt(info->irq, dev_instance);
 	} else {
 		set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
 	}
@@ -123,10 +70,7 @@
 
 static struct ata_port_operations rb532_pata_port_ops = {
 	.inherits		= &ata_sff_port_ops,
-	.sff_exec_command	= rb532_pata_exec_command,
-	.sff_data_xfer		= rb532_pata_data_xfer,
-	.freeze			= rb532_pata_freeze,
-	.thaw			= rb532_pata_thaw,
+	.sff_data_xfer		= ata_sff_data_xfer32,
 };
 
 /* ------------------------------------------------------------------------ */
@@ -145,7 +89,7 @@
 	ap = ah->ports[0];
 
 	ap->ops		= &rb532_pata_port_ops;
-	ap->pio_mask	= 0x1f; /* PIO4 */
+	ap->pio_mask	= ATA_PIO4;
 	ap->flags	= ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
 
 	ap->ioaddr.cmd_addr	= info->iobase + RB500_CF_REG_BASE;
@@ -160,7 +104,7 @@
 
 static __devinit int rb532_pata_driver_probe(struct platform_device *pdev)
 {
-	unsigned int irq;
+	int irq;
 	int gpio;
 	struct resource *res;
 	struct ata_host *ah;
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 46d6bc1..0c574c0 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -88,7 +88,7 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
+		.pio_mask = ATA_PIO4,
 		.port_ops = &rz1000_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 9a4bdca..f49814d 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -2,7 +2,6 @@
  * New ATA layer SC1200 driver		Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  * TODO: Mode selection filtering
- * TODO: Can't enable second channel until ATA core has serialize
  * TODO: Needs custom DMA cleanup code
  *
  * Based very heavily on
@@ -178,6 +177,31 @@
 	return ata_sff_qc_issue(qc);
 }
 
+/**
+ *	sc1200_qc_defer	-	implement serialization
+ *	@qc: command
+ *
+ *	Serialize command issue on this controller.
+ */
+
+static int sc1200_qc_defer(struct ata_queued_cmd *qc)
+{
+	struct ata_host *host = qc->ap->host;
+	struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
+	int rc;
+
+	/* First apply the usual rules */
+	rc = ata_std_qc_defer(qc);
+	if (rc != 0)
+		return rc;
+
+	/* Now apply serialization rules. Only allow a command if the
+	   other channel state machine is idle */
+	if (alt && alt->qc_active)
+		return	ATA_DEFER_PORT;
+	return 0;
+}
+
 static struct scsi_host_template sc1200_sht = {
 	ATA_BMDMA_SHT(DRV_NAME),
 	.sg_tablesize	= LIBATA_DUMB_MAX_PRD,
@@ -187,6 +211,7 @@
 	.inherits	= &ata_bmdma_port_ops,
 	.qc_prep 	= ata_sff_dumb_qc_prep,
 	.qc_issue	= sc1200_qc_issue,
+	.qc_defer	= sc1200_qc_defer,
 	.cable_detect	= ata_cable_40wire,
 	.set_piomode	= sc1200_set_piomode,
 	.set_dmamode	= sc1200_set_dmamode,
@@ -205,13 +230,13 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
-		.udma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
+		.udma_mask = ATA_UDMA2,
 		.port_ops = &sc1200_port_ops
 	};
 	/* Can't enable port 2 yet, see top comments */
-	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
+	const struct ata_port_info *ppi[] = { &info, };
 
 	return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL);
 }
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index d447f1c..4257d6b 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -1001,8 +1001,8 @@
 static struct ata_port_info scc_port_info[] = {
 	{
 		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x00,
+		.pio_mask	= ATA_PIO4,
+		/* No MWDMA */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &scc_pata_ops,
 	},
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c
index 6aeeeeb..99cceb45 100644
--- a/drivers/ata/pata_sch.c
+++ b/drivers/ata/pata_sch.c
@@ -84,9 +84,9 @@
 
 static struct ata_port_info sch_port_info = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
-	.pio_mask	= ATA_PIO4,   /* pio0-4 */
-	.mwdma_mask	= ATA_MWDMA2, /* mwdma0-2 */
-	.udma_mask	= ATA_UDMA5,  /* udma0-5 */
+	.pio_mask	= ATA_PIO4,
+	.mwdma_mask	= ATA_MWDMA2,
+	.udma_mask	= ATA_UDMA5,
 	.port_ops	= &sch_pata_ops,
 };
 
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 8d2fd9d..beaed12 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -398,26 +398,26 @@
 	static const struct ata_port_info info[4] = {
 		{ /* OSB4 */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			.udma_mask = ATA_UDMA2,
 			.port_ops = &serverworks_osb4_port_ops
 		}, { /* OSB4 no UDMA */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
-			.udma_mask = 0x00,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
+			/* No UDMA */
 			.port_ops = &serverworks_osb4_port_ops
 		}, { /* CSB5 */
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.udma_mask = ATA_UDMA4,
 			.port_ops = &serverworks_csb_port_ops
 		}, { /* CSB5 - later revisions*/
 			.flags = ATA_FLAG_SLAVE_POSS,
-			.pio_mask = 0x1f,
-			.mwdma_mask = 0x07,
+			.pio_mask = ATA_PIO4,
+			.mwdma_mask = ATA_MWDMA2,
 			.udma_mask = ATA_UDMA5,
 			.port_ops = &serverworks_csb_port_ops
 		}
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 9e764e5..4cb649d 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -282,15 +282,15 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA6,
 		.port_ops = &sil680_port_ops
 	};
 	static const struct ata_port_info info_slow = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &sil680_port_ops
 	};
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 27ceb42..488e77b 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -552,51 +552,57 @@
 
 static const struct ata_port_info sis_info = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
-	.pio_mask	= 0x1f,	/* pio0-4 */
-	.mwdma_mask	= 0x07,
-	.udma_mask	= 0,
+	.pio_mask	= ATA_PIO4,
+	.mwdma_mask	= ATA_MWDMA2,
+	/* No UDMA */
 	.port_ops	= &sis_old_ops,
 };
 static const struct ata_port_info sis_info33 = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
-	.pio_mask	= 0x1f,	/* pio0-4 */
-	.mwdma_mask	= 0x07,
-	.udma_mask	= ATA_UDMA2,	/* UDMA 33 */
+	.pio_mask	= ATA_PIO4,
+	.mwdma_mask	= ATA_MWDMA2,
+	.udma_mask	= ATA_UDMA2,
 	.port_ops	= &sis_old_ops,
 };
 static const struct ata_port_info sis_info66 = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
-	.pio_mask	= 0x1f,	/* pio0-4 */
-	.udma_mask	= ATA_UDMA4,	/* UDMA 66 */
+	.pio_mask	= ATA_PIO4,
+	/* No MWDMA */
+	.udma_mask	= ATA_UDMA4,
 	.port_ops	= &sis_66_ops,
 };
 static const struct ata_port_info sis_info100 = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
-	.pio_mask	= 0x1f,	/* pio0-4 */
+	.pio_mask	= ATA_PIO4,
+	/* No MWDMA */
 	.udma_mask	= ATA_UDMA5,
 	.port_ops	= &sis_100_ops,
 };
 static const struct ata_port_info sis_info100_early = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
+	.pio_mask	= ATA_PIO4,
+	/* No MWDMA */
 	.udma_mask	= ATA_UDMA5,
-	.pio_mask	= 0x1f,	/* pio0-4 */
 	.port_ops	= &sis_66_ops,
 };
 static const struct ata_port_info sis_info133 = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
-	.pio_mask	= 0x1f,	/* pio0-4 */
+	.pio_mask	= ATA_PIO4,
+	/* No MWDMA */
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_133_ops,
 };
 const struct ata_port_info sis_info133_for_sata = {
 	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
-	.pio_mask	= 0x1f,	/* pio0-4 */
+	.pio_mask	= ATA_PIO4,
+	/* No MWDMA */
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_133_for_sata_ops,
 };
 static const struct ata_port_info sis_info133_early = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
-	.pio_mask	= 0x1f,	/* pio0-4 */
+	.pio_mask	= ATA_PIO4,
+	/* No MWDMA */
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_133_early_ops,
 };
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 1b0e7b6..29f733c 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -283,13 +283,13 @@
 {
 	static const struct ata_port_info info_dma = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.port_ops = &sl82c105_port_ops
 	};
 	static const struct ata_port_info info_early = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
+		.pio_mask = ATA_PIO4,
 		.port_ops = &sl82c105_port_ops
 	};
 	/* for now use only the first port */
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index ef95975..f1f13ff 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -191,8 +191,8 @@
 {
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.port_ops = &triflex_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index ba556d3..b08e6e0 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -422,46 +422,46 @@
 	/* Early VIA without UDMA support */
 	static const struct ata_port_info via_mwdma_info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.port_ops = &via_port_ops
 	};
 	/* Ditto with IRQ masking required */
 	static const struct ata_port_info via_mwdma_info_borked = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.port_ops = &via_port_ops_noirq,
 	};
 	/* VIA UDMA 33 devices (and borked 66) */
 	static const struct ata_port_info via_udma33_info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA2,
 		.port_ops = &via_port_ops
 	};
 	/* VIA UDMA 66 devices */
 	static const struct ata_port_info via_udma66_info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA4,
 		.port_ops = &via_port_ops
 	};
 	/* VIA UDMA 100 devices */
 	static const struct ata_port_info via_udma100_info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &via_port_ops
 	};
 	/* UDMA133 with bad AST (All current 133) */
 	static const struct ata_port_info via_udma133_info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA6,	/* FIXME: should check north bridge */
 		.port_ops = &via_port_ops
 	};
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
index 319e164..6d8619b 100644
--- a/drivers/ata/pata_winbond.c
+++ b/drivers/ata/pata_winbond.c
@@ -193,7 +193,7 @@
 		ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", cmd_port, ctl_port);
 
 		ap->ops = &winbond_port_ops;
-		ap->pio_mask = 0x1F;
+		ap->pio_mask = ATA_PIO4;
 		ap->flags |= ATA_FLAG_SLAVE_POSS;
 		ap->ioaddr.cmd_addr = cmd_addr;
 		ap->ioaddr.altstatus_addr = ctl_addr;
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index be53545..3958817 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -148,6 +148,8 @@
 static struct ata_port_operations adma_ata_ops = {
 	.inherits		= &ata_sff_port_ops,
 
+	.lost_interrupt		= ATA_OP_NULL,
+
 	.check_atapi_dma	= adma_check_atapi_dma,
 	.qc_prep		= adma_qc_prep,
 	.qc_issue		= adma_qc_issue,
@@ -166,7 +168,7 @@
 		.flags		= ATA_FLAG_SLAVE_POSS |
 				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
 				  ATA_FLAG_PIO_POLLING,
-		.pio_mask	= 0x10, /* pio4 */
+		.pio_mask	= ATA_PIO4_ONLY,
 		.udma_mask	= ATA_UDMA4,
 		.port_ops	= &adma_ata_ops,
 	},
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 55bc88c..c2e90e1 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -1279,8 +1279,8 @@
 static const struct ata_port_info sata_fsl_port_info[] = {
 	{
 	 .flags = SATA_FSL_HOST_FLAGS,
-	 .pio_mask = 0x1f,	/* pio 0-4 */
-	 .udma_mask = 0x7f,	/* udma 0-6 */
+	 .pio_mask = ATA_PIO4,
+	 .udma_mask = ATA_UDMA6,
 	 .port_ops = &sata_fsl_ops,
 	 },
 };
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index fbbd87c..305a4f8 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -744,8 +744,8 @@
 
 static struct ata_port_info inic_port_info = {
 	.flags			= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
-	.pio_mask		= 0x1f,	/* pio0-4 */
-	.mwdma_mask		= 0x07, /* mwdma0-2 */
+	.pio_mask		= ATA_PIO4,
+	.mwdma_mask		= ATA_MWDMA2,
 	.udma_mask		= ATA_UDMA6,
 	.port_ops		= &inic_port_ops
 };
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 7007edd..a377226 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1,10 +1,13 @@
 /*
  * sata_mv.c - Marvell SATA support
  *
- * Copyright 2008: Marvell Corporation, all rights reserved.
+ * Copyright 2008-2009: Marvell Corporation, all rights reserved.
  * Copyright 2005: EMC Corporation, all rights reserved.
  * Copyright 2005 Red Hat, Inc.  All rights reserved.
  *
+ * Originally written by Brett Russ.
+ * Extensive overhaul and enhancement by Mark Lord <mlord@pobox.com>.
+ *
  * Please ALWAYS copy linux-ide@vger.kernel.org on emails.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -25,20 +28,13 @@
 /*
  * 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).
- *
  * --> 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.
+ * --> Add sysfs attributes for per-chip / per-HC IRQ coalescing thresholds.
  *
  * --> [Experiment, Marvell value added] Is it possible to use target
  *       mode to cross-connect two Linux boxes with Marvell cards?  If so,
@@ -68,7 +64,27 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_mv"
-#define DRV_VERSION	"1.25"
+#define DRV_VERSION	"1.27"
+
+/*
+ * module options
+ */
+
+static int msi;
+#ifdef CONFIG_PCI
+module_param(msi, int, S_IRUGO);
+MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
+#endif
+
+static int irq_coalescing_io_count;
+module_param(irq_coalescing_io_count, int, S_IRUGO);
+MODULE_PARM_DESC(irq_coalescing_io_count,
+		 "IRQ coalescing I/O count threshold (0..255)");
+
+static int irq_coalescing_usecs;
+module_param(irq_coalescing_usecs, int, S_IRUGO);
+MODULE_PARM_DESC(irq_coalescing_usecs,
+		 "IRQ coalescing time threshold in usecs");
 
 enum {
 	/* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -79,13 +95,32 @@
 	MV_MAJOR_REG_AREA_SZ	= 0x10000,	/* 64KB */
 	MV_MINOR_REG_AREA_SZ	= 0x2000,	/* 8KB */
 
+	/* For use with both IRQ coalescing methods ("all ports" or "per-HC" */
+	COAL_CLOCKS_PER_USEC	= 150,		/* for calculating COAL_TIMEs */
+	MAX_COAL_TIME_THRESHOLD	= ((1 << 24) - 1), /* internal clocks count */
+	MAX_COAL_IO_COUNT	= 255,		/* completed I/O count */
+
 	MV_PCI_REG_BASE		= 0,
-	MV_IRQ_COAL_REG_BASE	= 0x18000,	/* 6xxx part only */
-	MV_IRQ_COAL_CAUSE		= (MV_IRQ_COAL_REG_BASE + 0x08),
-	MV_IRQ_COAL_CAUSE_LO		= (MV_IRQ_COAL_REG_BASE + 0x88),
-	MV_IRQ_COAL_CAUSE_HI		= (MV_IRQ_COAL_REG_BASE + 0x8c),
-	MV_IRQ_COAL_THRESHOLD		= (MV_IRQ_COAL_REG_BASE + 0xcc),
-	MV_IRQ_COAL_TIME_THRESHOLD	= (MV_IRQ_COAL_REG_BASE + 0xd0),
+
+	/*
+	 * Per-chip ("all ports") interrupt coalescing feature.
+	 * This is only for GEN_II / GEN_IIE hardware.
+	 *
+	 * Coalescing defers the interrupt until either the IO_THRESHOLD
+	 * (count of completed I/Os) is met, or the TIME_THRESHOLD is met.
+	 */
+	MV_COAL_REG_BASE	= 0x18000,
+	MV_IRQ_COAL_CAUSE	= (MV_COAL_REG_BASE + 0x08),
+	ALL_PORTS_COAL_IRQ	= (1 << 4),	/* all ports irq event */
+
+	MV_IRQ_COAL_IO_THRESHOLD   = (MV_COAL_REG_BASE + 0xcc),
+	MV_IRQ_COAL_TIME_THRESHOLD = (MV_COAL_REG_BASE + 0xd0),
+
+	/*
+	 * Registers for the (unused here) transaction coalescing feature:
+	 */
+	MV_TRAN_COAL_CAUSE_LO	= (MV_COAL_REG_BASE + 0x88),
+	MV_TRAN_COAL_CAUSE_HI	= (MV_COAL_REG_BASE + 0x8c),
 
 	MV_SATAHC0_REG_BASE	= 0x20000,
 	MV_FLASH_CTL_OFS	= 0x1046c,
@@ -117,17 +152,16 @@
 
 	/* Host Flags */
 	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
-	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
 
 	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
-				  ATA_FLAG_PIO_POLLING,
+				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
 
-	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
+	MV_GEN_I_FLAGS		= MV_COMMON_FLAGS | ATA_FLAG_NO_ATAPI,
 
-	MV_GENIIE_FLAGS		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-				  ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
-				  ATA_FLAG_NCQ | ATA_FLAG_AN,
+	MV_GEN_II_FLAGS		= MV_COMMON_FLAGS | ATA_FLAG_NCQ |
+				  ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA,
+
+	MV_GEN_IIE_FLAGS	= MV_GEN_II_FLAGS | ATA_FLAG_AN,
 
 	CRQB_FLAG_READ		= (1 << 0),
 	CRQB_TAG_SHIFT		= 1,
@@ -180,16 +214,18 @@
 	PCI_HC_MAIN_IRQ_MASK_OFS  = 0x1d64,
 	SOC_HC_MAIN_IRQ_CAUSE_OFS = 0x20020,
 	SOC_HC_MAIN_IRQ_MASK_OFS  = 0x20024,
-	ERR_IRQ			= (1 << 0),	/* shift by port # */
-	DONE_IRQ		= (1 << 1),	/* shift by port # */
+	ERR_IRQ			= (1 << 0),	/* shift by (2 * port #) */
+	DONE_IRQ		= (1 << 1),	/* shift by (2 * port #) */
 	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
 	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
+	DONE_IRQ_0_3		= 0x000000aa,	/* DONE_IRQ ports 0,1,2,3 */
+	DONE_IRQ_4_7		= (DONE_IRQ_0_3 << HC_SHIFT),  /* 4,5,6,7 */
 	PCI_ERR			= (1 << 18),
-	TRAN_LO_DONE		= (1 << 19),	/* 6xxx: IRQ coalescing */
-	TRAN_HI_DONE		= (1 << 20),	/* 6xxx: IRQ coalescing */
-	PORTS_0_3_COAL_DONE	= (1 << 8),
-	PORTS_4_7_COAL_DONE	= (1 << 17),
-	PORTS_0_7_COAL_DONE	= (1 << 21),	/* 6xxx: IRQ coalescing */
+	TRAN_COAL_LO_DONE	= (1 << 19),	/* transaction coalescing */
+	TRAN_COAL_HI_DONE	= (1 << 20),	/* transaction coalescing */
+	PORTS_0_3_COAL_DONE	= (1 << 8),	/* HC0 IRQ coalescing */
+	PORTS_4_7_COAL_DONE	= (1 << 17),	/* HC1 IRQ coalescing */
+	ALL_PORTS_COAL_DONE	= (1 << 21),	/* GEN_II(E) IRQ coalescing */
 	GPIO_INT		= (1 << 22),
 	SELF_INT		= (1 << 23),
 	TWSI_INT		= (1 << 24),
@@ -205,6 +241,21 @@
 	HC_COAL_IRQ		= (1 << 4),	/* IRQ coalescing */
 	DEV_IRQ			= (1 << 8),	/* shift by port # */
 
+	/*
+	 * Per-HC (Host-Controller) interrupt coalescing feature.
+	 * This is present on all chip generations.
+	 *
+	 * Coalescing defers the interrupt until either the IO_THRESHOLD
+	 * (count of completed I/Os) is met, or the TIME_THRESHOLD is met.
+	 */
+	HC_IRQ_COAL_IO_THRESHOLD_OFS	= 0x000c,
+	HC_IRQ_COAL_TIME_THRESHOLD_OFS	= 0x0010,
+
+	SOC_LED_CTRL_OFS	= 0x2c,
+	SOC_LED_CTRL_BLINK	= (1 << 0),	/* Active LED blink */
+	SOC_LED_CTRL_ACT_PRESENCE = (1 << 2),	/* Multiplex dev presence */
+						/*  with dev activity LED */
+
 	/* Shadow block registers */
 	SHD_BLK_OFS		= 0x100,
 	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
@@ -346,6 +397,12 @@
 	EDMA_ARB_CFG_OFS	= 0x38,
 
 	EDMA_HALTCOND_OFS	= 0x60,		/* GenIIe halt conditions */
+	EDMA_UNKNOWN_RSVD_OFS	= 0x6C,		/* GenIIe unknown/reserved */
+
+	BMDMA_CMD_OFS		= 0x224,	/* bmdma command register */
+	BMDMA_STATUS_OFS	= 0x228,	/* bmdma status register */
+	BMDMA_PRD_LOW_OFS	= 0x22c,	/* bmdma PRD addr 31:0 */
+	BMDMA_PRD_HIGH_OFS	= 0x230,	/* bmdma PRD addr 63:32 */
 
 	/* Host private flags (hp_flags) */
 	MV_HP_FLAG_MSI		= (1 << 0),
@@ -359,12 +416,14 @@
 	MV_HP_PCIE		= (1 << 9),	/* PCIe bus/regs: 7042 */
 	MV_HP_CUT_THROUGH	= (1 << 10),	/* can use EDMA cut-through */
 	MV_HP_FLAG_SOC		= (1 << 11),	/* SystemOnChip, no PCI */
+	MV_HP_QUIRK_LED_BLINK_EN = (1 << 12),	/* is led blinking enabled? */
 
 	/* 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_FBS_EN	= (1 << 2),	/* is EDMA set up for FBS? */
 	MV_PP_FLAG_DELAYED_EH	= (1 << 3),	/* delayed dev err handling */
+	MV_PP_FLAG_FAKE_ATA_BUSY = (1 << 4),	/* ignore initial ATA_DRDY */
 };
 
 #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
@@ -433,6 +492,18 @@
 	__le32			reserved;
 };
 
+/*
+ * We keep a local cache of a few frequently accessed port
+ * registers here, to avoid having to read them (very slow)
+ * when switching between EDMA and non-EDMA modes.
+ */
+struct mv_cached_regs {
+	u32			fiscfg;
+	u32			ltmode;
+	u32			haltcond;
+	u32			unknown_rsvd;
+};
+
 struct mv_port_priv {
 	struct mv_crqb		*crqb;
 	dma_addr_t		crqb_dma;
@@ -445,6 +516,7 @@
 	unsigned int		resp_idx;
 
 	u32			pp_flags;
+	struct mv_cached_regs	cached;
 	unsigned int		delayed_eh_pmp_map;
 };
 
@@ -535,7 +607,7 @@
 			     unsigned int port_no);
 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_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma);
 
 static void mv_pmp_select(struct ata_port *ap, int pmp);
 static int mv_pmp_hardreset(struct ata_link *link, unsigned int *class,
@@ -546,6 +618,14 @@
 static void mv_process_crpb_entries(struct ata_port *ap,
 					struct mv_port_priv *pp);
 
+static void mv_sff_irq_clear(struct ata_port *ap);
+static int mv_check_atapi_dma(struct ata_queued_cmd *qc);
+static void mv_bmdma_setup(struct ata_queued_cmd *qc);
+static void mv_bmdma_start(struct ata_queued_cmd *qc);
+static void mv_bmdma_stop(struct ata_queued_cmd *qc);
+static u8   mv_bmdma_status(struct ata_port *ap);
+static u8 mv_sff_check_status(struct ata_port *ap);
+
 /* .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().
@@ -566,6 +646,8 @@
 static struct ata_port_operations mv5_ops = {
 	.inherits		= &ata_sff_port_ops,
 
+	.lost_interrupt		= ATA_OP_NULL,
+
 	.qc_defer		= mv_qc_defer,
 	.qc_prep		= mv_qc_prep,
 	.qc_issue		= mv_qc_issue,
@@ -593,6 +675,14 @@
 	.pmp_softreset		= mv_softreset,
 	.softreset		= mv_softreset,
 	.error_handler		= mv_pmp_error_handler,
+
+	.sff_check_status	= mv_sff_check_status,
+	.sff_irq_clear		= mv_sff_irq_clear,
+	.check_atapi_dma	= mv_check_atapi_dma,
+	.bmdma_setup		= mv_bmdma_setup,
+	.bmdma_start		= mv_bmdma_start,
+	.bmdma_stop		= mv_bmdma_stop,
+	.bmdma_status		= mv_bmdma_status,
 };
 
 static struct ata_port_operations mv_iie_ops = {
@@ -603,53 +693,49 @@
 
 static const struct ata_port_info mv_port_info[] = {
 	{  /* chip_504x */
-		.flags		= MV_COMMON_FLAGS,
+		.flags		= MV_GEN_I_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_508x */
-		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
+		.flags		= MV_GEN_I_FLAGS | MV_FLAG_DUAL_HC,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_5080 */
-		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
+		.flags		= MV_GEN_I_FLAGS | MV_FLAG_DUAL_HC,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_604x */
-		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-				  ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
-				  ATA_FLAG_NCQ,
+		.flags		= MV_GEN_II_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv6_ops,
 	},
 	{  /* chip_608x */
-		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-				  ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
-				  ATA_FLAG_NCQ | MV_FLAG_DUAL_HC,
+		.flags		= MV_GEN_II_FLAGS | MV_FLAG_DUAL_HC,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv6_ops,
 	},
 	{  /* chip_6042 */
-		.flags		= MV_GENIIE_FLAGS,
+		.flags		= MV_GEN_IIE_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv_iie_ops,
 	},
 	{  /* chip_7042 */
-		.flags		= MV_GENIIE_FLAGS,
+		.flags		= MV_GEN_IIE_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv_iie_ops,
 	},
 	{  /* chip_soc */
-		.flags		= MV_GENIIE_FLAGS,
+		.flags		= MV_GEN_IIE_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv_iie_ops,
@@ -794,6 +880,44 @@
 	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
 }
 
+/**
+ *      mv_save_cached_regs - (re-)initialize cached port registers
+ *      @ap: the port whose registers we are caching
+ *
+ *	Initialize the local cache of port registers,
+ *	so that reading them over and over again can
+ *	be avoided on the hotter paths of this driver.
+ *	This saves a few microseconds each time we switch
+ *	to/from EDMA mode to perform (eg.) a drive cache flush.
+ */
+static void mv_save_cached_regs(struct ata_port *ap)
+{
+	void __iomem *port_mmio = mv_ap_base(ap);
+	struct mv_port_priv *pp = ap->private_data;
+
+	pp->cached.fiscfg = readl(port_mmio + FISCFG_OFS);
+	pp->cached.ltmode = readl(port_mmio + LTMODE_OFS);
+	pp->cached.haltcond = readl(port_mmio + EDMA_HALTCOND_OFS);
+	pp->cached.unknown_rsvd = readl(port_mmio + EDMA_UNKNOWN_RSVD_OFS);
+}
+
+/**
+ *      mv_write_cached_reg - write to a cached port register
+ *      @addr: hardware address of the register
+ *      @old: pointer to cached value of the register
+ *      @new: new value for the register
+ *
+ *	Write a new value to a cached register,
+ *	but only if the value is different from before.
+ */
+static inline void mv_write_cached_reg(void __iomem *addr, u32 *old, u32 new)
+{
+	if (new != *old) {
+		*old = new;
+		writel(new, addr);
+	}
+}
+
 static void mv_set_edma_ptrs(void __iomem *port_mmio,
 			     struct mv_host_priv *hpriv,
 			     struct mv_port_priv *pp)
@@ -825,6 +949,23 @@
 		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 }
 
+static void mv_write_main_irq_mask(u32 mask, struct mv_host_priv *hpriv)
+{
+	/*
+	 * When writing to the main_irq_mask in hardware,
+	 * we must ensure exclusivity between the interrupt coalescing bits
+	 * and the corresponding individual port DONE_IRQ bits.
+	 *
+	 * Note that this register is really an "IRQ enable" register,
+	 * not an "IRQ mask" register as Marvell's naming might suggest.
+	 */
+	if (mask & (ALL_PORTS_COAL_DONE | PORTS_0_3_COAL_DONE))
+		mask &= ~DONE_IRQ_0_3;
+	if (mask & (ALL_PORTS_COAL_DONE | PORTS_4_7_COAL_DONE))
+		mask &= ~DONE_IRQ_4_7;
+	writelfl(mask, hpriv->main_irq_mask_addr);
+}
+
 static void mv_set_main_irq_mask(struct ata_host *host,
 				 u32 disable_bits, u32 enable_bits)
 {
@@ -835,7 +976,7 @@
 	new_mask = (old_mask & ~disable_bits) | enable_bits;
 	if (new_mask != old_mask) {
 		hpriv->main_irq_mask = new_mask;
-		writelfl(new_mask, hpriv->main_irq_mask_addr);
+		mv_write_main_irq_mask(new_mask, hpriv);
 	}
 }
 
@@ -852,8 +993,94 @@
 	mv_set_main_irq_mask(ap->host, disable_bits, enable_bits);
 }
 
+static void mv_clear_and_enable_port_irqs(struct ata_port *ap,
+					  void __iomem *port_mmio,
+					  unsigned int port_irqs)
+{
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	int hardport = mv_hardport_from_port(ap->port_no);
+	void __iomem *hc_mmio = mv_hc_base_from_port(
+				mv_host_base(ap->host), ap->port_no);
+	u32 hc_irq_cause;
+
+	/* clear EDMA event indicators, if any */
+	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+	/* clear pending irq events */
+	hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport);
+	writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+
+	/* clear FIS IRQ Cause */
+	if (IS_GEN_IIE(hpriv))
+		writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
+
+	mv_enable_port_irqs(ap, port_irqs);
+}
+
+static void mv_set_irq_coalescing(struct ata_host *host,
+				  unsigned int count, unsigned int usecs)
+{
+	struct mv_host_priv *hpriv = host->private_data;
+	void __iomem *mmio = hpriv->base, *hc_mmio;
+	u32 coal_enable = 0;
+	unsigned long flags;
+	unsigned int clks, is_dual_hc = hpriv->n_ports > MV_PORTS_PER_HC;
+	const u32 coal_disable = PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
+							ALL_PORTS_COAL_DONE;
+
+	/* Disable IRQ coalescing if either threshold is zero */
+	if (!usecs || !count) {
+		clks = count = 0;
+	} else {
+		/* Respect maximum limits of the hardware */
+		clks = usecs * COAL_CLOCKS_PER_USEC;
+		if (clks > MAX_COAL_TIME_THRESHOLD)
+			clks = MAX_COAL_TIME_THRESHOLD;
+		if (count > MAX_COAL_IO_COUNT)
+			count = MAX_COAL_IO_COUNT;
+	}
+
+	spin_lock_irqsave(&host->lock, flags);
+	mv_set_main_irq_mask(host, coal_disable, 0);
+
+	if (is_dual_hc && !IS_GEN_I(hpriv)) {
+		/*
+		 * GEN_II/GEN_IIE with dual host controllers:
+		 * one set of global thresholds for the entire chip.
+		 */
+		writel(clks,  mmio + MV_IRQ_COAL_TIME_THRESHOLD);
+		writel(count, mmio + MV_IRQ_COAL_IO_THRESHOLD);
+		/* clear leftover coal IRQ bit */
+		writel(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE);
+		if (count)
+			coal_enable = ALL_PORTS_COAL_DONE;
+		clks = count = 0; /* force clearing of regular regs below */
+	}
+
+	/*
+	 * All chips: independent thresholds for each HC on the chip.
+	 */
+	hc_mmio = mv_hc_base_from_port(mmio, 0);
+	writel(clks,  hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS);
+	writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS);
+	writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS);
+	if (count)
+		coal_enable |= PORTS_0_3_COAL_DONE;
+	if (is_dual_hc) {
+		hc_mmio = mv_hc_base_from_port(mmio, MV_PORTS_PER_HC);
+		writel(clks,  hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS);
+		writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS);
+		writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS);
+		if (count)
+			coal_enable |= PORTS_4_7_COAL_DONE;
+	}
+
+	mv_set_main_irq_mask(host, 0, coal_enable);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
 /**
- *      mv_start_dma - Enable eDMA engine
+ *      mv_start_edma - Enable eDMA engine
  *      @base: port base address
  *      @pp: port private data
  *
@@ -863,7 +1090,7 @@
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
+static void mv_start_edma(struct ata_port *ap, void __iomem *port_mmio,
 			 struct mv_port_priv *pp, u8 protocol)
 {
 	int want_ncq = (protocol == ATA_PROT_NCQ);
@@ -875,26 +1102,11 @@
 	}
 	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
 		struct mv_host_priv *hpriv = ap->host->private_data;
-		int hardport = mv_hardport_from_port(ap->port_no);
-		void __iomem *hc_mmio = mv_hc_base_from_port(
-					mv_host_base(ap->host), ap->port_no);
-		u32 hc_irq_cause;
 
-		/* clear EDMA event indicators, if any */
-		writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-
-		/* clear pending irq events */
-		hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport);
-		writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
-
-		mv_edma_cfg(ap, want_ncq);
-
-		/* clear FIS IRQ Cause */
-		if (IS_GEN_IIE(hpriv))
-			writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
+		mv_edma_cfg(ap, want_ncq, 1);
 
 		mv_set_edma_ptrs(port_mmio, hpriv, pp);
-		mv_enable_port_irqs(ap, DONE_IRQ|ERR_IRQ);
+		mv_clear_and_enable_port_irqs(ap, port_mmio, DONE_IRQ|ERR_IRQ);
 
 		writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
 		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
@@ -952,6 +1164,7 @@
 {
 	void __iomem *port_mmio = mv_ap_base(ap);
 	struct mv_port_priv *pp = ap->private_data;
+	int err = 0;
 
 	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN))
 		return 0;
@@ -959,9 +1172,10 @@
 	mv_wait_for_edma_empty_idle(ap);
 	if (mv_stop_edma_engine(port_mmio)) {
 		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
-		return -EIO;
+		err = -EIO;
 	}
-	return 0;
+	mv_edma_cfg(ap, 0, 0);
+	return err;
 }
 
 #ifdef ATA_DEBUG
@@ -1130,35 +1344,33 @@
 	return ATA_DEFER_PORT;
 }
 
-static void mv_config_fbs(void __iomem *port_mmio, int want_ncq, int want_fbs)
+static void mv_config_fbs(struct ata_port *ap, int want_ncq, int want_fbs)
 {
-	u32 new_fiscfg, old_fiscfg;
-	u32 new_ltmode, old_ltmode;
-	u32 new_haltcond, old_haltcond;
+	struct mv_port_priv *pp = ap->private_data;
+	void __iomem *port_mmio;
 
-	old_fiscfg   = readl(port_mmio + FISCFG_OFS);
-	old_ltmode   = readl(port_mmio + LTMODE_OFS);
-	old_haltcond = readl(port_mmio + EDMA_HALTCOND_OFS);
+	u32 fiscfg,   *old_fiscfg   = &pp->cached.fiscfg;
+	u32 ltmode,   *old_ltmode   = &pp->cached.ltmode;
+	u32 haltcond, *old_haltcond = &pp->cached.haltcond;
 
-	new_fiscfg   = old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR);
-	new_ltmode   = old_ltmode & ~LTMODE_BIT8;
-	new_haltcond = old_haltcond | EDMA_ERR_DEV;
+	ltmode   = *old_ltmode & ~LTMODE_BIT8;
+	haltcond = *old_haltcond | EDMA_ERR_DEV;
 
 	if (want_fbs) {
-		new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC;
-		new_ltmode = old_ltmode | LTMODE_BIT8;
+		fiscfg = *old_fiscfg | FISCFG_SINGLE_SYNC;
+		ltmode = *old_ltmode | LTMODE_BIT8;
 		if (want_ncq)
-			new_haltcond &= ~EDMA_ERR_DEV;
+			haltcond &= ~EDMA_ERR_DEV;
 		else
-			new_fiscfg |=  FISCFG_WAIT_DEV_ERR;
+			fiscfg |=  FISCFG_WAIT_DEV_ERR;
+	} else {
+		fiscfg = *old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR);
 	}
 
-	if (new_fiscfg != old_fiscfg)
-		writelfl(new_fiscfg, port_mmio + FISCFG_OFS);
-	if (new_ltmode != old_ltmode)
-		writelfl(new_ltmode, port_mmio + LTMODE_OFS);
-	if (new_haltcond != old_haltcond)
-		writelfl(new_haltcond, port_mmio + EDMA_HALTCOND_OFS);
+	port_mmio = mv_ap_base(ap);
+	mv_write_cached_reg(port_mmio + FISCFG_OFS, old_fiscfg, fiscfg);
+	mv_write_cached_reg(port_mmio + LTMODE_OFS, old_ltmode, ltmode);
+	mv_write_cached_reg(port_mmio + EDMA_HALTCOND_OFS, old_haltcond, haltcond);
 }
 
 static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq)
@@ -1176,7 +1388,86 @@
 		writel(new, hpriv->base + MV_GPIO_PORT_CTL_OFS);
 }
 
-static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
+/**
+ *	mv_bmdma_enable - set a magic bit on GEN_IIE to allow bmdma
+ *	@ap: Port being initialized
+ *
+ *	There are two DMA modes on these chips:  basic DMA, and EDMA.
+ *
+ *	Bit-0 of the "EDMA RESERVED" register enables/disables use
+ *	of basic DMA on the GEN_IIE versions of the chips.
+ *
+ *	This bit survives EDMA resets, and must be set for basic DMA
+ *	to function, and should be cleared when EDMA is active.
+ */
+static void mv_bmdma_enable_iie(struct ata_port *ap, int enable_bmdma)
+{
+	struct mv_port_priv *pp = ap->private_data;
+	u32 new, *old = &pp->cached.unknown_rsvd;
+
+	if (enable_bmdma)
+		new = *old | 1;
+	else
+		new = *old & ~1;
+	mv_write_cached_reg(mv_ap_base(ap) + EDMA_UNKNOWN_RSVD_OFS, old, new);
+}
+
+/*
+ * SOC chips have an issue whereby the HDD LEDs don't always blink
+ * during I/O when NCQ is enabled. Enabling a special "LED blink" mode
+ * of the SOC takes care of it, generating a steady blink rate when
+ * any drive on the chip is active.
+ *
+ * Unfortunately, the blink mode is a global hardware setting for the SOC,
+ * so we must use it whenever at least one port on the SOC has NCQ enabled.
+ *
+ * We turn "LED blink" off when NCQ is not in use anywhere, because the normal
+ * LED operation works then, and provides better (more accurate) feedback.
+ *
+ * Note that this code assumes that an SOC never has more than one HC onboard.
+ */
+static void mv_soc_led_blink_enable(struct ata_port *ap)
+{
+	struct ata_host *host = ap->host;
+	struct mv_host_priv *hpriv = host->private_data;
+	void __iomem *hc_mmio;
+	u32 led_ctrl;
+
+	if (hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN)
+		return;
+	hpriv->hp_flags |= MV_HP_QUIRK_LED_BLINK_EN;
+	hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no);
+	led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS);
+	writel(led_ctrl | SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS);
+}
+
+static void mv_soc_led_blink_disable(struct ata_port *ap)
+{
+	struct ata_host *host = ap->host;
+	struct mv_host_priv *hpriv = host->private_data;
+	void __iomem *hc_mmio;
+	u32 led_ctrl;
+	unsigned int port;
+
+	if (!(hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN))
+		return;
+
+	/* disable led-blink only if no ports are using NCQ */
+	for (port = 0; port < hpriv->n_ports; port++) {
+		struct ata_port *this_ap = host->ports[port];
+		struct mv_port_priv *pp = this_ap->private_data;
+
+		if (pp->pp_flags & MV_PP_FLAG_NCQ_EN)
+			return;
+	}
+
+	hpriv->hp_flags &= ~MV_HP_QUIRK_LED_BLINK_EN;
+	hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no);
+	led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS);
+	writel(led_ctrl & ~SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS);
+}
+
+static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma)
 {
 	u32 cfg;
 	struct mv_port_priv *pp    = ap->private_data;
@@ -1185,7 +1476,8 @@
 
 	/* set up non-NCQ EDMA configuration */
 	cfg = EDMA_CFG_Q_DEPTH;		/* always 0x1f for *all* chips */
-	pp->pp_flags &= ~MV_PP_FLAG_FBS_EN;
+	pp->pp_flags &=
+	  ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY);
 
 	if (IS_GEN_I(hpriv))
 		cfg |= (1 << 8);	/* enab config burst size mask */
@@ -1206,7 +1498,7 @@
 		 */
 		want_fbs &= want_ncq;
 
-		mv_config_fbs(port_mmio, want_ncq, want_fbs);
+		mv_config_fbs(ap, want_ncq, want_fbs);
 
 		if (want_fbs) {
 			pp->pp_flags |= MV_PP_FLAG_FBS_EN;
@@ -1214,18 +1506,27 @@
 		}
 
 		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
-		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
-		if (!IS_SOC(hpriv))
-			cfg |= (1 << 18);	/* enab early completion */
+		if (want_edma) {
+			cfg |= (1 << 22); /* enab 4-entry host queue cache */
+			if (!IS_SOC(hpriv))
+				cfg |= (1 << 18); /* enab early completion */
+		}
 		if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
 			cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
+		mv_bmdma_enable_iie(ap, !want_edma);
+
+		if (IS_SOC(hpriv)) {
+			if (want_ncq)
+				mv_soc_led_blink_enable(ap);
+			else
+				mv_soc_led_blink_disable(ap);
+		}
 	}
 
 	if (want_ncq) {
 		cfg |= EDMA_CFG_NCQ;
 		pp->pp_flags |=  MV_PP_FLAG_NCQ_EN;
-	} else
-		pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN;
+	}
 
 	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
 }
@@ -1309,6 +1610,8 @@
 			pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
 		}
 	}
+	mv_save_cached_regs(ap);
+	mv_edma_cfg(ap, 0, 0);
 	return 0;
 
 out_port_free_dma_mem:
@@ -1357,12 +1660,13 @@
 			u32 offset = addr & 0xffff;
 			u32 len = sg_len;
 
-			if ((offset + sg_len > 0x10000))
+			if (offset + len > 0x10000)
 				len = 0x10000 - offset;
 
 			mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
 			mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
 			mv_sg->flags_size = cpu_to_le32(len & 0xffff);
+			mv_sg->reserved = 0;
 
 			sg_len -= len;
 			addr += len;
@@ -1374,6 +1678,7 @@
 
 	if (likely(last_sg))
 		last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
+	mb(); /* ensure data structure is visible to the chipset */
 }
 
 static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
@@ -1384,6 +1689,147 @@
 }
 
 /**
+ *	mv_sff_irq_clear - Clear hardware interrupt after DMA.
+ *	@ap: Port associated with this ATA transaction.
+ *
+ *	We need this only for ATAPI bmdma transactions,
+ *	as otherwise we experience spurious interrupts
+ *	after libata-sff handles the bmdma interrupts.
+ */
+static void mv_sff_irq_clear(struct ata_port *ap)
+{
+	mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), ERR_IRQ);
+}
+
+/**
+ *	mv_check_atapi_dma - Filter ATAPI cmds which are unsuitable for DMA.
+ *	@qc: queued command to check for chipset/DMA compatibility.
+ *
+ *	The bmdma engines cannot handle speculative data sizes
+ *	(bytecount under/over flow).  So only allow DMA for
+ *	data transfer commands with known data sizes.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+static int mv_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *scmd = qc->scsicmd;
+
+	if (scmd) {
+		switch (scmd->cmnd[0]) {
+		case READ_6:
+		case READ_10:
+		case READ_12:
+		case WRITE_6:
+		case WRITE_10:
+		case WRITE_12:
+		case GPCMD_READ_CD:
+		case GPCMD_SEND_DVD_STRUCTURE:
+		case GPCMD_SEND_CUE_SHEET:
+			return 0; /* DMA is safe */
+		}
+	}
+	return -EOPNOTSUPP; /* use PIO instead */
+}
+
+/**
+ *	mv_bmdma_setup - Set up BMDMA transaction
+ *	@qc: queued command to prepare DMA for.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+static void mv_bmdma_setup(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void __iomem *port_mmio = mv_ap_base(ap);
+	struct mv_port_priv *pp = ap->private_data;
+
+	mv_fill_sg(qc);
+
+	/* clear all DMA cmd bits */
+	writel(0, port_mmio + BMDMA_CMD_OFS);
+
+	/* load PRD table addr. */
+	writel((pp->sg_tbl_dma[qc->tag] >> 16) >> 16,
+		port_mmio + BMDMA_PRD_HIGH_OFS);
+	writelfl(pp->sg_tbl_dma[qc->tag],
+		port_mmio + BMDMA_PRD_LOW_OFS);
+
+	/* issue r/w command */
+	ap->ops->sff_exec_command(ap, &qc->tf);
+}
+
+/**
+ *	mv_bmdma_start - Start a BMDMA transaction
+ *	@qc: queued command to start DMA on.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+static void mv_bmdma_start(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void __iomem *port_mmio = mv_ap_base(ap);
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+	u32 cmd = (rw ? 0 : ATA_DMA_WR) | ATA_DMA_START;
+
+	/* start host DMA transaction */
+	writelfl(cmd, port_mmio + BMDMA_CMD_OFS);
+}
+
+/**
+ *	mv_bmdma_stop - Stop BMDMA transfer
+ *	@qc: queued command to stop DMA on.
+ *
+ *	Clears the ATA_DMA_START flag in the bmdma control register
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+static void mv_bmdma_stop(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void __iomem *port_mmio = mv_ap_base(ap);
+	u32 cmd;
+
+	/* clear start/stop bit */
+	cmd = readl(port_mmio + BMDMA_CMD_OFS);
+	cmd &= ~ATA_DMA_START;
+	writelfl(cmd, port_mmio + BMDMA_CMD_OFS);
+
+	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+	ata_sff_dma_pause(ap);
+}
+
+/**
+ *	mv_bmdma_status - Read BMDMA status
+ *	@ap: port for which to retrieve DMA status.
+ *
+ *	Read and return equivalent of the sff BMDMA status register.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+static u8 mv_bmdma_status(struct ata_port *ap)
+{
+	void __iomem *port_mmio = mv_ap_base(ap);
+	u32 reg, status;
+
+	/*
+	 * Other bits are valid only if ATA_DMA_ACTIVE==0,
+	 * and the ATA_DMA_INTR bit doesn't exist.
+	 */
+	reg = readl(port_mmio + BMDMA_STATUS_OFS);
+	if (reg & ATA_DMA_ACTIVE)
+		status = ATA_DMA_ACTIVE;
+	else
+		status = (reg & ATA_DMA_ERR) | ATA_DMA_INTR;
+	return status;
+}
+
+/**
  *      mv_qc_prep - Host specific command preparation.
  *      @qc: queued command to prepare
  *
@@ -1545,6 +1991,132 @@
 }
 
 /**
+ *	mv_sff_check_status - fetch device status, if valid
+ *	@ap: ATA port to fetch status from
+ *
+ *	When using command issue via mv_qc_issue_fis(),
+ *	the initial ATA_BUSY state does not show up in the
+ *	ATA status (shadow) register.  This can confuse libata!
+ *
+ *	So we have a hook here to fake ATA_BUSY for that situation,
+ *	until the first time a BUSY, DRQ, or ERR bit is seen.
+ *
+ *	The rest of the time, it simply returns the ATA status register.
+ */
+static u8 mv_sff_check_status(struct ata_port *ap)
+{
+	u8 stat = ioread8(ap->ioaddr.status_addr);
+	struct mv_port_priv *pp = ap->private_data;
+
+	if (pp->pp_flags & MV_PP_FLAG_FAKE_ATA_BUSY) {
+		if (stat & (ATA_BUSY | ATA_DRQ | ATA_ERR))
+			pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY;
+		else
+			stat = ATA_BUSY;
+	}
+	return stat;
+}
+
+/**
+ *	mv_send_fis - Send a FIS, using the "Vendor-Unique FIS" register
+ *	@fis: fis to be sent
+ *	@nwords: number of 32-bit words in the fis
+ */
+static unsigned int mv_send_fis(struct ata_port *ap, u32 *fis, int nwords)
+{
+	void __iomem *port_mmio = mv_ap_base(ap);
+	u32 ifctl, old_ifctl, ifstat;
+	int i, timeout = 200, final_word = nwords - 1;
+
+	/* Initiate FIS transmission mode */
+	old_ifctl = readl(port_mmio + SATA_IFCTL_OFS);
+	ifctl = 0x100 | (old_ifctl & 0xf);
+	writelfl(ifctl, port_mmio + SATA_IFCTL_OFS);
+
+	/* Send all words of the FIS except for the final word */
+	for (i = 0; i < final_word; ++i)
+		writel(fis[i], port_mmio + VENDOR_UNIQUE_FIS_OFS);
+
+	/* Flag end-of-transmission, and then send the final word */
+	writelfl(ifctl | 0x200, port_mmio + SATA_IFCTL_OFS);
+	writelfl(fis[final_word], port_mmio + VENDOR_UNIQUE_FIS_OFS);
+
+	/*
+	 * Wait for FIS transmission to complete.
+	 * This typically takes just a single iteration.
+	 */
+	do {
+		ifstat = readl(port_mmio + SATA_IFSTAT_OFS);
+	} while (!(ifstat & 0x1000) && --timeout);
+
+	/* Restore original port configuration */
+	writelfl(old_ifctl, port_mmio + SATA_IFCTL_OFS);
+
+	/* See if it worked */
+	if ((ifstat & 0x3000) != 0x1000) {
+		ata_port_printk(ap, KERN_WARNING,
+				"%s transmission error, ifstat=%08x\n",
+				__func__, ifstat);
+		return AC_ERR_OTHER;
+	}
+	return 0;
+}
+
+/**
+ *	mv_qc_issue_fis - Issue a command directly as a FIS
+ *	@qc: queued command to start
+ *
+ *	Note that the ATA shadow registers are not updated
+ *	after command issue, so the device will appear "READY"
+ *	if polled, even while it is BUSY processing the command.
+ *
+ *	So we use a status hook to fake ATA_BUSY until the drive changes state.
+ *
+ *	Note: we don't get updated shadow regs on *completion*
+ *	of non-data commands. So avoid sending them via this function,
+ *	as they will appear to have completed immediately.
+ *
+ *	GEN_IIE has special registers that we could get the result tf from,
+ *	but earlier chipsets do not.  For now, we ignore those registers.
+ */
+static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct mv_port_priv *pp = ap->private_data;
+	struct ata_link *link = qc->dev->link;
+	u32 fis[5];
+	int err = 0;
+
+	ata_tf_to_fis(&qc->tf, link->pmp, 1, (void *)fis);
+	err = mv_send_fis(ap, fis, sizeof(fis) / sizeof(fis[0]));
+	if (err)
+		return err;
+
+	switch (qc->tf.protocol) {
+	case ATAPI_PROT_PIO:
+		pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY;
+		/* fall through */
+	case ATAPI_PROT_NODATA:
+		ap->hsm_task_state = HSM_ST_FIRST;
+		break;
+	case ATA_PROT_PIO:
+		pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY;
+		if (qc->tf.flags & ATA_TFLAG_WRITE)
+			ap->hsm_task_state = HSM_ST_FIRST;
+		else
+			ap->hsm_task_state = HSM_ST;
+		break;
+	default:
+		ap->hsm_task_state = HSM_ST_LAST;
+		break;
+	}
+
+	if (qc->tf.flags & ATA_TFLAG_POLLING)
+		ata_pio_queue_task(ap, qc, 0);
+	return 0;
+}
+
+/**
  *      mv_qc_issue - Initiate a command to the host
  *      @qc: queued command to start
  *
@@ -1558,14 +2130,28 @@
  */
 static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
 {
+	static int limit_warnings = 10;
 	struct ata_port *ap = qc->ap;
 	void __iomem *port_mmio = mv_ap_base(ap);
 	struct mv_port_priv *pp = ap->private_data;
 	u32 in_index;
+	unsigned int port_irqs;
 
-	if ((qc->tf.protocol != ATA_PROT_DMA) &&
-	    (qc->tf.protocol != ATA_PROT_NCQ)) {
-		static int limit_warnings = 10;
+	pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY; /* paranoia */
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+	case ATA_PROT_NCQ:
+		mv_start_edma(ap, port_mmio, pp, qc->tf.protocol);
+		pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
+		in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
+
+		/* Write the request in pointer to kick the EDMA to life */
+		writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
+					port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+		return 0;
+
+	case ATA_PROT_PIO:
 		/*
 		 * Errata SATA#16, SATA#24: warn if multiple DRQs expected.
 		 *
@@ -1583,27 +2169,46 @@
 					": attempting PIO w/multiple DRQ: "
 					"this may fail due to h/w errata\n");
 		}
-		/*
-		 * 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_edma(ap);
-		mv_enable_port_irqs(ap, ERR_IRQ);
-		mv_pmp_select(ap, qc->dev->link->pmp);
-		return ata_sff_qc_issue(qc);
+		/* drop through */
+	case ATA_PROT_NODATA:
+	case ATAPI_PROT_PIO:
+	case ATAPI_PROT_NODATA:
+		if (ap->flags & ATA_FLAG_PIO_POLLING)
+			qc->tf.flags |= ATA_TFLAG_POLLING;
+		break;
 	}
 
-	mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
+	if (qc->tf.flags & ATA_TFLAG_POLLING)
+		port_irqs = ERR_IRQ;	/* mask device interrupt when polling */
+	else
+		port_irqs = ERR_IRQ | DONE_IRQ;	/* unmask all interrupts */
 
-	pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
-	in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
+	/*
+	 * 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_edma(ap);
+	mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs);
+	mv_pmp_select(ap, qc->dev->link->pmp);
 
-	/* and write the request in pointer to kick the EDMA to life */
-	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
-		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-
-	return 0;
+	if (qc->tf.command == ATA_CMD_READ_LOG_EXT) {
+		struct mv_host_priv *hpriv = ap->host->private_data;
+		/*
+		 * Workaround for 88SX60x1 FEr SATA#25 (part 2).
+		 *
+		 * After any NCQ error, the READ_LOG_EXT command
+		 * from libata-eh *must* use mv_qc_issue_fis().
+		 * Otherwise it might fail, due to chip errata.
+		 *
+		 * Rather than special-case it, we'll just *always*
+		 * use this method here for READ_LOG_EXT, making for
+		 * easier testing.
+		 */
+		if (IS_GEN_II(hpriv))
+			return mv_qc_issue_fis(qc);
+	}
+	return ata_sff_qc_issue(qc);
 }
 
 static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap)
@@ -1614,8 +2219,12 @@
 	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;
+	if (qc) {
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			qc = NULL;
+		else if (!(qc->flags & ATA_QCFLAG_ACTIVE))
+			qc = NULL;
+	}
 	return qc;
 }
 
@@ -2084,6 +2693,10 @@
 	void __iomem *mmio = hpriv->base, *hc_mmio;
 	unsigned int handled = 0, port;
 
+	/* If asserted, clear the "all ports" IRQ coalescing bit */
+	if (main_irq_cause & ALL_PORTS_COAL_DONE)
+		writel(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE);
+
 	for (port = 0; port < hpriv->n_ports; port++) {
 		struct ata_port *ap = host->ports[port];
 		unsigned int p, shift, hardport, port_cause;
@@ -2116,6 +2729,8 @@
 			 * to ack (only) those ports via hc_irq_cause.
 			 */
 			ack_irqs = 0;
+			if (hc_cause & PORTS_0_3_COAL_DONE)
+				ack_irqs = HC_COAL_IRQ;
 			for (p = 0; p < MV_PORTS_PER_HC; ++p) {
 				if ((port + p) >= hpriv->n_ports)
 					break;
@@ -2204,7 +2819,7 @@
 
 	/* for MSI:  block new interrupts while in here */
 	if (using_msi)
-		writel(0, hpriv->main_irq_mask_addr);
+		mv_write_main_irq_mask(0, hpriv);
 
 	main_irq_cause = readl(hpriv->main_irq_cause_addr);
 	pending_irqs   = main_irq_cause & hpriv->main_irq_mask;
@@ -2218,11 +2833,12 @@
 		else
 			handled = mv_host_intr(host, pending_irqs);
 	}
-	spin_unlock(&host->lock);
 
 	/* for MSI: unmask; interrupt cause bits will retrigger now */
 	if (using_msi)
-		writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr);
+		mv_write_main_irq_mask(hpriv->main_irq_mask, hpriv);
+
+	spin_unlock(&host->lock);
 
 	return IRQ_RETVAL(handled);
 }
@@ -2773,6 +3389,8 @@
 
 	mv_reset_channel(hpriv, mmio, ap->port_no);
 	pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+	pp->pp_flags &=
+	  ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY);
 
 	/* Workaround for errata FEr SATA#10 (part 2) */
 	do {
@@ -2792,6 +3410,8 @@
 				extra = HZ; /* only extend it once, max */
 		}
 	} while (sstatus != 0x0 && sstatus != 0x113 && sstatus != 0x123);
+	mv_save_cached_regs(ap);
+	mv_edma_cfg(ap, 0, 0);
 
 	return rc;
 }
@@ -3125,6 +3745,8 @@
 	 * The per-port interrupts get done later as ports are set up.
 	 */
 	mv_set_main_irq_mask(host, 0, PCI_ERR);
+	mv_set_irq_coalescing(host, irq_coalescing_io_count,
+				    irq_coalescing_usecs);
 done:
 	return rc;
 }
@@ -3286,12 +3908,6 @@
 	.remove			= ata_pci_remove_one,
 };
 
-/*
- * module options
- */
-static int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
-
-
 /* move to PCI layer or libata core? */
 static int pci_go_64(struct pci_dev *pdev)
 {
@@ -3473,10 +4089,5 @@
 MODULE_VERSION(DRV_VERSION);
 MODULE_ALIAS("platform:" DRV_NAME);
 
-#ifdef CONFIG_PCI
-module_param(msi, int, 0444);
-MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
-#endif
-
 module_init(mv_init);
 module_exit(mv_exit);
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 55a8eed..6cda12b 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -57,9 +57,9 @@
 	NV_MMIO_BAR			= 5,
 
 	NV_PORTS			= 2,
-	NV_PIO_MASK			= 0x1f,
-	NV_MWDMA_MASK			= 0x07,
-	NV_UDMA_MASK			= 0x7f,
+	NV_PIO_MASK			= ATA_PIO4,
+	NV_MWDMA_MASK			= ATA_MWDMA2,
+	NV_UDMA_MASK			= ATA_UDMA6,
 	NV_PORT0_SCR_REG_OFFSET		= 0x00,
 	NV_PORT1_SCR_REG_OFFSET		= 0x40,
 
@@ -408,6 +408,7 @@
 
 static struct ata_port_operations nv_common_ops = {
 	.inherits		= &ata_bmdma_port_ops,
+	.lost_interrupt		= ATA_OP_NULL,
 	.scr_read		= nv_scr_read,
 	.scr_write		= nv_scr_write,
 };
@@ -2523,7 +2524,7 @@
 module_init(nv_init);
 module_exit(nv_exit);
 module_param_named(adma, adma_enabled, bool, 0444);
-MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");
+MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");
 module_param_named(swncq, swncq_enabled, bool, 0444);
 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 ba9a257..b1fd7d6 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -176,7 +176,9 @@
 	.check_atapi_dma	= pdc_check_atapi_dma,
 	.qc_prep		= pdc_qc_prep,
 	.qc_issue		= pdc_qc_issue,
+
 	.sff_irq_clear		= pdc_irq_clear,
+	.lost_interrupt		= ATA_OP_NULL,
 
 	.post_internal_cmd	= pdc_post_internal_cmd,
 	.error_handler		= pdc_error_handler,
@@ -213,8 +215,8 @@
 	{
 		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |
 				  PDC_FLAG_SATA_PATA,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_old_sata_ops,
 	},
@@ -222,8 +224,8 @@
 	[board_2037x_pata] =
 	{
 		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_pata_ops,
 	},
@@ -232,8 +234,8 @@
 	{
 		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |
 				  PDC_FLAG_4_PORTS,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_old_sata_ops,
 	},
@@ -242,8 +244,8 @@
 	{
 		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
 				  PDC_FLAG_4_PORTS,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_pata_ops,
 	},
@@ -252,8 +254,8 @@
 	{
 		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |
 				  PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_sata_ops,
 	},
@@ -262,8 +264,8 @@
 	{
 		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
 				  PDC_FLAG_GEN_II,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_pata_ops,
 	},
@@ -272,8 +274,8 @@
 	{
 		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |
 				  PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_sata_ops,
 	},
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index a000c86..c3936d3 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -147,6 +147,7 @@
 	.softreset		= ATA_OP_NULL,
 	.error_handler		= qs_error_handler,
 	.post_internal_cmd	= ATA_OP_NULL,
+	.lost_interrupt		= ATA_OP_NULL,
 
 	.scr_read		= qs_scr_read,
 	.scr_write		= qs_scr_write,
@@ -160,7 +161,7 @@
 	{
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
-		.pio_mask	= 0x10, /* pio4 */
+		.pio_mask	= ATA_PIO4_ONLY,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &qs_ata_ops,
 	},
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index d009160..e67ce8e 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -200,8 +200,8 @@
 	/* sil_3112 */
 	{
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
-		.pio_mask	= 0x1f,			/* pio0-4 */
-		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
@@ -209,24 +209,24 @@
 	{
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE |
 				  SIL_FLAG_NO_SATA_IRQ,
-		.pio_mask	= 0x1f,			/* pio0-4 */
-		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 	/* sil_3512 */
 	{
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
-		.pio_mask	= 0x1f,			/* pio0-4 */
-		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 	/* sil_3114 */
 	{
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
-		.pio_mask	= 0x1f,			/* pio0-4 */
-		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 2590c22..0d8990d 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -429,25 +429,25 @@
 	{
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
 				  SIL24_FLAG_PCIX_IRQ_WOC,
-		.pio_mask	= 0x1f,			/* pio0-4 */
-		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil24_ops,
 	},
 	/* sil_3132 */
 	{
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
-		.pio_mask	= 0x1f,			/* pio0-4 */
-		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil24_ops,
 	},
 	/* sil_3131/sil_3531 */
 	{
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
-		.pio_mask	= 0x1f,			/* pio0-4 */
-		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil24_ops,
 	},
 };
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 9c43b4e..8f98332 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -97,8 +97,8 @@
 
 static const struct ata_port_info sis_port_info = {
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-	.pio_mask	= 0x1f,
-	.mwdma_mask	= 0x7,
+	.pio_mask	= ATA_PIO4,
+	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_ops,
 };
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 609d147..7257f2d 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -361,8 +361,8 @@
 	{
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &k2_sata_ops,
 	},
@@ -371,8 +371,8 @@
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA |
 				  K2_FLAG_SATA_8_PORTS,
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &k2_sata_ops,
 	},
@@ -380,8 +380,8 @@
 	{
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3,
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &k2_sata_ops,
 	},
@@ -389,8 +389,8 @@
 	{
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO,
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &k2_sata_ops,
 	},
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index ec04b8d..dce3dcc 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -265,8 +265,8 @@
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO |
 				  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
-		.pio_mask	= 0x1f, /* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_20621_ops,
 	},
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 019575b..e5bff47 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -89,7 +89,7 @@
 static const struct ata_port_info uli_port_info = {
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 			  ATA_FLAG_IGN_SIMPLEX,
-	.pio_mask       = 0x1f,		/* pio0-4 */
+	.pio_mask       = ATA_PIO4,
 	.udma_mask      = ATA_UDMA6,
 	.port_ops       = &uli_ops,
 };
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 5c62da9..98e8c50 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -146,24 +146,24 @@
 
 static const struct ata_port_info vt6420_port_info = {
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-	.pio_mask	= 0x1f,
-	.mwdma_mask	= 0x07,
+	.pio_mask	= ATA_PIO4,
+	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt6420_sata_ops,
 };
 
 static struct ata_port_info vt6421_sport_info = {
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-	.pio_mask	= 0x1f,
-	.mwdma_mask	= 0x07,
+	.pio_mask	= ATA_PIO4,
+	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt6421_sata_ops,
 };
 
 static struct ata_port_info vt6421_pport_info = {
 	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
-	.pio_mask	= 0x1f,
-	.mwdma_mask	= 0,
+	.pio_mask	= ATA_PIO4,
+	/* No MWDMA */
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt6421_pata_ops,
 };
@@ -171,8 +171,8 @@
 static struct ata_port_info vt8251_port_info = {
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS |
 			  ATA_FLAG_NO_LEGACY,
-	.pio_mask	= 0x1f,
-	.mwdma_mask	= 0x07,
+	.pio_mask	= ATA_PIO4,
+	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt8251_ops,
 };
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index c57cdff..ed70bd2 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -308,6 +308,9 @@
 
 static struct ata_port_operations vsc_sata_ops = {
 	.inherits		= &ata_bmdma_port_ops,
+	/* The IRQ handling is not quite standard SFF behaviour so we
+	   cannot use the default lost interrupt handler */
+	.lost_interrupt		= ATA_OP_NULL,
 	.sff_tf_load		= vsc_sata_tf_load,
 	.sff_tf_read		= vsc_sata_tf_read,
 	.freeze			= vsc_freeze,
@@ -345,8 +348,8 @@
 	static const struct ata_port_info pi = {
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO,
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &vsc_sata_ops,
 	};
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 9f50f1b..ddc9749 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -63,6 +63,32 @@
 #define to_class(obj)	\
 	container_of(obj, struct class_private, class_subsys.kobj)
 
+/**
+ * struct device_private - structure to hold the private to the driver core portions of the device structure.
+ *
+ * @klist_children - klist containing all children of this device
+ * @knode_parent - node in sibling list
+ * @knode_driver - node in driver list
+ * @knode_bus - node in bus list
+ * @device - pointer back to the struct class that this structure is
+ * associated with.
+ *
+ * Nothing outside of the driver core should ever touch these fields.
+ */
+struct device_private {
+	struct klist klist_children;
+	struct klist_node knode_parent;
+	struct klist_node knode_driver;
+	struct klist_node knode_bus;
+	struct device *device;
+};
+#define to_device_private_parent(obj)	\
+	container_of(obj, struct device_private, knode_parent)
+#define to_device_private_driver(obj)	\
+	container_of(obj, struct device_private, knode_driver)
+#define to_device_private_bus(obj)	\
+	container_of(obj, struct device_private, knode_bus)
+
 /* initialisation functions */
 extern int devices_init(void);
 extern int buses_init(void);
@@ -86,6 +112,11 @@
 
 extern void driver_detach(struct device_driver *drv);
 extern int driver_probe_device(struct device_driver *drv, struct device *dev);
+static inline int driver_match_device(struct device_driver *drv,
+				      struct device *dev)
+{
+	return drv->bus->match && drv->bus->match(dev, drv);
+}
 
 extern void sysdev_shutdown(void);
 
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 83f32b8..dc030f1 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -198,7 +198,7 @@
 	int err = -ENODEV;
 
 	dev = bus_find_device_by_name(bus, NULL, buf);
-	if (dev && dev->driver == NULL) {
+	if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
 		if (dev->parent)	/* Needed for USB */
 			down(&dev->parent->sem);
 		down(&dev->sem);
@@ -253,7 +253,14 @@
 static struct device *next_device(struct klist_iter *i)
 {
 	struct klist_node *n = klist_next(i);
-	return n ? container_of(n, struct device, knode_bus) : NULL;
+	struct device *dev = NULL;
+	struct device_private *dev_prv;
+
+	if (n) {
+		dev_prv = to_device_private_bus(n);
+		dev = dev_prv->device;
+	}
+	return dev;
 }
 
 /**
@@ -286,7 +293,7 @@
 		return -EINVAL;
 
 	klist_iter_init_node(&bus->p->klist_devices, &i,
-			     (start ? &start->knode_bus : NULL));
+			     (start ? &start->p->knode_bus : NULL));
 	while ((dev = next_device(&i)) && !error)
 		error = fn(dev, data);
 	klist_iter_exit(&i);
@@ -320,7 +327,7 @@
 		return NULL;
 
 	klist_iter_init_node(&bus->p->klist_devices, &i,
-			     (start ? &start->knode_bus : NULL));
+			     (start ? &start->p->knode_bus : NULL));
 	while ((dev = next_device(&i)))
 		if (match(dev, data) && get_device(dev))
 			break;
@@ -507,7 +514,8 @@
 			ret = device_attach(dev);
 		WARN_ON(ret < 0);
 		if (ret >= 0)
-			klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
+			klist_add_tail(&dev->p->knode_bus,
+				       &bus->p->klist_devices);
 	}
 }
 
@@ -528,8 +536,8 @@
 		sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
 				  dev_name(dev));
 		device_remove_attrs(dev->bus, dev);
-		if (klist_node_attached(&dev->knode_bus))
-			klist_del(&dev->knode_bus);
+		if (klist_node_attached(&dev->p->knode_bus))
+			klist_del(&dev->p->knode_bus);
 
 		pr_debug("bus: '%s': remove device %s\n",
 			 dev->bus->name, dev_name(dev));
@@ -831,14 +839,16 @@
 
 static void klist_devices_get(struct klist_node *n)
 {
-	struct device *dev = container_of(n, struct device, knode_bus);
+	struct device_private *dev_prv = to_device_private_bus(n);
+	struct device *dev = dev_prv->device;
 
 	get_device(dev);
 }
 
 static void klist_devices_put(struct klist_node *n)
 {
-	struct device *dev = container_of(n, struct device, knode_bus);
+	struct device_private *dev_prv = to_device_private_bus(n);
+	struct device *dev = dev_prv->device;
 
 	put_device(dev);
 }
@@ -932,6 +942,7 @@
 	kset_unregister(&bus->p->subsys);
 	kfree(bus->p);
 out:
+	bus->p = NULL;
 	return retval;
 }
 EXPORT_SYMBOL_GPL(bus_register);
@@ -953,6 +964,7 @@
 	bus_remove_file(bus, &bus_attr_uevent);
 	kset_unregister(&bus->p->subsys);
 	kfree(bus->p);
+	bus->p = NULL;
 }
 EXPORT_SYMBOL_GPL(bus_unregister);
 
@@ -993,18 +1005,20 @@
 {
 	struct list_head *pos;
 	struct klist_node *n;
+	struct device_private *dev_prv;
 	struct device *b;
 
 	list_for_each(pos, list) {
 		n = container_of(pos, struct klist_node, n_node);
-		b = container_of(n, struct device, knode_bus);
+		dev_prv = to_device_private_bus(n);
+		b = dev_prv->device;
 		if (compare(a, b) <= 0) {
-			list_move_tail(&a->knode_bus.n_node,
-				       &b->knode_bus.n_node);
+			list_move_tail(&a->p->knode_bus.n_node,
+				       &b->p->knode_bus.n_node);
 			return;
 		}
 	}
-	list_move_tail(&a->knode_bus.n_node, list);
+	list_move_tail(&a->p->knode_bus.n_node, list);
 }
 
 void bus_sort_breadthfirst(struct bus_type *bus,
@@ -1014,6 +1028,7 @@
 	LIST_HEAD(sorted_devices);
 	struct list_head *pos, *tmp;
 	struct klist_node *n;
+	struct device_private *dev_prv;
 	struct device *dev;
 	struct klist *device_klist;
 
@@ -1022,7 +1037,8 @@
 	spin_lock(&device_klist->k_lock);
 	list_for_each_safe(pos, tmp, &device_klist->k_list) {
 		n = container_of(pos, struct klist_node, n_node);
-		dev = container_of(n, struct device, knode_bus);
+		dev_prv = to_device_private_bus(n);
+		dev = dev_prv->device;
 		device_insertion_sort_klist(dev, &sorted_devices, compare);
 	}
 	list_splice(&sorted_devices, &device_klist->k_list);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index f3eae63..e73c92d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -109,6 +109,7 @@
 static void device_release(struct kobject *kobj)
 {
 	struct device *dev = to_dev(kobj);
+	struct device_private *p = dev->p;
 
 	if (dev->release)
 		dev->release(dev);
@@ -120,6 +121,7 @@
 		WARN(1, KERN_ERR "Device '%s' does not have a release() "
 			"function, it is broken and must be fixed.\n",
 			dev_name(dev));
+	kfree(p);
 }
 
 static struct kobj_type device_ktype = {
@@ -134,8 +136,6 @@
 
 	if (ktype == &device_ktype) {
 		struct device *dev = to_dev(kobj);
-		if (dev->uevent_suppress)
-			return 0;
 		if (dev->bus)
 			return 1;
 		if (dev->class)
@@ -507,14 +507,16 @@
 
 static void klist_children_get(struct klist_node *n)
 {
-	struct device *dev = container_of(n, struct device, knode_parent);
+	struct device_private *p = to_device_private_parent(n);
+	struct device *dev = p->device;
 
 	get_device(dev);
 }
 
 static void klist_children_put(struct klist_node *n)
 {
-	struct device *dev = container_of(n, struct device, knode_parent);
+	struct device_private *p = to_device_private_parent(n);
+	struct device *dev = p->device;
 
 	put_device(dev);
 }
@@ -538,8 +540,6 @@
 {
 	dev->kobj.kset = devices_kset;
 	kobject_init(&dev->kobj, &device_ktype);
-	klist_init(&dev->klist_children, klist_children_get,
-		   klist_children_put);
 	INIT_LIST_HEAD(&dev->dma_pools);
 	init_MUTEX(&dev->sem);
 	spin_lock_init(&dev->devres_lock);
@@ -777,17 +777,12 @@
 int dev_set_name(struct device *dev, const char *fmt, ...)
 {
 	va_list vargs;
-	char *s;
+	int err;
 
 	va_start(vargs, fmt);
-	vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs);
+	err = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
 	va_end(vargs);
-
-	/* ewww... some of these buggers have / in the name... */
-	while ((s = strchr(dev->bus_id, '/')))
-		*s = '!';
-
-	return 0;
+	return err;
 }
 EXPORT_SYMBOL_GPL(dev_set_name);
 
@@ -864,12 +859,26 @@
 	if (!dev)
 		goto done;
 
-	/* Temporarily support init_name if it is set.
-	 * It will override bus_id for now */
-	if (dev->init_name)
-		dev_set_name(dev, "%s", dev->init_name);
+	dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL);
+	if (!dev->p) {
+		error = -ENOMEM;
+		goto done;
+	}
+	dev->p->device = dev;
+	klist_init(&dev->p->klist_children, klist_children_get,
+		   klist_children_put);
 
-	if (!strlen(dev->bus_id))
+	/*
+	 * for statically allocated devices, which should all be converted
+	 * some day, we need to initialize the name. We prevent reading back
+	 * the name, and force the use of dev_name()
+	 */
+	if (dev->init_name) {
+		dev_set_name(dev, dev->init_name);
+		dev->init_name = NULL;
+	}
+
+	if (!dev_name(dev))
 		goto done;
 
 	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
@@ -928,7 +937,8 @@
 	kobject_uevent(&dev->kobj, KOBJ_ADD);
 	bus_attach_device(dev);
 	if (parent)
-		klist_add_tail(&dev->knode_parent, &parent->klist_children);
+		klist_add_tail(&dev->p->knode_parent,
+			       &parent->p->klist_children);
 
 	if (dev->class) {
 		mutex_lock(&dev->class->p->class_mutex);
@@ -1042,7 +1052,7 @@
 	device_pm_remove(dev);
 	dpm_sysfs_remove(dev);
 	if (parent)
-		klist_del(&dev->knode_parent);
+		klist_del(&dev->p->knode_parent);
 	if (MAJOR(dev->devt)) {
 		device_remove_sys_dev_entry(dev);
 		device_remove_file(dev, &devt_attr);
@@ -1103,7 +1113,14 @@
 static struct device *next_device(struct klist_iter *i)
 {
 	struct klist_node *n = klist_next(i);
-	return n ? container_of(n, struct device, knode_parent) : NULL;
+	struct device *dev = NULL;
+	struct device_private *p;
+
+	if (n) {
+		p = to_device_private_parent(n);
+		dev = p->device;
+	}
+	return dev;
 }
 
 /**
@@ -1125,7 +1142,7 @@
 	struct device *child;
 	int error = 0;
 
-	klist_iter_init(&parent->klist_children, &i);
+	klist_iter_init(&parent->p->klist_children, &i);
 	while ((child = next_device(&i)) && !error)
 		error = fn(child, data);
 	klist_iter_exit(&i);
@@ -1156,7 +1173,7 @@
 	if (!parent)
 		return NULL;
 
-	klist_iter_init(&parent->klist_children, &i);
+	klist_iter_init(&parent->p->klist_children, &i);
 	while ((child = next_device(&i)))
 		if (match(child, data) && get_device(child))
 			break;
@@ -1348,7 +1365,10 @@
 	dev->release = device_create_release;
 	dev_set_drvdata(dev, drvdata);
 
-	vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
+	retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
+	if (retval)
+		goto error;
+
 	retval = device_register(dev);
 	if (retval)
 		goto error;
@@ -1452,19 +1472,15 @@
 		old_class_name = make_class_name(dev->class->name, &dev->kobj);
 #endif
 
-	old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
+	old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
 	if (!old_device_name) {
 		error = -ENOMEM;
 		goto out;
 	}
-	strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE);
-	strlcpy(dev->bus_id, new_name, BUS_ID_SIZE);
 
 	error = kobject_rename(&dev->kobj, new_name);
-	if (error) {
-		strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE);
+	if (error)
 		goto out;
-	}
 
 #ifdef CONFIG_SYSFS_DEPRECATED
 	if (old_class_name) {
@@ -1545,8 +1561,10 @@
  * device_move - moves a device to a new parent
  * @dev: the pointer to the struct device to be moved
  * @new_parent: the new parent of the device (can by NULL)
+ * @dpm_order: how to reorder the dpm_list
  */
-int device_move(struct device *dev, struct device *new_parent)
+int device_move(struct device *dev, struct device *new_parent,
+		enum dpm_order dpm_order)
 {
 	int error;
 	struct device *old_parent;
@@ -1556,6 +1574,7 @@
 	if (!dev)
 		return -EINVAL;
 
+	device_pm_lock();
 	new_parent = get_device(new_parent);
 	new_parent_kobj = get_device_parent(dev, new_parent);
 
@@ -1570,9 +1589,10 @@
 	old_parent = dev->parent;
 	dev->parent = new_parent;
 	if (old_parent)
-		klist_remove(&dev->knode_parent);
+		klist_remove(&dev->p->knode_parent);
 	if (new_parent) {
-		klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
+		klist_add_tail(&dev->p->knode_parent,
+			       &new_parent->p->klist_children);
 		set_dev_node(dev, dev_to_node(new_parent));
 	}
 
@@ -1584,11 +1604,11 @@
 		device_move_class_links(dev, new_parent, old_parent);
 		if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
 			if (new_parent)
-				klist_remove(&dev->knode_parent);
+				klist_remove(&dev->p->knode_parent);
 			dev->parent = old_parent;
 			if (old_parent) {
-				klist_add_tail(&dev->knode_parent,
-					       &old_parent->klist_children);
+				klist_add_tail(&dev->p->knode_parent,
+					       &old_parent->p->klist_children);
 				set_dev_node(dev, dev_to_node(old_parent));
 			}
 		}
@@ -1596,9 +1616,23 @@
 		put_device(new_parent);
 		goto out;
 	}
+	switch (dpm_order) {
+	case DPM_ORDER_NONE:
+		break;
+	case DPM_ORDER_DEV_AFTER_PARENT:
+		device_pm_move_after(dev, new_parent);
+		break;
+	case DPM_ORDER_PARENT_BEFORE_DEV:
+		device_pm_move_before(new_parent, dev);
+		break;
+	case DPM_ORDER_DEV_LAST:
+		device_pm_move_last(dev);
+		break;
+	}
 out_put:
 	put_device(old_parent);
 out:
+	device_pm_unlock();
 	put_device(dev);
 	return error;
 }
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1352312..f17c326 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -30,7 +30,7 @@
 
 static void driver_bound(struct device *dev)
 {
-	if (klist_node_attached(&dev->knode_driver)) {
+	if (klist_node_attached(&dev->p->knode_driver)) {
 		printk(KERN_WARNING "%s: device %s already bound\n",
 			__func__, kobject_name(&dev->kobj));
 		return;
@@ -43,7 +43,7 @@
 		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 					     BUS_NOTIFY_BOUND_DRIVER, dev);
 
-	klist_add_tail(&dev->knode_driver, &dev->driver->p->klist_devices);
+	klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
 }
 
 static int driver_sysfs_add(struct device *dev)
@@ -172,16 +172,12 @@
 /**
  * wait_for_device_probe
  * Wait for device probing to be completed.
- *
- * Note: this function polls at 100 msec intervals.
  */
-int wait_for_device_probe(void)
+void wait_for_device_probe(void)
 {
 	/* wait for the known devices to complete their probing */
-	while (driver_probe_done() != 0)
-		msleep(100);
+	wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
 	async_synchronize_full();
-	return 0;
 }
 
 /**
@@ -189,14 +185,8 @@
  * @drv: driver to bind a device to
  * @dev: device to try to bind to the driver
  *
- * First, we call the bus's match function, if one present, which should
- * compare the device IDs the driver supports with the device IDs of the
- * device. Note we don't do this ourselves because we don't know the
- * format of the ID structures, nor what is to be considered a match and
- * what is not.
- *
- * This function returns 1 if a match is found, -ENODEV if the device is
- * not registered, and 0 otherwise.
+ * This function returns -ENODEV if the device is not registered,
+ * 1 if the device is bound sucessfully and 0 otherwise.
  *
  * This function must be called with @dev->sem held.  When called for a
  * USB interface, @dev->parent->sem must be held as well.
@@ -207,21 +197,22 @@
 
 	if (!device_is_registered(dev))
 		return -ENODEV;
-	if (drv->bus->match && !drv->bus->match(dev, drv))
-		goto done;
 
 	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
 		 drv->bus->name, __func__, dev_name(dev), drv->name);
 
 	ret = really_probe(dev, drv);
 
-done:
 	return ret;
 }
 
 static int __device_attach(struct device_driver *drv, void *data)
 {
 	struct device *dev = data;
+
+	if (!driver_match_device(drv, dev))
+		return 0;
+
 	return driver_probe_device(drv, dev);
 }
 
@@ -274,7 +265,7 @@
 	 * is an error.
 	 */
 
-	if (drv->bus->match && !drv->bus->match(dev, drv))
+	if (!driver_match_device(drv, dev))
 		return 0;
 
 	if (dev->parent)	/* Needed for USB */
@@ -327,7 +318,7 @@
 			drv->remove(dev);
 		devres_release_all(dev);
 		dev->driver = NULL;
-		klist_remove(&dev->knode_driver);
+		klist_remove(&dev->p->knode_driver);
 	}
 }
 
@@ -357,6 +348,7 @@
  */
 void driver_detach(struct device_driver *drv)
 {
+	struct device_private *dev_prv;
 	struct device *dev;
 
 	for (;;) {
@@ -365,8 +357,10 @@
 			spin_unlock(&drv->p->klist_devices.k_lock);
 			break;
 		}
-		dev = list_entry(drv->p->klist_devices.k_list.prev,
-				struct device, knode_driver.n_node);
+		dev_prv = list_entry(drv->p->klist_devices.k_list.prev,
+				     struct device_private,
+				     knode_driver.n_node);
+		dev = dev_prv->device;
 		get_device(dev);
 		spin_unlock(&drv->p->klist_devices.k_lock);
 
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 1e2bda7..c51f11b 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -19,7 +19,14 @@
 static struct device *next_device(struct klist_iter *i)
 {
 	struct klist_node *n = klist_next(i);
-	return n ? container_of(n, struct device, knode_driver) : NULL;
+	struct device *dev = NULL;
+	struct device_private *dev_prv;
+
+	if (n) {
+		dev_prv = to_device_private_driver(n);
+		dev = dev_prv->device;
+	}
+	return dev;
 }
 
 /**
@@ -42,7 +49,7 @@
 		return -EINVAL;
 
 	klist_iter_init_node(&drv->p->klist_devices, &i,
-			     start ? &start->knode_driver : NULL);
+			     start ? &start->p->knode_driver : NULL);
 	while ((dev = next_device(&i)) && !error)
 		error = fn(dev, data);
 	klist_iter_exit(&i);
@@ -76,7 +83,7 @@
 		return NULL;
 
 	klist_iter_init_node(&drv->p->klist_devices, &i,
-			     (start ? &start->knode_driver : NULL));
+			     (start ? &start->p->knode_driver : NULL));
 	while ((dev = next_device(&i)))
 		if (match(dev, data) && get_device(dev))
 			break;
@@ -216,6 +223,8 @@
 	int ret;
 	struct device_driver *other;
 
+	BUG_ON(!drv->bus->p);
+
 	if ((drv->bus->probe && drv->probe) ||
 	    (drv->bus->remove && drv->remove) ||
 	    (drv->bus->shutdown && drv->shutdown))
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 44699d9..d3a59c68 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -319,7 +319,7 @@
 	f_dev->parent = device;
 	f_dev->class = &firmware_class;
 	dev_set_drvdata(f_dev, fw_priv);
-	f_dev->uevent_suppress = 1;
+	dev_set_uevent_suppress(f_dev, 1);
 	retval = device_register(f_dev);
 	if (retval) {
 		dev_err(device, "%s: device_register failed\n", __func__);
@@ -366,7 +366,7 @@
 	}
 
 	if (uevent)
-		f_dev->uevent_suppress = 0;
+		dev_set_uevent_suppress(f_dev, 0);
 	*dev_p = f_dev;
 	goto out;
 
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 43fa90b..f8f578a 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -303,7 +303,7 @@
 	sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
 	sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
 	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
-		unsigned int nid;
+		int nid;
 
 		nid = get_nid_for_pfn(pfn);
 		if (nid < 0)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 349a101..d2198f6 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -217,6 +217,7 @@
 	if (d) {
 		memcpy(d, data, size);
 		pdev->dev.platform_data = d;
+		pdev->platform_data = d;
 	}
 	return d ? 0 : -ENOMEM;
 }
@@ -246,6 +247,21 @@
 	else
 		dev_set_name(&pdev->dev, pdev->name);
 
+	/* We will remove platform_data field from struct device
+	* if all platform devices pass its platform specific data
+	* from platform_device. The conversion is going to be a
+	* long time, so we allow the two cases coexist to make
+	* this kind of fix more easily*/
+	if (pdev->platform_data && pdev->dev.platform_data) {
+		printk(KERN_ERR
+			       "%s: use which platform_data?\n",
+			       dev_name(&pdev->dev));
+	} else if (pdev->platform_data) {
+		pdev->dev.platform_data = pdev->platform_data;
+	} else if (pdev->dev.platform_data) {
+		pdev->platform_data = pdev->dev.platform_data;
+	}
+
 	for (i = 0; i < pdev->num_resources; i++) {
 		struct resource *p, *r = &pdev->resource[i];
 
@@ -584,10 +600,25 @@
 {
 	struct platform_device	*pdev = to_platform_device(dev);
 
-	add_uevent_var(env, "MODALIAS=platform:%s", pdev->name);
+	add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
+		(pdev->id_entry) ? pdev->id_entry->name : pdev->name);
 	return 0;
 }
 
+static const struct platform_device_id *platform_match_id(
+			struct platform_device_id *id,
+			struct platform_device *pdev)
+{
+	while (id->name[0]) {
+		if (strcmp(pdev->name, id->name) == 0) {
+			pdev->id_entry = id;
+			return id;
+		}
+		id++;
+	}
+	return NULL;
+}
+
 /**
  * platform_match - bind platform device to platform driver.
  * @dev: device.
@@ -603,9 +634,14 @@
  */
 static int platform_match(struct device *dev, struct device_driver *drv)
 {
-	struct platform_device *pdev;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct platform_driver *pdrv = to_platform_driver(drv);
 
-	pdev = container_of(dev, struct platform_device, dev);
+	/* match against the id table first */
+	if (pdrv->id_table)
+		return platform_match_id(pdrv->id_table, pdev) != NULL;
+
+	/* fall-back to driver name match */
 	return (strcmp(pdev->name, drv->name) == 0);
 }
 
@@ -623,26 +659,24 @@
 
 static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg)
 {
-	struct platform_driver *drv = to_platform_driver(dev->driver);
-	struct platform_device *pdev;
+	struct platform_driver *pdrv = to_platform_driver(dev->driver);
+	struct platform_device *pdev = to_platform_device(dev);
 	int ret = 0;
 
-	pdev = container_of(dev, struct platform_device, dev);
-	if (dev->driver && drv->suspend_late)
-		ret = drv->suspend_late(pdev, mesg);
+	if (dev->driver && pdrv->suspend_late)
+		ret = pdrv->suspend_late(pdev, mesg);
 
 	return ret;
 }
 
 static int platform_legacy_resume_early(struct device *dev)
 {
-	struct platform_driver *drv = to_platform_driver(dev->driver);
-	struct platform_device *pdev;
+	struct platform_driver *pdrv = to_platform_driver(dev->driver);
+	struct platform_device *pdev = to_platform_device(dev);
 	int ret = 0;
 
-	pdev = container_of(dev, struct platform_device, dev);
-	if (dev->driver && drv->resume_early)
-		ret = drv->resume_early(pdev);
+	if (dev->driver && pdrv->resume_early)
+		ret = pdrv->resume_early(pdev);
 
 	return ret;
 }
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 2d14f4a..e255341 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -107,6 +107,50 @@
 }
 
 /**
+ *	device_pm_move_before - move device in dpm_list
+ *	@deva:  Device to move in dpm_list
+ *	@devb:  Device @deva should come before
+ */
+void device_pm_move_before(struct device *deva, struct device *devb)
+{
+	pr_debug("PM: Moving %s:%s before %s:%s\n",
+		 deva->bus ? deva->bus->name : "No Bus",
+		 kobject_name(&deva->kobj),
+		 devb->bus ? devb->bus->name : "No Bus",
+		 kobject_name(&devb->kobj));
+	/* Delete deva from dpm_list and reinsert before devb. */
+	list_move_tail(&deva->power.entry, &devb->power.entry);
+}
+
+/**
+ *	device_pm_move_after - move device in dpm_list
+ *	@deva:  Device to move in dpm_list
+ *	@devb:  Device @deva should come after
+ */
+void device_pm_move_after(struct device *deva, struct device *devb)
+{
+	pr_debug("PM: Moving %s:%s after %s:%s\n",
+		 deva->bus ? deva->bus->name : "No Bus",
+		 kobject_name(&deva->kobj),
+		 devb->bus ? devb->bus->name : "No Bus",
+		 kobject_name(&devb->kobj));
+	/* Delete deva from dpm_list and reinsert after devb. */
+	list_move(&deva->power.entry, &devb->power.entry);
+}
+
+/**
+ * 	device_pm_move_last - move device to end of dpm_list
+ * 	@dev:   Device to move in dpm_list
+ */
+void device_pm_move_last(struct device *dev)
+{
+	pr_debug("PM: Moving %s:%s to end of list\n",
+		 dev->bus ? dev->bus->name : "No Bus",
+		 kobject_name(&dev->kobj));
+	list_move_tail(&dev->power.entry, &dpm_list);
+}
+
+/**
  *	pm_op - execute the PM operation appropiate for given PM event
  *	@dev:	Device.
  *	@ops:	PM operations to choose from.
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 41f51fa..c7cb4fc 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -18,11 +18,19 @@
 
 extern void device_pm_add(struct device *);
 extern void device_pm_remove(struct device *);
+extern void device_pm_move_before(struct device *, struct device *);
+extern void device_pm_move_after(struct device *, struct device *);
+extern void device_pm_move_last(struct device *);
 
 #else /* CONFIG_PM_SLEEP */
 
 static inline void device_pm_add(struct device *dev) {}
 static inline void device_pm_remove(struct device *dev) {}
+static inline void device_pm_move_before(struct device *deva,
+					 struct device *devb) {}
+static inline void device_pm_move_after(struct device *deva,
+					struct device *devb) {}
+static inline void device_pm_move_last(struct device *dev) {}
 
 #endif
 
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index b428c8c..cbd36cf 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -30,10 +30,10 @@
 
 
 static ssize_t
-sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
+sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
 {
-	struct sys_device * sysdev = to_sysdev(kobj);
-	struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
+	struct sys_device *sysdev = to_sysdev(kobj);
+	struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
 
 	if (sysdev_attr->show)
 		return sysdev_attr->show(sysdev, sysdev_attr, buffer);
@@ -42,11 +42,11 @@
 
 
 static ssize_t
-sysdev_store(struct kobject * kobj, struct attribute * attr,
-	     const char * buffer, size_t count)
+sysdev_store(struct kobject *kobj, struct attribute *attr,
+	     const char *buffer, size_t count)
 {
-	struct sys_device * sysdev = to_sysdev(kobj);
-	struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
+	struct sys_device *sysdev = to_sysdev(kobj);
+	struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
 
 	if (sysdev_attr->store)
 		return sysdev_attr->store(sysdev, sysdev_attr, buffer, count);
@@ -63,13 +63,13 @@
 };
 
 
-int sysdev_create_file(struct sys_device * s, struct sysdev_attribute * a)
+int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a)
 {
 	return sysfs_create_file(&s->kobj, &a->attr);
 }
 
 
-void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a)
+void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a)
 {
 	sysfs_remove_file(&s->kobj, &a->attr);
 }
@@ -84,7 +84,7 @@
 static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
 				 char *buffer)
 {
-	struct sysdev_class * class = to_sysdev_class(kobj);
+	struct sysdev_class *class = to_sysdev_class(kobj);
 	struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
 
 	if (class_attr->show)
@@ -95,8 +95,8 @@
 static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr,
 				  const char *buffer, size_t count)
 {
-	struct sysdev_class * class = to_sysdev_class(kobj);
-	struct sysdev_class_attribute * class_attr = to_sysdev_class_attr(attr);
+	struct sysdev_class *class = to_sysdev_class(kobj);
+	struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
 
 	if (class_attr->store)
 		return class_attr->store(class, buffer, count);
@@ -128,7 +128,7 @@
 
 static struct kset *system_kset;
 
-int sysdev_class_register(struct sysdev_class * cls)
+int sysdev_class_register(struct sysdev_class *cls)
 {
 	pr_debug("Registering sysdev class '%s'\n", cls->name);
 
@@ -141,7 +141,7 @@
 	return kset_register(&cls->kset);
 }
 
-void sysdev_class_unregister(struct sysdev_class * cls)
+void sysdev_class_unregister(struct sysdev_class *cls)
 {
 	pr_debug("Unregistering sysdev class '%s'\n",
 		 kobject_name(&cls->kset.kobj));
@@ -203,8 +203,8 @@
  *	@cls:	Class driver belongs to.
  *	@drv:	Driver.
  */
-void sysdev_driver_unregister(struct sysdev_class * cls,
-			      struct sysdev_driver * drv)
+void sysdev_driver_unregister(struct sysdev_class *cls,
+			      struct sysdev_driver *drv)
 {
 	mutex_lock(&sysdev_drivers_lock);
 	list_del_init(&drv->entry);
@@ -229,10 +229,10 @@
  *	@sysdev:	device in question
  *
  */
-int sysdev_register(struct sys_device * sysdev)
+int sysdev_register(struct sys_device *sysdev)
 {
 	int error;
-	struct sysdev_class * cls = sysdev->cls;
+	struct sysdev_class *cls = sysdev->cls;
 
 	if (!cls)
 		return -EINVAL;
@@ -252,7 +252,7 @@
 				     sysdev->id);
 
 	if (!error) {
-		struct sysdev_driver * drv;
+		struct sysdev_driver *drv;
 
 		pr_debug("Registering sys device '%s'\n",
 			 kobject_name(&sysdev->kobj));
@@ -274,9 +274,9 @@
 	return error;
 }
 
-void sysdev_unregister(struct sys_device * sysdev)
+void sysdev_unregister(struct sys_device *sysdev)
 {
-	struct sysdev_driver * drv;
+	struct sysdev_driver *drv;
 
 	mutex_lock(&sysdev_drivers_lock);
 	list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
@@ -305,19 +305,19 @@
  */
 void sysdev_shutdown(void)
 {
-	struct sysdev_class * cls;
+	struct sysdev_class *cls;
 
 	pr_debug("Shutting Down System Devices\n");
 
 	mutex_lock(&sysdev_drivers_lock);
 	list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
-		struct sys_device * sysdev;
+		struct sys_device *sysdev;
 
 		pr_debug("Shutting down type '%s':\n",
 			 kobject_name(&cls->kset.kobj));
 
 		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
-			struct sysdev_driver * drv;
+			struct sysdev_driver *drv;
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
 			/* Call auxillary drivers first */
@@ -364,7 +364,7 @@
  */
 int sysdev_suspend(pm_message_t state)
 {
-	struct sysdev_class * cls;
+	struct sysdev_class *cls;
 	struct sys_device *sysdev, *err_dev;
 	struct sysdev_driver *drv, *err_drv;
 	int ret;
@@ -442,12 +442,12 @@
  */
 int sysdev_resume(void)
 {
-	struct sysdev_class * cls;
+	struct sysdev_class *cls;
 
 	pr_debug("Resuming System Devices\n");
 
 	list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) {
-		struct sys_device * sysdev;
+		struct sys_device *sysdev;
 
 		pr_debug("Resuming type '%s':\n",
 			 kobject_name(&cls->kset.kobj));
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 204332b..87e120e 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy.o
 obj-$(CONFIG_AMIGA_FLOPPY)	+= amiflop.o
 obj-$(CONFIG_PS3_DISK)		+= ps3disk.o
+obj-$(CONFIG_PS3_VRAM)		+= ps3vram.o
 obj-$(CONFIG_ATARI_FLOPPY)	+= ataflop.o
 obj-$(CONFIG_AMIGA_Z2RAM)	+= z2ram.o
 obj-$(CONFIG_BLK_DEV_RAM)	+= brd.o
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index b5a0611..4f9b6d7 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3606,11 +3606,9 @@
 		if (cciss_hard_reset_controller(pdev) || cciss_reset_msi(pdev))
 			return -ENODEV;
 
-		/* Some devices (notably the HP Smart Array 5i Controller)
-		   need a little pause here */
-		schedule_timeout_uninterruptible(30*HZ);
-
-		/* Now try to get the controller to respond to a no-op */
+		/* Now try to get the controller to respond to a no-op. Some
+		   devices (notably the HP Smart Array 5i Controller) need
+		   up to 30 seconds to respond. */
 		for (i=0; i<30; i++) {
 			if (cciss_noop(pdev) == 0)
 				break;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 83d8ed3..c2c95e6 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4135,10 +4135,9 @@
 static ssize_t floppy_cmos_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct platform_device *p;
+	struct platform_device *p = to_platform_device(dev);
 	int drive;
 
-	p = container_of(dev, struct platform_device,dev);
 	drive = p->id;
 	return sprintf(buf, "%X\n", UDP->cmos);
 }
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index edbaac6..bf03455 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -392,8 +392,7 @@
 	struct loop_device *lo = p->lo;
 	struct page *page = buf->page;
 	sector_t IV;
-	size_t size;
-	int ret;
+	int size, ret;
 
 	ret = buf->ops->confirm(pipe, buf);
 	if (unlikely(ret))
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
new file mode 100644
index 0000000..393ed67
--- /dev/null
+++ b/drivers/block/ps3vram.c
@@ -0,0 +1,865 @@
+/*
+ * ps3vram - Use extra PS3 video ram as MTD block device.
+ *
+ * Copyright 2009 Sony Corporation
+ *
+ * Based on the MTD ps3vram driver, which is
+ * Copyright (c) 2007-2008 Jim Paris <jim@jtan.com>
+ * Added support RSX DMA Vivien Chappelier <vivien.chappelier@free.fr>
+ */
+
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <asm/firmware.h>
+#include <asm/lv1call.h>
+#include <asm/ps3.h>
+
+
+#define DEVICE_NAME		"ps3vram"
+
+
+#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */
+#define XDR_IOIF 0x0c000000
+
+#define FIFO_BASE XDR_IOIF
+#define FIFO_SIZE (64 * 1024)
+
+#define DMA_PAGE_SIZE (4 * 1024)
+
+#define CACHE_PAGE_SIZE (256 * 1024)
+#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE)
+
+#define CACHE_OFFSET CACHE_PAGE_SIZE
+#define FIFO_OFFSET 0
+
+#define CTRL_PUT 0x10
+#define CTRL_GET 0x11
+#define CTRL_TOP 0x15
+
+#define UPLOAD_SUBCH	1
+#define DOWNLOAD_SUBCH	2
+
+#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN	0x0000030c
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY	0x00000104
+
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601
+
+#define CACHE_PAGE_PRESENT 1
+#define CACHE_PAGE_DIRTY   2
+
+struct ps3vram_tag {
+	unsigned int address;
+	unsigned int flags;
+};
+
+struct ps3vram_cache {
+	unsigned int page_count;
+	unsigned int page_size;
+	struct ps3vram_tag *tags;
+	unsigned int hit;
+	unsigned int miss;
+};
+
+struct ps3vram_priv {
+	struct request_queue *queue;
+	struct gendisk *gendisk;
+
+	u64 size;
+
+	u64 memory_handle;
+	u64 context_handle;
+	u32 *ctrl;
+	u32 *reports;
+	u8 __iomem *ddr_base;
+	u8 *xdr_buf;
+
+	u32 *fifo_base;
+	u32 *fifo_ptr;
+
+	struct ps3vram_cache cache;
+
+	/* Used to serialize cache/DMA operations */
+	struct mutex lock;
+};
+
+
+static int ps3vram_major;
+
+
+static struct block_device_operations ps3vram_fops = {
+	.owner		= THIS_MODULE,
+};
+
+
+#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */
+#define DMA_NOTIFIER_OFFSET_BASE 0x1000     /* first DMA notifier offset */
+#define DMA_NOTIFIER_SIZE        0x40
+#define NOTIFIER 7	/* notifier used for completion report */
+
+static char *size = "256M";
+module_param(size, charp, 0);
+MODULE_PARM_DESC(size, "memory size");
+
+static u32 *ps3vram_get_notifier(u32 *reports, int notifier)
+{
+	return (void *)reports + DMA_NOTIFIER_OFFSET_BASE +
+	       DMA_NOTIFIER_SIZE * notifier;
+}
+
+static void ps3vram_notifier_reset(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
+	int i;
+
+	for (i = 0; i < 4; i++)
+		notify[i] = 0xffffffff;
+}
+
+static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev,
+				 unsigned int timeout_ms)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
+	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+
+	do {
+		if (!notify[3])
+			return 0;
+		msleep(1);
+	} while (time_before(jiffies, timeout));
+
+	return -ETIMEDOUT;
+}
+
+static void ps3vram_init_ring(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+
+	priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
+	priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET;
+}
+
+static int ps3vram_wait_ring(struct ps3_system_bus_device *dev,
+			     unsigned int timeout_ms)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+
+	do {
+		if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET])
+			return 0;
+		msleep(1);
+	} while (time_before(jiffies, timeout));
+
+	dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n",
+		 priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET],
+		 priv->ctrl[CTRL_TOP]);
+
+	return -ETIMEDOUT;
+}
+
+static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data)
+{
+	*(priv->fifo_ptr)++ = data;
+}
+
+static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, u32 tag,
+			       u32 size)
+{
+	ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag);
+}
+
+static void ps3vram_rewind_ring(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	int status;
+
+	ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET));
+
+	priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
+
+	/* asking the HV for a blit will kick the FIFO */
+	status = lv1_gpu_context_attribute(priv->context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0,
+					   0, 0, 0);
+	if (status)
+		dev_err(&dev->core,
+			"%s: lv1_gpu_context_attribute failed %d\n", __func__,
+			status);
+
+	priv->fifo_ptr = priv->fifo_base;
+}
+
+static void ps3vram_fire_ring(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	int status;
+
+	mutex_lock(&ps3_gpu_mutex);
+
+	priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET +
+			       (priv->fifo_ptr - priv->fifo_base) * sizeof(u32);
+
+	/* asking the HV for a blit will kick the FIFO */
+	status = lv1_gpu_context_attribute(priv->context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0,
+					   0, 0, 0);
+	if (status)
+		dev_err(&dev->core,
+			"%s: lv1_gpu_context_attribute failed %d\n", __func__,
+			status);
+
+	if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) >
+	    FIFO_SIZE - 1024) {
+		dev_dbg(&dev->core, "FIFO full, rewinding\n");
+		ps3vram_wait_ring(dev, 200);
+		ps3vram_rewind_ring(dev);
+	}
+
+	mutex_unlock(&ps3_gpu_mutex);
+}
+
+static void ps3vram_bind(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+
+	ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1);
+	ps3vram_out_ring(priv, 0x31337303);
+	ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3);
+	ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER);
+	ps3vram_out_ring(priv, 0xfeed0001);	/* DMA system RAM instance */
+	ps3vram_out_ring(priv, 0xfeed0000);     /* DMA video RAM instance */
+
+	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1);
+	ps3vram_out_ring(priv, 0x3137c0de);
+	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3);
+	ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER);
+	ps3vram_out_ring(priv, 0xfeed0000);	/* DMA video RAM instance */
+	ps3vram_out_ring(priv, 0xfeed0001);	/* DMA system RAM instance */
+
+	ps3vram_fire_ring(dev);
+}
+
+static int ps3vram_upload(struct ps3_system_bus_device *dev,
+			  unsigned int src_offset, unsigned int dst_offset,
+			  int len, int count)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+
+	ps3vram_begin_ring(priv, UPLOAD_SUBCH,
+			   NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+	ps3vram_out_ring(priv, XDR_IOIF + src_offset);
+	ps3vram_out_ring(priv, dst_offset);
+	ps3vram_out_ring(priv, len);
+	ps3vram_out_ring(priv, len);
+	ps3vram_out_ring(priv, len);
+	ps3vram_out_ring(priv, count);
+	ps3vram_out_ring(priv, (1 << 8) | 1);
+	ps3vram_out_ring(priv, 0);
+
+	ps3vram_notifier_reset(dev);
+	ps3vram_begin_ring(priv, UPLOAD_SUBCH,
+			   NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
+	ps3vram_out_ring(priv, 0);
+	ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1);
+	ps3vram_out_ring(priv, 0);
+	ps3vram_fire_ring(dev);
+	if (ps3vram_notifier_wait(dev, 200) < 0) {
+		dev_warn(&dev->core, "%s: Notifier timeout\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int ps3vram_download(struct ps3_system_bus_device *dev,
+			    unsigned int src_offset, unsigned int dst_offset,
+			    int len, int count)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+
+	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH,
+			   NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+	ps3vram_out_ring(priv, src_offset);
+	ps3vram_out_ring(priv, XDR_IOIF + dst_offset);
+	ps3vram_out_ring(priv, len);
+	ps3vram_out_ring(priv, len);
+	ps3vram_out_ring(priv, len);
+	ps3vram_out_ring(priv, count);
+	ps3vram_out_ring(priv, (1 << 8) | 1);
+	ps3vram_out_ring(priv, 0);
+
+	ps3vram_notifier_reset(dev);
+	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH,
+			   NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
+	ps3vram_out_ring(priv, 0);
+	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1);
+	ps3vram_out_ring(priv, 0);
+	ps3vram_fire_ring(dev);
+	if (ps3vram_notifier_wait(dev, 200) < 0) {
+		dev_warn(&dev->core, "%s: Notifier timeout\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void ps3vram_cache_evict(struct ps3_system_bus_device *dev, int entry)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_cache *cache = &priv->cache;
+
+	if (!(cache->tags[entry].flags & CACHE_PAGE_DIRTY))
+		return;
+
+	dev_dbg(&dev->core, "Flushing %d: 0x%08x\n", entry,
+		cache->tags[entry].address);
+	if (ps3vram_upload(dev, CACHE_OFFSET + entry * cache->page_size,
+			   cache->tags[entry].address, DMA_PAGE_SIZE,
+			   cache->page_size / DMA_PAGE_SIZE) < 0) {
+		dev_err(&dev->core,
+			"Failed to upload from 0x%x to " "0x%x size 0x%x\n",
+			entry * cache->page_size, cache->tags[entry].address,
+			cache->page_size);
+	}
+	cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY;
+}
+
+static void ps3vram_cache_load(struct ps3_system_bus_device *dev, int entry,
+			       unsigned int address)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_cache *cache = &priv->cache;
+
+	dev_dbg(&dev->core, "Fetching %d: 0x%08x\n", entry, address);
+	if (ps3vram_download(dev, address,
+			     CACHE_OFFSET + entry * cache->page_size,
+			     DMA_PAGE_SIZE,
+			     cache->page_size / DMA_PAGE_SIZE) < 0) {
+		dev_err(&dev->core,
+			"Failed to download from 0x%x to 0x%x size 0x%x\n",
+			address, entry * cache->page_size, cache->page_size);
+	}
+
+	cache->tags[entry].address = address;
+	cache->tags[entry].flags |= CACHE_PAGE_PRESENT;
+}
+
+
+static void ps3vram_cache_flush(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_cache *cache = &priv->cache;
+	int i;
+
+	dev_dbg(&dev->core, "FLUSH\n");
+	for (i = 0; i < cache->page_count; i++) {
+		ps3vram_cache_evict(dev, i);
+		cache->tags[i].flags = 0;
+	}
+}
+
+static unsigned int ps3vram_cache_match(struct ps3_system_bus_device *dev,
+					loff_t address)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_cache *cache = &priv->cache;
+	unsigned int base;
+	unsigned int offset;
+	int i;
+	static int counter;
+
+	offset = (unsigned int) (address & (cache->page_size - 1));
+	base = (unsigned int) (address - offset);
+
+	/* fully associative check */
+	for (i = 0; i < cache->page_count; i++) {
+		if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) &&
+		    cache->tags[i].address == base) {
+			cache->hit++;
+			dev_dbg(&dev->core, "Found entry %d: 0x%08x\n", i,
+				cache->tags[i].address);
+			return i;
+		}
+	}
+
+	/* choose a random entry */
+	i = (jiffies + (counter++)) % cache->page_count;
+	dev_dbg(&dev->core, "Using entry %d\n", i);
+
+	ps3vram_cache_evict(dev, i);
+	ps3vram_cache_load(dev, i, base);
+
+	cache->miss++;
+	return i;
+}
+
+static int ps3vram_cache_init(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+
+	priv->cache.page_count = CACHE_PAGE_COUNT;
+	priv->cache.page_size = CACHE_PAGE_SIZE;
+	priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) *
+				   CACHE_PAGE_COUNT, GFP_KERNEL);
+	if (priv->cache.tags == NULL) {
+		dev_err(&dev->core, "Could not allocate cache tags\n");
+		return -ENOMEM;
+	}
+
+	dev_info(&dev->core, "Created ram cache: %d entries, %d KiB each\n",
+		CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024);
+
+	return 0;
+}
+
+static void ps3vram_cache_cleanup(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+
+	ps3vram_cache_flush(dev);
+	kfree(priv->cache.tags);
+}
+
+static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
+			size_t len, size_t *retlen, u_char *buf)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	unsigned int cached, count;
+
+	dev_dbg(&dev->core, "%s: from=0x%08x len=0x%zx\n", __func__,
+		(unsigned int)from, len);
+
+	if (from >= priv->size)
+		return -EIO;
+
+	if (len > priv->size - from)
+		len = priv->size - from;
+
+	/* Copy from vram to buf */
+	count = len;
+	while (count) {
+		unsigned int offset, avail;
+		unsigned int entry;
+
+		offset = (unsigned int) (from & (priv->cache.page_size - 1));
+		avail  = priv->cache.page_size - offset;
+
+		mutex_lock(&priv->lock);
+
+		entry = ps3vram_cache_match(dev, from);
+		cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
+
+		dev_dbg(&dev->core, "%s: from=%08x cached=%08x offset=%08x "
+			"avail=%08x count=%08x\n", __func__,
+			(unsigned int)from, cached, offset, avail, count);
+
+		if (avail > count)
+			avail = count;
+		memcpy(buf, priv->xdr_buf + cached, avail);
+
+		mutex_unlock(&priv->lock);
+
+		buf += avail;
+		count -= avail;
+		from += avail;
+	}
+
+	*retlen = len;
+	return 0;
+}
+
+static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to,
+			 size_t len, size_t *retlen, const u_char *buf)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	unsigned int cached, count;
+
+	if (to >= priv->size)
+		return -EIO;
+
+	if (len > priv->size - to)
+		len = priv->size - to;
+
+	/* Copy from buf to vram */
+	count = len;
+	while (count) {
+		unsigned int offset, avail;
+		unsigned int entry;
+
+		offset = (unsigned int) (to & (priv->cache.page_size - 1));
+		avail  = priv->cache.page_size - offset;
+
+		mutex_lock(&priv->lock);
+
+		entry = ps3vram_cache_match(dev, to);
+		cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
+
+		dev_dbg(&dev->core, "%s: to=%08x cached=%08x offset=%08x "
+			"avail=%08x count=%08x\n", __func__, (unsigned int)to,
+			cached, offset, avail, count);
+
+		if (avail > count)
+			avail = count;
+		memcpy(priv->xdr_buf + cached, buf, avail);
+
+		priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY;
+
+		mutex_unlock(&priv->lock);
+
+		buf += avail;
+		count -= avail;
+		to += avail;
+	}
+
+	*retlen = len;
+	return 0;
+}
+
+static int ps3vram_proc_show(struct seq_file *m, void *v)
+{
+	struct ps3vram_priv *priv = m->private;
+
+	seq_printf(m, "hit:%u\nmiss:%u\n", priv->cache.hit, priv->cache.miss);
+	return 0;
+}
+
+static int ps3vram_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ps3vram_proc_show, PDE(inode)->data);
+}
+
+static const struct file_operations ps3vram_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= ps3vram_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct proc_dir_entry *pde;
+
+	pde = proc_create(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops);
+	if (!pde) {
+		dev_warn(&dev->core, "failed to create /proc entry\n");
+		return;
+	}
+
+	pde->owner = THIS_MODULE;
+	pde->data = priv;
+}
+
+static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
+{
+	struct ps3_system_bus_device *dev = q->queuedata;
+	int write = bio_data_dir(bio) == WRITE;
+	const char *op = write ? "write" : "read";
+	loff_t offset = bio->bi_sector << 9;
+	int error = 0;
+	struct bio_vec *bvec;
+	unsigned int i;
+
+	dev_dbg(&dev->core, "%s\n", __func__);
+
+	bio_for_each_segment(bvec, bio, i) {
+		/* PS3 is ppc64, so we don't handle highmem */
+		char *ptr = page_address(bvec->bv_page) + bvec->bv_offset;
+		size_t len = bvec->bv_len, retlen;
+
+		dev_dbg(&dev->core, "    %s %zu bytes at offset %llu\n", op,
+			len, offset);
+		if (write)
+			error = ps3vram_write(dev, offset, len, &retlen, ptr);
+		else
+			error = ps3vram_read(dev, offset, len, &retlen, ptr);
+
+		if (error) {
+			dev_err(&dev->core, "%s failed\n", op);
+			goto out;
+		}
+
+		if (retlen != len) {
+			dev_err(&dev->core, "Short %s\n", op);
+			goto out;
+		}
+
+		offset += len;
+	}
+
+	dev_dbg(&dev->core, "%s completed\n", op);
+
+out:
+	bio_endio(bio, error);
+	return 0;
+}
+
+static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv;
+	int error, status;
+	struct request_queue *queue;
+	struct gendisk *gendisk;
+	u64 ddr_lpar, ctrl_lpar, info_lpar, reports_lpar, ddr_size,
+	    reports_size;
+	char *rest;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		error = -ENOMEM;
+		goto fail;
+	}
+
+	mutex_init(&priv->lock);
+	dev->core.driver_data = priv;
+
+	priv = dev->core.driver_data;
+
+	/* Allocate XDR buffer (1MiB aligned) */
+	priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL,
+		get_order(XDR_BUF_SIZE));
+	if (priv->xdr_buf == NULL) {
+		dev_err(&dev->core, "Could not allocate XDR buffer\n");
+		error = -ENOMEM;
+		goto fail_free_priv;
+	}
+
+	/* Put FIFO at begginning of XDR buffer */
+	priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET);
+	priv->fifo_ptr = priv->fifo_base;
+
+	/* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */
+	if (ps3_open_hv_device(dev)) {
+		dev_err(&dev->core, "ps3_open_hv_device failed\n");
+		error = -EAGAIN;
+		goto out_close_gpu;
+	}
+
+	/* Request memory */
+	status = -1;
+	ddr_size = ALIGN(memparse(size, &rest), 1024*1024);
+	if (!ddr_size) {
+		dev_err(&dev->core, "Specified size is too small\n");
+		error = -EINVAL;
+		goto out_close_gpu;
+	}
+
+	while (ddr_size > 0) {
+		status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0,
+						 &priv->memory_handle,
+						 &ddr_lpar);
+		if (!status)
+			break;
+		ddr_size -= 1024*1024;
+	}
+	if (status) {
+		dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n",
+			status);
+		error = -ENOMEM;
+		goto out_free_xdr_buf;
+	}
+
+	/* Request context */
+	status = lv1_gpu_context_allocate(priv->memory_handle, 0,
+					  &priv->context_handle, &ctrl_lpar,
+					  &info_lpar, &reports_lpar,
+					  &reports_size);
+	if (status) {
+		dev_err(&dev->core, "lv1_gpu_context_allocate failed %d\n",
+			status);
+		error = -ENOMEM;
+		goto out_free_memory;
+	}
+
+	/* Map XDR buffer to RSX */
+	status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF,
+				       ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)),
+				       XDR_BUF_SIZE, 0);
+	if (status) {
+		dev_err(&dev->core, "lv1_gpu_context_iomap failed %d\n",
+			status);
+		error = -ENOMEM;
+		goto out_free_context;
+	}
+
+	priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE);
+
+	if (!priv->ddr_base) {
+		dev_err(&dev->core, "ioremap DDR failed\n");
+		error = -ENOMEM;
+		goto out_free_context;
+	}
+
+	priv->ctrl = ioremap(ctrl_lpar, 64 * 1024);
+	if (!priv->ctrl) {
+		dev_err(&dev->core, "ioremap CTRL failed\n");
+		error = -ENOMEM;
+		goto out_unmap_vram;
+	}
+
+	priv->reports = ioremap(reports_lpar, reports_size);
+	if (!priv->reports) {
+		dev_err(&dev->core, "ioremap REPORTS failed\n");
+		error = -ENOMEM;
+		goto out_unmap_ctrl;
+	}
+
+	mutex_lock(&ps3_gpu_mutex);
+	ps3vram_init_ring(dev);
+	mutex_unlock(&ps3_gpu_mutex);
+
+	priv->size = ddr_size;
+
+	ps3vram_bind(dev);
+
+	mutex_lock(&ps3_gpu_mutex);
+	error = ps3vram_wait_ring(dev, 100);
+	mutex_unlock(&ps3_gpu_mutex);
+	if (error < 0) {
+		dev_err(&dev->core, "Failed to initialize channels\n");
+		error = -ETIMEDOUT;
+		goto out_unmap_reports;
+	}
+
+	ps3vram_cache_init(dev);
+	ps3vram_proc_init(dev);
+
+	queue = blk_alloc_queue(GFP_KERNEL);
+	if (!queue) {
+		dev_err(&dev->core, "blk_alloc_queue failed\n");
+		error = -ENOMEM;
+		goto out_cache_cleanup;
+	}
+
+	priv->queue = queue;
+	queue->queuedata = dev;
+	blk_queue_make_request(queue, ps3vram_make_request);
+	blk_queue_max_phys_segments(queue, MAX_PHYS_SEGMENTS);
+	blk_queue_max_hw_segments(queue, MAX_HW_SEGMENTS);
+	blk_queue_max_segment_size(queue, MAX_SEGMENT_SIZE);
+	blk_queue_max_sectors(queue, SAFE_MAX_SECTORS);
+
+	gendisk = alloc_disk(1);
+	if (!gendisk) {
+		dev_err(&dev->core, "alloc_disk failed\n");
+		error = -ENOMEM;
+		goto fail_cleanup_queue;
+	}
+
+	priv->gendisk = gendisk;
+	gendisk->major = ps3vram_major;
+	gendisk->first_minor = 0;
+	gendisk->fops = &ps3vram_fops;
+	gendisk->queue = queue;
+	gendisk->private_data = dev;
+	gendisk->driverfs_dev = &dev->core;
+	strlcpy(gendisk->disk_name, DEVICE_NAME, sizeof(gendisk->disk_name));
+	set_capacity(gendisk, priv->size >> 9);
+
+	dev_info(&dev->core, "%s: Using %lu MiB of GPU memory\n",
+		 gendisk->disk_name, get_capacity(gendisk) >> 11);
+
+	add_disk(gendisk);
+	return 0;
+
+fail_cleanup_queue:
+	blk_cleanup_queue(queue);
+out_cache_cleanup:
+	remove_proc_entry(DEVICE_NAME, NULL);
+	ps3vram_cache_cleanup(dev);
+out_unmap_reports:
+	iounmap(priv->reports);
+out_unmap_ctrl:
+	iounmap(priv->ctrl);
+out_unmap_vram:
+	iounmap(priv->ddr_base);
+out_free_context:
+	lv1_gpu_context_free(priv->context_handle);
+out_free_memory:
+	lv1_gpu_memory_free(priv->memory_handle);
+out_close_gpu:
+	ps3_close_hv_device(dev);
+out_free_xdr_buf:
+	free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
+fail_free_priv:
+	kfree(priv);
+	dev->core.driver_data = NULL;
+fail:
+	return error;
+}
+
+static int ps3vram_remove(struct ps3_system_bus_device *dev)
+{
+	struct ps3vram_priv *priv = dev->core.driver_data;
+
+	del_gendisk(priv->gendisk);
+	put_disk(priv->gendisk);
+	blk_cleanup_queue(priv->queue);
+	remove_proc_entry(DEVICE_NAME, NULL);
+	ps3vram_cache_cleanup(dev);
+	iounmap(priv->reports);
+	iounmap(priv->ctrl);
+	iounmap(priv->ddr_base);
+	lv1_gpu_context_free(priv->context_handle);
+	lv1_gpu_memory_free(priv->memory_handle);
+	ps3_close_hv_device(dev);
+	free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
+	kfree(priv);
+	dev->core.driver_data = NULL;
+	return 0;
+}
+
+static struct ps3_system_bus_driver ps3vram = {
+	.match_id	= PS3_MATCH_ID_GPU,
+	.match_sub_id	= PS3_MATCH_SUB_ID_GPU_RAMDISK,
+	.core.name	= DEVICE_NAME,
+	.core.owner	= THIS_MODULE,
+	.probe		= ps3vram_probe,
+	.remove		= ps3vram_remove,
+	.shutdown	= ps3vram_remove,
+};
+
+
+static int __init ps3vram_init(void)
+{
+	int error;
+
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return -ENODEV;
+
+	error = register_blkdev(0, DEVICE_NAME);
+	if (error <= 0) {
+		pr_err("%s: register_blkdev failed %d\n", DEVICE_NAME, error);
+		return error;
+	}
+	ps3vram_major = error;
+
+	pr_info("%s: registered block device major %d\n", DEVICE_NAME,
+		ps3vram_major);
+
+	error = ps3_system_bus_driver_register(&ps3vram);
+	if (error)
+		unregister_blkdev(ps3vram_major, DEVICE_NAME);
+
+	return error;
+}
+
+static void __exit ps3vram_exit(void)
+{
+	ps3_system_bus_driver_unregister(&ps3vram);
+	unregister_blkdev(ps3vram_major, DEVICE_NAME);
+}
+
+module_init(ps3vram_init);
+module_exit(ps3vram_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PS3 Video RAM Storage Driver");
+MODULE_AUTHOR("Sony Corporation");
+MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 12fb816..69b7f8e 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -391,7 +391,7 @@
  */
 #ifdef CONFIG_USB_LIBUSUAL
 
-#define ub_usb_ids  storage_usb_ids
+#define ub_usb_ids  usb_storage_usb_ids
 #else
 
 static struct usb_device_id ub_usb_ids[] = {
@@ -2146,10 +2146,9 @@
 		ep = &altsetting->endpoint[i].desc;
 
 		/* Is it a BULK endpoint? */
-		if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-				== USB_ENDPOINT_XFER_BULK) {
+		if (usb_endpoint_xfer_bulk(ep)) {
 			/* BULK in or out? */
-			if (ep->bEndpointAddress & USB_DIR_IN) {
+			if (usb_endpoint_dir_in(ep)) {
 				if (ep_in == NULL)
 					ep_in = ep;
 			} else {
@@ -2168,9 +2167,9 @@
 	sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0);
 	sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0);
 	sc->send_bulk_pipe = usb_sndbulkpipe(dev,
-		ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+		usb_endpoint_num(ep_out));
 	sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, 
-		ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+		usb_endpoint_num(ep_in));
 
 	return 0;
 }
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index b6c8ce2..8f90508 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -977,6 +977,8 @@
 		break;
 
 	case XenbusStateClosing:
+		if (info->gd == NULL)
+			xenbus_dev_fatal(dev, -ENODEV, "gd is NULL");
 		bd = bdget_disk(info->gd, 0);
 		if (bd == NULL)
 			xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 381d686..119be34 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -489,6 +489,28 @@
 		ace->fsm_state, ace->id_req_count);
 #endif
 
+	/* Verify that there is actually a CF in the slot. If not, then
+	 * bail out back to the idle state and wake up all the waiters */
+	status = ace_in32(ace, ACE_STATUS);
+	if ((status & ACE_STATUS_CFDETECT) == 0) {
+		ace->fsm_state = ACE_FSM_STATE_IDLE;
+		ace->media_change = 1;
+		set_capacity(ace->gd, 0);
+		dev_info(ace->dev, "No CF in slot\n");
+
+		/* Drop all pending requests */
+		while ((req = elv_next_request(ace->queue)) != NULL)
+			end_request(req, 0);
+
+		/* Drop back to IDLE state and notify waiters */
+		ace->fsm_state = ACE_FSM_STATE_IDLE;
+		ace->id_result = -EIO;
+		while (ace->id_req_count) {
+			complete(&ace->id_completion);
+			ace->id_req_count--;
+		}
+	}
+
 	switch (ace->fsm_state) {
 	case ACE_FSM_STATE_IDLE:
 		/* See if there is anything to do */
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 52f4361..d765afd 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -271,15 +271,15 @@
 	nb_order = (nb_order >> 1) & 7;
 	pci_read_config_dword(nb, AMD64_GARTAPERTUREBASE, &nb_base);
 	nb_aper = nb_base << 25;
-	if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) {
-		return 0;
-	}
 
 	/* Northbridge seems to contain crap. Try the AGP bridge. */
 
 	pci_read_config_word(agp, cap+0x14, &apsize);
-	if (apsize == 0xffff)
+	if (apsize == 0xffff) {
+		if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order))
+			return 0;
 		return -1;
+	}
 
 	apsize &= 0xfff;
 	/* Some BIOS use weird encodings not in the AGPv3 table. */
@@ -301,6 +301,11 @@
 		order = nb_order;
 	}
 
+	if (nb_order >= order) {
+		if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order))
+			return 0;
+	}
+
 	dev_info(&agp->dev, "aperture from AGP @ %Lx size %u MB\n",
 		 aper, 32 << order);
 	if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order))
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index c771418..4373adb 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -633,13 +633,15 @@
 			break;
 		}
 	}
-	if (gtt_entries > 0)
+	if (gtt_entries > 0) {
 		dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n",
 		       gtt_entries / KB(1), local ? "local" : "stolen");
-	else
+		gtt_entries /= KB(4);
+	} else {
 		dev_info(&agp_bridge->dev->dev,
 		       "no pre-allocated video memory detected\n");
-	gtt_entries /= KB(4);
+		gtt_entries = 0;
+	}
 
 	intel_private.gtt_entries = gtt_entries;
 }
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index db60539..699e342 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -359,9 +359,16 @@
 	return error;
 }
 
-static struct device *next_device(struct klist_iter *i) {
-	struct klist_node * n = klist_next(i);
-	return n ? container_of(n, struct device, knode_parent) : NULL;
+static int
+find_quicksilver(struct device *dev, void *data)
+{
+	struct parisc_device **lba = data;
+	struct parisc_device *padev = to_parisc_device(dev);
+
+	if (IS_QUICKSILVER(padev))
+		*lba = padev;
+
+	return 0;
 }
 
 static int
@@ -372,8 +379,6 @@
 	int err = -1;
 	struct parisc_device *sba = NULL, *lba = NULL;
 	struct lba_device *lbadev = NULL;
-	struct device *dev = NULL;
-	struct klist_iter i;
 
 	if (!sba_list)
 		goto out;
@@ -386,13 +391,7 @@
 	}
 
 	/* Now search our Pluto for our precious AGP device... */
-	klist_iter_init(&sba->dev.klist_children, &i);
-	while ((dev = next_device(&i))) {
-		struct parisc_device *padev = to_parisc_device(dev);
-		if (IS_QUICKSILVER(padev))
-			lba = padev;
-	}
-	klist_iter_exit(&i);
+	device_for_each_child(&sba->dev, &lba, find_quicksilver);
 
 	if (!lba) {
 		printk(KERN_INFO DRVPFX "No AGP devices found.\n");
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 6e6eb44..c76bccf 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -1139,15 +1139,6 @@
 	hvcsd->tty = tty;
 	tty->driver_data = hvcsd;
 
-	/*
-	 * Set this driver to low latency so that we actually have a chance at
-	 * catching a throttled TTY after we flip_buffer_push.  Otherwise the
-	 * flush_to_async may not execute until after the kernel_thread has
-	 * yielded and resumed the next flip_buffer_push resulting in data
-	 * loss.
-	 */
-	tty->low_latency = 1;
-
 	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
 
 	/*
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index 406f874..2989056 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -810,7 +810,6 @@
 	hp = &hvsi_ports[line];
 
 	tty->driver_data = hp;
-	tty->low_latency = 1; /* avoid throttle/tty_flip_buffer_push race */
 
 	mb();
 	if (hp->state == HVSI_FSP_DIED)
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 8822eca..5fab647 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -20,6 +20,20 @@
 
 	  If unsure, say Y.
 
+config HW_RANDOM_TIMERIOMEM
+	tristate "Timer IOMEM HW Random Number Generator support"
+	depends on HW_RANDOM && HAS_IOMEM
+	---help---
+	  This driver provides kernel-side support for a generic Random
+	  Number Generator used by reading a 'dumb' iomem address that
+	  is to be read no faster than, for example, once a second;
+	  the default FPGA bitstream on the TS-7800 has such functionality.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called timeriomem-rng.
+
+	  If unsure, say Y.
+
 config HW_RANDOM_INTEL
 	tristate "Intel HW Random Number Generator support"
 	depends on HW_RANDOM && (X86 || IA64) && PCI
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index b6effb7..e81d21a 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_HW_RANDOM) += rng-core.o
 rng-core-y := core.o
+obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
 obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
 obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
 obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
new file mode 100644
index 0000000..10ad41b
--- /dev/null
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -0,0 +1,151 @@
+/*
+ * drivers/char/hw_random/timeriomem-rng.c
+ *
+ * Copyright (C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ *
+ * Derived from drivers/char/hw_random/omap-rng.c
+ *   Copyright 2005 (c) MontaVista Software, Inc.
+ *   Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Overview:
+ *   This driver is useful for platforms that have an IO range that provides
+ *   periodic random data from a single IO memory address.  All the platform
+ *   has to do is provide the address and 'wait time' that new data becomes
+ *   available.
+ *
+ * TODO: add support for reading sizes other than 32bits and masking
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/timeriomem-rng.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+
+static struct timeriomem_rng_data *timeriomem_rng_data;
+
+static void timeriomem_rng_trigger(unsigned long);
+static DEFINE_TIMER(timeriomem_rng_timer, timeriomem_rng_trigger, 0, 0);
+
+/*
+ * have data return 1, however return 0 if we have nothing
+ */
+static int timeriomem_rng_data_present(struct hwrng *rng, int wait)
+{
+	if (rng->priv == 0)
+		return 1;
+
+	if (!wait || timeriomem_rng_data->present)
+		return timeriomem_rng_data->present;
+
+	wait_for_completion(&timeriomem_rng_data->completion);
+
+	return 1;
+}
+
+static int timeriomem_rng_data_read(struct hwrng *rng, u32 *data)
+{
+	unsigned long cur;
+	s32 delay;
+
+	*data = readl(timeriomem_rng_data->address);
+
+	if (rng->priv != 0) {
+		cur = jiffies;
+
+		delay = cur - timeriomem_rng_timer.expires;
+		delay = rng->priv - (delay % rng->priv);
+
+		timeriomem_rng_timer.expires = cur + delay;
+		timeriomem_rng_data->present = 0;
+
+		init_completion(&timeriomem_rng_data->completion);
+		add_timer(&timeriomem_rng_timer);
+	}
+
+	return 4;
+}
+
+static void timeriomem_rng_trigger(unsigned long dummy)
+{
+	timeriomem_rng_data->present = 1;
+	complete(&timeriomem_rng_data->completion);
+}
+
+static struct hwrng timeriomem_rng_ops = {
+	.name		= "timeriomem",
+	.data_present	= timeriomem_rng_data_present,
+	.data_read	= timeriomem_rng_data_read,
+	.priv		= 0,
+};
+
+static int __init timeriomem_rng_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	timeriomem_rng_data = pdev->dev.platform_data;
+
+	if (timeriomem_rng_data->period != 0
+		&& usecs_to_jiffies(timeriomem_rng_data->period) > 0) {
+		timeriomem_rng_timer.expires = jiffies;
+
+		timeriomem_rng_ops.priv = usecs_to_jiffies(
+						timeriomem_rng_data->period);
+	}
+	timeriomem_rng_data->present = 1;
+
+	ret = hwrng_register(&timeriomem_rng_ops);
+	if (ret) {
+		dev_err(&pdev->dev, "problem registering\n");
+		return ret;
+	}
+
+	dev_info(&pdev->dev, "32bits from 0x%p @ %dus\n",
+			timeriomem_rng_data->address,
+			timeriomem_rng_data->period);
+
+	return 0;
+}
+
+static int __devexit timeriomem_rng_remove(struct platform_device *pdev)
+{
+	del_timer_sync(&timeriomem_rng_timer);
+	hwrng_unregister(&timeriomem_rng_ops);
+
+	return 0;
+}
+
+static struct platform_driver timeriomem_rng_driver = {
+	.driver = {
+		.name		= "timeriomem_rng",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= timeriomem_rng_probe,
+	.remove		= __devexit_p(timeriomem_rng_remove),
+};
+
+static int __init timeriomem_rng_init(void)
+{
+	return platform_driver_register(&timeriomem_rng_driver);
+}
+
+static void __exit timeriomem_rng_exit(void)
+{
+	platform_driver_unregister(&timeriomem_rng_driver);
+}
+
+module_init(timeriomem_rng_init);
+module_exit(timeriomem_rng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
+MODULE_DESCRIPTION("Timer IOMEM H/W RNG driver");
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 9c47dc4..ccdd828 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -429,134 +429,148 @@
 #define TPM_DIGEST_SIZE 20
 #define TPM_ERROR_SIZE 10
 #define TPM_RET_CODE_IDX 6
-#define TPM_GET_CAP_RET_SIZE_IDX 10
-#define TPM_GET_CAP_RET_UINT32_1_IDX 14
-#define TPM_GET_CAP_RET_UINT32_2_IDX 18
-#define TPM_GET_CAP_RET_UINT32_3_IDX 22
-#define TPM_GET_CAP_RET_UINT32_4_IDX 26
-#define TPM_GET_CAP_PERM_DISABLE_IDX 16
-#define TPM_GET_CAP_PERM_INACTIVE_IDX 18
-#define TPM_GET_CAP_RET_BOOL_1_IDX 14
-#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16
-
-#define TPM_CAP_IDX 13
-#define TPM_CAP_SUBCAP_IDX 21
 
 enum tpm_capabilities {
-	TPM_CAP_FLAG = 4,
-	TPM_CAP_PROP = 5,
+	TPM_CAP_FLAG = cpu_to_be32(4),
+	TPM_CAP_PROP = cpu_to_be32(5),
+	CAP_VERSION_1_1 = cpu_to_be32(0x06),
+	CAP_VERSION_1_2 = cpu_to_be32(0x1A)
 };
 
 enum tpm_sub_capabilities {
-	TPM_CAP_PROP_PCR = 0x1,
-	TPM_CAP_PROP_MANUFACTURER = 0x3,
-	TPM_CAP_FLAG_PERM = 0x8,
-	TPM_CAP_FLAG_VOL = 0x9,
-	TPM_CAP_PROP_OWNER = 0x11,
-	TPM_CAP_PROP_TIS_TIMEOUT = 0x15,
-	TPM_CAP_PROP_TIS_DURATION = 0x20,
+	TPM_CAP_PROP_PCR = cpu_to_be32(0x101),
+	TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103),
+	TPM_CAP_FLAG_PERM = cpu_to_be32(0x108),
+	TPM_CAP_FLAG_VOL = cpu_to_be32(0x109),
+	TPM_CAP_PROP_OWNER = cpu_to_be32(0x111),
+	TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115),
+	TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120),
+
 };
 
-/*
- * This is a semi generic GetCapability command for use
- * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG
- * and their associated sub_capabilities.
- */
-
-static const u8 tpm_cap[] = {
-	0, 193,			/* TPM_TAG_RQU_COMMAND */
-	0, 0, 0, 22,		/* length */
-	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
-	0, 0, 0, 0,		/* TPM_CAP_<TYPE> */
-	0, 0, 0, 4,		/* TPM_CAP_SUB_<TYPE> size */
-	0, 0, 1, 0		/* TPM_CAP_SUB_<TYPE> */
-};
-
-static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
-			    char *desc)
+static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
+			    int len, const char *desc)
 {
 	int err;
 
-	len = tpm_transmit(chip, data, len);
+	len = tpm_transmit(chip,(u8 *) cmd, len);
 	if (len <  0)
 		return len;
 	if (len == TPM_ERROR_SIZE) {
-		err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)));
+		err = be32_to_cpu(cmd->header.out.return_code);
 		dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
 		return err;
 	}
 	return 0;
 }
 
+#define TPM_INTERNAL_RESULT_SIZE 200
+#define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
+#define TPM_ORD_GET_CAP cpu_to_be32(101)
+
+static const struct tpm_input_header tpm_getcap_header = {
+	.tag = TPM_TAG_RQU_COMMAND,
+	.length = cpu_to_be32(22),
+	.ordinal = TPM_ORD_GET_CAP
+};
+
+ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap,
+		   const char *desc)
+{
+	struct tpm_cmd_t tpm_cmd;
+	int rc;
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+
+	tpm_cmd.header.in = tpm_getcap_header;
+	if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) {
+		tpm_cmd.params.getcap_in.cap = subcap_id;
+		/*subcap field not necessary */
+		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0);
+		tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32));
+	} else {
+		if (subcap_id == TPM_CAP_FLAG_PERM ||
+		    subcap_id == TPM_CAP_FLAG_VOL)
+			tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG;
+		else
+			tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
+		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
+		tpm_cmd.params.getcap_in.subcap = subcap_id;
+	}
+	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc);
+	if (!rc)
+		*cap = tpm_cmd.params.getcap_out.cap;
+	return rc;
+}
+
 void tpm_gen_interrupt(struct tpm_chip *chip)
 {
-	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+	struct	tpm_cmd_t tpm_cmd;
 	ssize_t rc;
 
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_PROP;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+	tpm_cmd.header.in = tpm_getcap_header;
+	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
+	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
+	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
 
-	rc = transmit_cmd(chip, data, sizeof(data),
+	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
 			"attempting to determine the timeouts");
 }
 EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
 
 void tpm_get_timeouts(struct tpm_chip *chip)
 {
-	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+	struct tpm_cmd_t tpm_cmd;
+	struct timeout_t *timeout_cap;
+	struct duration_t *duration_cap;
 	ssize_t rc;
 	u32 timeout;
 
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_PROP;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+	tpm_cmd.header.in = tpm_getcap_header;
+	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
+	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
+	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
 
-	rc = transmit_cmd(chip, data, sizeof(data),
+	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
 			"attempting to determine the timeouts");
 	if (rc)
 		goto duration;
 
-	if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+	if (be32_to_cpu(tpm_cmd.header.out.length)
 	    != 4 * sizeof(u32))
 		goto duration;
 
+	timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
 	/* Don't overwrite default if value is 0 */
-	timeout =
-	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+	timeout = be32_to_cpu(timeout_cap->a);
 	if (timeout)
 		chip->vendor.timeout_a = usecs_to_jiffies(timeout);
-	timeout =
-	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+	timeout = be32_to_cpu(timeout_cap->b);
 	if (timeout)
 		chip->vendor.timeout_b = usecs_to_jiffies(timeout);
-	timeout =
-	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+	timeout = be32_to_cpu(timeout_cap->c);
 	if (timeout)
 		chip->vendor.timeout_c = usecs_to_jiffies(timeout);
-	timeout =
-	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
+	timeout = be32_to_cpu(timeout_cap->d);
 	if (timeout)
 		chip->vendor.timeout_d = usecs_to_jiffies(timeout);
 
 duration:
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_PROP;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION;
+	tpm_cmd.header.in = tpm_getcap_header;
+	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
+	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
+	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION;
 
-	rc = transmit_cmd(chip, data, sizeof(data),
+	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
 			"attempting to determine the durations");
 	if (rc)
 		return;
 
-	if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+	if (be32_to_cpu(tpm_cmd.header.out.return_code)
 	    != 3 * sizeof(u32))
 		return;
-
+	duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
 	chip->vendor.duration[TPM_SHORT] =
-	    usecs_to_jiffies(be32_to_cpu
-			     (*((__be32 *) (data +
-					    TPM_GET_CAP_RET_UINT32_1_IDX))));
+	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
 	/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
 	 * value wrong and apparently reports msecs rather than usecs. So we
 	 * fix up the resulting too-small TPM_SHORT value to make things work.
@@ -565,13 +579,9 @@
 		chip->vendor.duration[TPM_SHORT] = HZ;
 
 	chip->vendor.duration[TPM_MEDIUM] =
-	    usecs_to_jiffies(be32_to_cpu
-			     (*((__be32 *) (data +
-					    TPM_GET_CAP_RET_UINT32_2_IDX))));
+	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
 	chip->vendor.duration[TPM_LONG] =
-	    usecs_to_jiffies(be32_to_cpu
-			     (*((__be32 *) (data +
-					    TPM_GET_CAP_RET_UINT32_3_IDX))));
+	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
 }
 EXPORT_SYMBOL_GPL(tpm_get_timeouts);
 
@@ -587,36 +597,18 @@
 }
 EXPORT_SYMBOL_GPL(tpm_continue_selftest);
 
-#define  TPM_INTERNAL_RESULT_SIZE 200
-
 ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
 			char *buf)
 {
-	u8 *data;
+	cap_t cap;
 	ssize_t rc;
 
-	struct tpm_chip *chip = dev_get_drvdata(dev);
-	if (chip == NULL)
-		return -ENODEV;
-
-	data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_FLAG;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
-
-	rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
-			"attemtping to determine the permanent enabled state");
-	if (rc) {
-		kfree(data);
+	rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
+			 "attempting to determine the permanent enabled state");
+	if (rc)
 		return 0;
-	}
 
-	rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
-
-	kfree(data);
+	rc = sprintf(buf, "%d\n", !cap.perm_flags.disable);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_enabled);
@@ -624,31 +616,15 @@
 ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
 			char *buf)
 {
-	u8 *data;
+	cap_t cap;
 	ssize_t rc;
 
-	struct tpm_chip *chip = dev_get_drvdata(dev);
-	if (chip == NULL)
-		return -ENODEV;
-
-	data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_FLAG;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
-
-	rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
-			"attemtping to determine the permanent active state");
-	if (rc) {
-		kfree(data);
+	rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
+			 "attempting to determine the permanent active state");
+	if (rc)
 		return 0;
-	}
 
-	rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
-
-	kfree(data);
+	rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_active);
@@ -656,31 +632,15 @@
 ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
 			char *buf)
 {
-	u8 *data;
+	cap_t cap;
 	ssize_t rc;
 
-	struct tpm_chip *chip = dev_get_drvdata(dev);
-	if (chip == NULL)
-		return -ENODEV;
-
-	data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_PROP;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
-
-	rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
-			"attempting to determine the owner state");
-	if (rc) {
-		kfree(data);
+	rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap,
+			 "attempting to determine the owner state");
+	if (rc)
 		return 0;
-	}
 
-	rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
-
-	kfree(data);
+	rc = sprintf(buf, "%d\n", cap.owned);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_owned);
@@ -688,116 +648,180 @@
 ssize_t tpm_show_temp_deactivated(struct device * dev,
 				struct device_attribute * attr, char *buf)
 {
-	u8 *data;
+	cap_t cap;
 	ssize_t rc;
 
-	struct tpm_chip *chip = dev_get_drvdata(dev);
-	if (chip == NULL)
-		return -ENODEV;
-
-	data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_FLAG;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
-
-	rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
-			"attempting to determine the temporary state");
-	if (rc) {
-		kfree(data);
+	rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap,
+			 "attempting to determine the temporary state");
+	if (rc)
 		return 0;
-	}
 
-	rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
-
-	kfree(data);
+	rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
 
-static const u8 pcrread[] = {
-	0, 193,			/* TPM_TAG_RQU_COMMAND */
-	0, 0, 0, 14,		/* length */
-	0, 0, 0, 21,		/* TPM_ORD_PcrRead */
-	0, 0, 0, 0		/* PCR index */
+/*
+ * tpm_chip_find_get - return tpm_chip for given chip number
+ */
+static struct tpm_chip *tpm_chip_find_get(int chip_num)
+{
+	struct tpm_chip *pos, *chip = NULL;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
+		if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
+			continue;
+
+		if (try_module_get(pos->dev->driver->owner)) {
+			chip = pos;
+			break;
+		}
+	}
+	rcu_read_unlock();
+	return chip;
+}
+
+#define TPM_ORDINAL_PCRREAD cpu_to_be32(21)
+#define READ_PCR_RESULT_SIZE 30
+static struct tpm_input_header pcrread_header = {
+	.tag = TPM_TAG_RQU_COMMAND,
+	.length = cpu_to_be32(14),
+	.ordinal = TPM_ORDINAL_PCRREAD
 };
 
+int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
+{
+	int rc;
+	struct tpm_cmd_t cmd;
+
+	cmd.header.in = pcrread_header;
+	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
+	BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE);
+	rc = transmit_cmd(chip, &cmd, cmd.header.in.length,
+			  "attempting to read a pcr value");
+
+	if (rc == 0)
+		memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
+		       TPM_DIGEST_SIZE);
+	return rc;
+}
+
+/**
+ * tpm_pcr_read - read a pcr value
+ * @chip_num: 	tpm idx # or ANY
+ * @pcr_idx:	pcr idx to retrieve
+ * @res_buf: 	TPM_PCR value
+ * 		size of res_buf is 20 bytes (or NULL if you don't care)
+ *
+ * The TPM driver should be built-in, but for whatever reason it
+ * isn't, protect against the chip disappearing, by incrementing
+ * the module usage count.
+ */
+int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
+{
+	struct tpm_chip *chip;
+	int rc;
+
+	chip = tpm_chip_find_get(chip_num);
+	if (chip == NULL)
+		return -ENODEV;
+	rc = __tpm_pcr_read(chip, pcr_idx, res_buf);
+	module_put(chip->dev->driver->owner);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_read);
+
+/**
+ * tpm_pcr_extend - extend pcr value with hash
+ * @chip_num: 	tpm idx # or AN&
+ * @pcr_idx:	pcr idx to extend
+ * @hash: 	hash value used to extend pcr value
+ *
+ * The TPM driver should be built-in, but for whatever reason it
+ * isn't, protect against the chip disappearing, by incrementing
+ * the module usage count.
+ */
+#define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
+#define EXTEND_PCR_SIZE 34
+static struct tpm_input_header pcrextend_header = {
+	.tag = TPM_TAG_RQU_COMMAND,
+	.length = cpu_to_be32(34),
+	.ordinal = TPM_ORD_PCR_EXTEND
+};
+
+int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
+{
+	struct tpm_cmd_t cmd;
+	int rc;
+	struct tpm_chip *chip;
+
+	chip = tpm_chip_find_get(chip_num);
+	if (chip == NULL)
+		return -ENODEV;
+
+	cmd.header.in = pcrextend_header;
+	BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE);
+	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
+	memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
+	rc = transmit_cmd(chip, &cmd, cmd.header.in.length,
+			  "attempting extend a PCR value");
+
+	module_put(chip->dev->driver->owner);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_extend);
+
 ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
-	u8 *data;
+	cap_t cap;
+	u8 digest[TPM_DIGEST_SIZE];
 	ssize_t rc;
 	int i, j, num_pcrs;
-	__be32 index;
 	char *str = buf;
-
 	struct tpm_chip *chip = dev_get_drvdata(dev);
-	if (chip == NULL)
-		return -ENODEV;
 
-	data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_PROP;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
-
-	rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
+	rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap,
 			"attempting to determine the number of PCRS");
-	if (rc) {
-		kfree(data);
+	if (rc)
 		return 0;
-	}
 
-	num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
+	num_pcrs = be32_to_cpu(cap.num_pcrs);
 	for (i = 0; i < num_pcrs; i++) {
-		memcpy(data, pcrread, sizeof(pcrread));
-		index = cpu_to_be32(i);
-		memcpy(data + 10, &index, 4);
-		rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
-				"attempting to read a PCR");
+		rc = __tpm_pcr_read(chip, i, digest);
 		if (rc)
-			goto out;
+			break;
 		str += sprintf(str, "PCR-%02d: ", i);
 		for (j = 0; j < TPM_DIGEST_SIZE; j++)
-			str += sprintf(str, "%02X ", *(data + 10 + j));
+			str += sprintf(str, "%02X ", digest[j]);
 		str += sprintf(str, "\n");
 	}
-out:
-	kfree(data);
 	return str - buf;
 }
 EXPORT_SYMBOL_GPL(tpm_show_pcrs);
 
 #define  READ_PUBEK_RESULT_SIZE 314
-static const u8 readpubek[] = {
-	0, 193,			/* TPM_TAG_RQU_COMMAND */
-	0, 0, 0, 30,		/* length */
-	0, 0, 0, 124,		/* TPM_ORD_ReadPubek */
+#define TPM_ORD_READPUBEK cpu_to_be32(124)
+struct tpm_input_header tpm_readpubek_header = {
+	.tag = TPM_TAG_RQU_COMMAND,
+	.length = cpu_to_be32(30),
+	.ordinal = TPM_ORD_READPUBEK
 };
 
 ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
 		       char *buf)
 {
 	u8 *data;
+	struct tpm_cmd_t tpm_cmd;
 	ssize_t err;
 	int i, rc;
 	char *str = buf;
 
 	struct tpm_chip *chip = dev_get_drvdata(dev);
-	if (chip == NULL)
-		return -ENODEV;
 
-	data = kzalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	memcpy(data, readpubek, sizeof(readpubek));
-
-	err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE,
+	tpm_cmd.header.in = tpm_readpubek_header;
+	err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
 			"attempting to read the PUBEK");
 	if (err)
 		goto out;
@@ -812,7 +836,7 @@
 	   256 byte modulus
 	   ignore checksum 20 bytes
 	 */
-
+	data = tpm_cmd.params.readpubek_out_buffer;
 	str +=
 	    sprintf(str,
 		    "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
@@ -832,65 +856,33 @@
 	}
 out:
 	rc = str - buf;
-	kfree(data);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_pubek);
 
-#define CAP_VERSION_1_1 6
-#define CAP_VERSION_1_2 0x1A
-#define CAP_VERSION_IDX 13
-static const u8 cap_version[] = {
-	0, 193,			/* TPM_TAG_RQU_COMMAND */
-	0, 0, 0, 18,		/* length */
-	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
-	0, 0, 0, 0,
-	0, 0, 0, 0
-};
 
 ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
-	u8 *data;
+	cap_t cap;
 	ssize_t rc;
 	char *str = buf;
 
-	struct tpm_chip *chip = dev_get_drvdata(dev);
-	if (chip == NULL)
-		return -ENODEV;
-
-	data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_PROP;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
-
-	rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
+	rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap,
 			"attempting to determine the manufacturer");
-	if (rc) {
-		kfree(data);
-		return 0;
-	}
-
-	str += sprintf(str, "Manufacturer: 0x%x\n",
-		       be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
-
-	memcpy(data, cap_version, sizeof(cap_version));
-	data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
-	rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
-			"attempting to determine the 1.1 version");
 	if (rc)
-		goto out;
+		return 0;
+	str += sprintf(str, "Manufacturer: 0x%x\n",
+		       be32_to_cpu(cap.manufacturer_id));
 
+	rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap,
+		        "attempting to determine the 1.1 version");
+	if (rc)
+		return 0;
 	str += sprintf(str,
 		       "TCG version: %d.%d\nFirmware version: %d.%d\n",
-		       (int) data[14], (int) data[15], (int) data[16],
-		       (int) data[17]);
-
-out:
-	kfree(data);
+		       cap.tpm_version.Major, cap.tpm_version.Minor,
+		       cap.tpm_version.revMajor, cap.tpm_version.revMinor);
 	return str - buf;
 }
 EXPORT_SYMBOL_GPL(tpm_show_caps);
@@ -898,51 +890,25 @@
 ssize_t tpm_show_caps_1_2(struct device * dev,
 			  struct device_attribute * attr, char *buf)
 {
-	u8 *data;
-	ssize_t len;
+	cap_t cap;
+	ssize_t rc;
 	char *str = buf;
 
-	struct tpm_chip *chip = dev_get_drvdata(dev);
-	if (chip == NULL)
-		return -ENODEV;
-
-	data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	memcpy(data, tpm_cap, sizeof(tpm_cap));
-	data[TPM_CAP_IDX] = TPM_CAP_PROP;
-	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
-
-	len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE);
-	if (len <= TPM_ERROR_SIZE) {
-		dev_dbg(chip->dev, "A TPM error (%d) occurred "
-			"attempting to determine the manufacturer\n",
-			be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
-		kfree(data);
+	rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap,
+			"attempting to determine the manufacturer");
+	if (rc)
 		return 0;
-	}
-
 	str += sprintf(str, "Manufacturer: 0x%x\n",
-		       be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
-
-	memcpy(data, cap_version, sizeof(cap_version));
-	data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
-
-	len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE);
-	if (len <= TPM_ERROR_SIZE) {
-		dev_err(chip->dev, "A TPM error (%d) occurred "
-			"attempting to determine the 1.2 version\n",
-			be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
-		goto out;
-	}
+		       be32_to_cpu(cap.manufacturer_id));
+	rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap,
+			 "attempting to determine the 1.2 version");
+	if (rc)
+		return 0;
 	str += sprintf(str,
 		       "TCG version: %d.%d\nFirmware version: %d.%d\n",
-		       (int) data[16], (int) data[17], (int) data[18],
-		       (int) data[19]);
-
-out:
-	kfree(data);
+		       cap.tpm_version_1_2.Major, cap.tpm_version_1_2.Minor,
+		       cap.tpm_version_1_2.revMajor,
+		       cap.tpm_version_1_2.revMinor);
 	return str - buf;
 }
 EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 8e30df4..8e00b4d 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -26,6 +26,7 @@
 #include <linux/miscdevice.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/tpm.h>
 
 enum tpm_timeout {
 	TPM_TIMEOUT = 5,	/* msecs */
@@ -123,6 +124,147 @@
 	outb(index, base);
 	outb(value & 0xFF, base+1);
 }
+struct tpm_input_header {
+	__be16	tag;
+	__be32	length;
+	__be32	ordinal;
+}__attribute__((packed));
+
+struct tpm_output_header {
+	__be16	tag;
+	__be32	length;
+	__be32	return_code;
+}__attribute__((packed));
+
+struct	stclear_flags_t {
+	__be16	tag;
+	u8	deactivated;
+	u8	disableForceClear;
+	u8	physicalPresence;
+	u8	physicalPresenceLock;
+	u8	bGlobalLock;
+}__attribute__((packed));
+
+struct	tpm_version_t {
+	u8	Major;
+	u8	Minor;
+	u8	revMajor;
+	u8	revMinor;
+}__attribute__((packed));
+
+struct	tpm_version_1_2_t {
+	__be16	tag;
+	u8	Major;
+	u8	Minor;
+	u8	revMajor;
+	u8	revMinor;
+}__attribute__((packed));
+
+struct	timeout_t {
+	__be32	a;
+	__be32	b;
+	__be32	c;
+	__be32	d;
+}__attribute__((packed));
+
+struct duration_t {
+	__be32	tpm_short;
+	__be32	tpm_medium;
+	__be32	tpm_long;
+}__attribute__((packed));
+
+struct permanent_flags_t {
+	__be16	tag;
+	u8	disable;
+	u8	ownership;
+	u8	deactivated;
+	u8	readPubek;
+	u8	disableOwnerClear;
+	u8	allowMaintenance;
+	u8	physicalPresenceLifetimeLock;
+	u8	physicalPresenceHWEnable;
+	u8	physicalPresenceCMDEnable;
+	u8	CEKPUsed;
+	u8	TPMpost;
+	u8	TPMpostLock;
+	u8	FIPS;
+	u8	operator;
+	u8	enableRevokeEK;
+	u8	nvLocked;
+	u8	readSRKPub;
+	u8	tpmEstablished;
+	u8	maintenanceDone;
+	u8	disableFullDALogicInfo;
+}__attribute__((packed));
+
+typedef union {
+	struct	permanent_flags_t perm_flags;
+	struct	stclear_flags_t	stclear_flags;
+	bool	owned;
+	__be32	num_pcrs;
+	struct	tpm_version_t	tpm_version;
+	struct	tpm_version_1_2_t tpm_version_1_2;
+	__be32	manufacturer_id;
+	struct timeout_t  timeout;
+	struct duration_t duration;
+} cap_t;
+
+struct	tpm_getcap_params_in {
+	__be32	cap;
+	__be32	subcap_size;
+	__be32	subcap;
+}__attribute__((packed));
+
+struct	tpm_getcap_params_out {
+	__be32	cap_size;
+	cap_t	cap;
+}__attribute__((packed));
+
+struct	tpm_readpubek_params_out {
+	u8	algorithm[4];
+	u8	encscheme[2];
+	u8	sigscheme[2];
+	u8	parameters[12]; /*assuming RSA*/
+	__be32	keysize;
+	u8	modulus[256];
+	u8	checksum[20];
+}__attribute__((packed));
+
+typedef union {
+	struct	tpm_input_header in;
+	struct	tpm_output_header out;
+} tpm_cmd_header;
+
+#define TPM_DIGEST_SIZE 20
+struct tpm_pcrread_out {
+	u8	pcr_result[TPM_DIGEST_SIZE];
+}__attribute__((packed));
+
+struct tpm_pcrread_in {
+	__be32	pcr_idx;
+}__attribute__((packed));
+
+struct tpm_pcrextend_in {
+	__be32	pcr_idx;
+	u8	hash[TPM_DIGEST_SIZE];
+}__attribute__((packed));
+
+typedef union {
+	struct	tpm_getcap_params_out getcap_out;
+	struct	tpm_readpubek_params_out readpubek_out;
+	u8	readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
+	struct	tpm_getcap_params_in getcap_in;
+	struct	tpm_pcrread_in	pcrread_in;
+	struct	tpm_pcrread_out	pcrread_out;
+	struct	tpm_pcrextend_in pcrextend_in;
+} tpm_cmd_params;
+
+struct tpm_cmd_t {
+	tpm_cmd_header	header;
+	tpm_cmd_params	params;
+}__attribute__((packed));
+
+ssize_t	tpm_getcap(struct device *, __be32, cap_t *, const char *);
 
 extern void tpm_get_timeouts(struct tpm_chip *);
 extern void tpm_gen_interrupt(struct tpm_chip *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index d0e7926..c64a1bc 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -168,12 +168,22 @@
 	}
 }
 
-static struct device_driver atml_drv = {
-	.name = "tpm_atmel",
-	.bus = &platform_bus_type,
-	.owner = THIS_MODULE,
-	.suspend = tpm_pm_suspend,
-	.resume = tpm_pm_resume,
+static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg)
+{
+	return tpm_pm_suspend(&dev->dev, msg);
+}
+
+static int tpm_atml_resume(struct platform_device *dev)
+{
+	return tpm_pm_resume(&dev->dev);
+}
+static struct platform_driver atml_drv = {
+	.driver = {
+		.name = "tpm_atmel",
+		.owner		= THIS_MODULE,
+	},
+	.suspend = tpm_atml_suspend,
+	.resume = tpm_atml_resume,
 };
 
 static int __init init_atmel(void)
@@ -184,7 +194,7 @@
 	unsigned long base;
 	struct  tpm_chip *chip;
 
-	rc = driver_register(&atml_drv);
+	rc = platform_driver_register(&atml_drv);
 	if (rc)
 		return rc;
 
@@ -223,13 +233,13 @@
 		atmel_release_region(base,
 				     region_size);
 err_unreg_drv:
-	driver_unregister(&atml_drv);
+	platform_driver_unregister(&atml_drv);
 	return rc;
 }
 
 static void __exit cleanup_atmel(void)
 {
-	driver_unregister(&atml_drv);
+	platform_driver_unregister(&atml_drv);
 	atml_plat_remove();
 }
 
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 717af7a..aec1931 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -654,12 +654,22 @@
 		    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
 MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
 
-static struct device_driver tis_drv = {
-	.name = "tpm_tis",
-	.bus = &platform_bus_type,
-	.owner = THIS_MODULE,
-	.suspend = tpm_pm_suspend,
-	.resume = tpm_pm_resume,
+static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
+{
+	return tpm_pm_suspend(&dev->dev, msg);
+}
+
+static int tpm_tis_resume(struct platform_device *dev)
+{
+	return tpm_pm_resume(&dev->dev);
+}
+static struct platform_driver tis_drv = {
+	.driver = {
+		.name = "tpm_tis",
+		.owner		= THIS_MODULE,
+	},
+	.suspend = tpm_tis_suspend,
+	.resume = tpm_tis_resume,
 };
 
 static struct platform_device *pdev;
@@ -672,14 +682,14 @@
 	int rc;
 
 	if (force) {
-		rc = driver_register(&tis_drv);
+		rc = platform_driver_register(&tis_drv);
 		if (rc < 0)
 			return rc;
 		if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0)))
 			return PTR_ERR(pdev);
 		if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) {
 			platform_device_unregister(pdev);
-			driver_unregister(&tis_drv);
+			platform_driver_unregister(&tis_drv);
 		}
 		return rc;
 	}
@@ -711,7 +721,7 @@
 
 	if (force) {
 		platform_device_unregister(pdev);
-		driver_unregister(&tis_drv);
+		platform_driver_unregister(&tis_drv);
 	} else
 		pnp_unregister_driver(&tis_pnp_driver);
 }
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 4f3b3f9..d94d25c 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -479,18 +479,18 @@
 
 static struct class *vc_class;
 
-void vcs_make_sysfs(struct tty_struct *tty)
+void vcs_make_sysfs(int index)
 {
-	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), NULL,
-		      "vcs%u", tty->index + 1);
-	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), NULL,
-		      "vcsa%u", tty->index + 1);
+	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 1), NULL,
+		      "vcs%u", index + 1);
+	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 129), NULL,
+		      "vcsa%u", index + 1);
 }
 
-void vcs_remove_sysfs(struct tty_struct *tty)
+void vcs_remove_sysfs(int index)
 {
-	device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
-	device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
+	device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 1));
+	device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 129));
 }
 
 int __init vcs_init(void)
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 7900bd6..2c1d133 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -778,6 +778,7 @@
 	    }
 	    vc->vc_kmalloced = 1;
 	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
+	    vcs_make_sysfs(currcons);
 	    atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
 	}
 	return 0;
@@ -987,7 +988,9 @@
 	if (vc_cons_allocated(currcons)) {
 		struct vc_data *vc = vc_cons[currcons].d;
 		struct vt_notifier_param param = { .vc = vc };
+
 		atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
+		vcs_remove_sysfs(currcons);
 		vc->vc_sw->con_deinit(vc);
 		put_pid(vc->vt_pid);
 		module_put(vc->vc_sw->owner);
@@ -2775,7 +2778,6 @@
 				tty->termios->c_iflag |= IUTF8;
 			else
 				tty->termios->c_iflag &= ~IUTF8;
-			vcs_make_sysfs(tty);
 			release_console_sem();
 			return ret;
 		}
@@ -2795,7 +2797,6 @@
 	BUG_ON(vc == NULL);
 	acquire_console_sem();
 	vc->vc_tty = NULL;
-	vcs_remove_sysfs(tty);
 	release_console_sem();
 	tty_shutdown(tty);
 }
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 1525882..1efb287 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_X86_CYCLONE_TIMER)	+= cyclone.o
 obj-$(CONFIG_X86_PM_TIMER)	+= acpi_pm.o
 obj-$(CONFIG_SCx200HR_TIMER)	+= scx200_hrt.o
+obj-$(CONFIG_SH_TIMER_CMT)	+= sh_cmt.o
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
new file mode 100644
index 0000000..7783b42
--- /dev/null
+++ b/drivers/clocksource/sh_cmt.c
@@ -0,0 +1,615 @@
+/*
+ * SuperH Timer Support - CMT
+ *
+ *  Copyright (C) 2008 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/sh_cmt.h>
+
+struct sh_cmt_priv {
+	void __iomem *mapbase;
+	struct clk *clk;
+	unsigned long width; /* 16 or 32 bit version of hardware block */
+	unsigned long overflow_bit;
+	unsigned long clear_bits;
+	struct irqaction irqaction;
+	struct platform_device *pdev;
+
+	unsigned long flags;
+	unsigned long match_value;
+	unsigned long next_match_value;
+	unsigned long max_match_value;
+	unsigned long rate;
+	spinlock_t lock;
+	struct clock_event_device ced;
+	unsigned long total_cycles;
+};
+
+static DEFINE_SPINLOCK(sh_cmt_lock);
+
+#define CMSTR -1 /* shared register */
+#define CMCSR 0 /* channel register */
+#define CMCNT 1 /* channel register */
+#define CMCOR 2 /* channel register */
+
+static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
+{
+	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs;
+
+	if (reg_nr == CMSTR) {
+		offs = 0;
+		base -= cfg->channel_offset;
+	} else
+		offs = reg_nr;
+
+	if (p->width == 16)
+		offs <<= 1;
+	else {
+		offs <<= 2;
+		if ((reg_nr == CMCNT) || (reg_nr == CMCOR))
+			return ioread32(base + offs);
+	}
+
+	return ioread16(base + offs);
+}
+
+static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
+				unsigned long value)
+{
+	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs;
+
+	if (reg_nr == CMSTR) {
+		offs = 0;
+		base -= cfg->channel_offset;
+	} else
+		offs = reg_nr;
+
+	if (p->width == 16)
+		offs <<= 1;
+	else {
+		offs <<= 2;
+		if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) {
+			iowrite32(value, base + offs);
+			return;
+		}
+	}
+
+	iowrite16(value, base + offs);
+}
+
+static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
+					int *has_wrapped)
+{
+	unsigned long v1, v2, v3;
+
+	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
+	do {
+		v1 = sh_cmt_read(p, CMCNT);
+		v2 = sh_cmt_read(p, CMCNT);
+		v3 = sh_cmt_read(p, CMCNT);
+	} while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
+			  || (v3 > v1 && v3 < v2)));
+
+	*has_wrapped = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+	return v2;
+}
+
+
+static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
+{
+	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+	unsigned long flags, value;
+
+	/* start stop register shared by multiple timer channels */
+	spin_lock_irqsave(&sh_cmt_lock, flags);
+	value = sh_cmt_read(p, CMSTR);
+
+	if (start)
+		value |= 1 << cfg->timer_bit;
+	else
+		value &= ~(1 << cfg->timer_bit);
+
+	sh_cmt_write(p, CMSTR, value);
+	spin_unlock_irqrestore(&sh_cmt_lock, flags);
+}
+
+static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
+{
+	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+	int ret;
+
+	/* enable clock */
+	ret = clk_enable(p->clk);
+	if (ret) {
+		pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk);
+		return ret;
+	}
+	*rate = clk_get_rate(p->clk) / 8;
+
+	/* make sure channel is disabled */
+	sh_cmt_start_stop_ch(p, 0);
+
+	/* configure channel, periodic mode and maximum timeout */
+	if (p->width == 16)
+		sh_cmt_write(p, CMCSR, 0);
+	else
+		sh_cmt_write(p, CMCSR, 0x01a4);
+
+	sh_cmt_write(p, CMCOR, 0xffffffff);
+	sh_cmt_write(p, CMCNT, 0);
+
+	/* enable channel */
+	sh_cmt_start_stop_ch(p, 1);
+	return 0;
+}
+
+static void sh_cmt_disable(struct sh_cmt_priv *p)
+{
+	/* disable channel */
+	sh_cmt_start_stop_ch(p, 0);
+
+	/* stop clock */
+	clk_disable(p->clk);
+}
+
+/* private flags */
+#define FLAG_CLOCKEVENT (1 << 0)
+#define FLAG_CLOCKSOURCE (1 << 1)
+#define FLAG_REPROGRAM (1 << 2)
+#define FLAG_SKIPEVENT (1 << 3)
+#define FLAG_IRQCONTEXT (1 << 4)
+
+static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
+					      int absolute)
+{
+	unsigned long new_match;
+	unsigned long value = p->next_match_value;
+	unsigned long delay = 0;
+	unsigned long now = 0;
+	int has_wrapped;
+
+	now = sh_cmt_get_counter(p, &has_wrapped);
+	p->flags |= FLAG_REPROGRAM; /* force reprogram */
+
+	if (has_wrapped) {
+		/* we're competing with the interrupt handler.
+		 *  -> let the interrupt handler reprogram the timer.
+		 *  -> interrupt number two handles the event.
+		 */
+		p->flags |= FLAG_SKIPEVENT;
+		return;
+	}
+
+	if (absolute)
+		now = 0;
+
+	do {
+		/* reprogram the timer hardware,
+		 * but don't save the new match value yet.
+		 */
+		new_match = now + value + delay;
+		if (new_match > p->max_match_value)
+			new_match = p->max_match_value;
+
+		sh_cmt_write(p, CMCOR, new_match);
+
+		now = sh_cmt_get_counter(p, &has_wrapped);
+		if (has_wrapped && (new_match > p->match_value)) {
+			/* we are changing to a greater match value,
+			 * so this wrap must be caused by the counter
+			 * matching the old value.
+			 * -> first interrupt reprograms the timer.
+			 * -> interrupt number two handles the event.
+			 */
+			p->flags |= FLAG_SKIPEVENT;
+			break;
+		}
+
+		if (has_wrapped) {
+			/* we are changing to a smaller match value,
+			 * so the wrap must be caused by the counter
+			 * matching the new value.
+			 * -> save programmed match value.
+			 * -> let isr handle the event.
+			 */
+			p->match_value = new_match;
+			break;
+		}
+
+		/* be safe: verify hardware settings */
+		if (now < new_match) {
+			/* timer value is below match value, all good.
+			 * this makes sure we won't miss any match events.
+			 * -> save programmed match value.
+			 * -> let isr handle the event.
+			 */
+			p->match_value = new_match;
+			break;
+		}
+
+		/* the counter has reached a value greater
+		 * than our new match value. and since the
+		 * has_wrapped flag isn't set we must have
+		 * programmed a too close event.
+		 * -> increase delay and retry.
+		 */
+		if (delay)
+			delay <<= 1;
+		else
+			delay = 1;
+
+		if (!delay)
+			pr_warning("sh_cmt: too long delay\n");
+
+	} while (delay);
+}
+
+static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+{
+	unsigned long flags;
+
+	if (delta > p->max_match_value)
+		pr_warning("sh_cmt: delta out of range\n");
+
+	spin_lock_irqsave(&p->lock, flags);
+	p->next_match_value = delta;
+	sh_cmt_clock_event_program_verify(p, 0);
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
+{
+	struct sh_cmt_priv *p = dev_id;
+
+	/* clear flags */
+	sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits);
+
+	/* update clock source counter to begin with if enabled
+	 * the wrap flag should be cleared by the timer specific
+	 * isr before we end up here.
+	 */
+	if (p->flags & FLAG_CLOCKSOURCE)
+		p->total_cycles += p->match_value;
+
+	if (!(p->flags & FLAG_REPROGRAM))
+		p->next_match_value = p->max_match_value;
+
+	p->flags |= FLAG_IRQCONTEXT;
+
+	if (p->flags & FLAG_CLOCKEVENT) {
+		if (!(p->flags & FLAG_SKIPEVENT)) {
+			if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) {
+				p->next_match_value = p->max_match_value;
+				p->flags |= FLAG_REPROGRAM;
+			}
+
+			p->ced.event_handler(&p->ced);
+		}
+	}
+
+	p->flags &= ~FLAG_SKIPEVENT;
+
+	if (p->flags & FLAG_REPROGRAM) {
+		p->flags &= ~FLAG_REPROGRAM;
+		sh_cmt_clock_event_program_verify(p, 1);
+
+		if (p->flags & FLAG_CLOCKEVENT)
+			if ((p->ced.mode == CLOCK_EVT_MODE_SHUTDOWN)
+			    || (p->match_value == p->next_match_value))
+				p->flags &= ~FLAG_REPROGRAM;
+	}
+
+	p->flags &= ~FLAG_IRQCONTEXT;
+
+	return IRQ_HANDLED;
+}
+
+static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&p->lock, flags);
+
+	if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
+		ret = sh_cmt_enable(p, &p->rate);
+
+	if (ret)
+		goto out;
+	p->flags |= flag;
+
+	/* setup timeout if no clockevent */
+	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
+		sh_cmt_set_next(p, p->max_match_value);
+ out:
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	return ret;
+}
+
+static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
+{
+	unsigned long flags;
+	unsigned long f;
+
+	spin_lock_irqsave(&p->lock, flags);
+
+	f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
+	p->flags &= ~flag;
+
+	if (f && !(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
+		sh_cmt_disable(p);
+
+	/* adjust the timeout to maximum if only clocksource left */
+	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
+		sh_cmt_set_next(p, p->max_match_value);
+
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced)
+{
+	return container_of(ced, struct sh_cmt_priv, ced);
+}
+
+static void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic)
+{
+	struct clock_event_device *ced = &p->ced;
+
+	sh_cmt_start(p, FLAG_CLOCKEVENT);
+
+	/* TODO: calculate good shift from rate and counter bit width */
+
+	ced->shift = 32;
+	ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
+	ced->max_delta_ns = clockevent_delta2ns(p->max_match_value, ced);
+	ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);
+
+	if (periodic)
+		sh_cmt_set_next(p, (p->rate + HZ/2) / HZ);
+	else
+		sh_cmt_set_next(p, p->max_match_value);
+}
+
+static void sh_cmt_clock_event_mode(enum clock_event_mode mode,
+				    struct clock_event_device *ced)
+{
+	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
+
+	/* deal with old setting first */
+	switch (ced->mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+	case CLOCK_EVT_MODE_ONESHOT:
+		sh_cmt_stop(p, FLAG_CLOCKEVENT);
+		break;
+	default:
+		break;
+	}
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		pr_info("sh_cmt: %s used for periodic clock events\n",
+			ced->name);
+		sh_cmt_clock_event_start(p, 1);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		pr_info("sh_cmt: %s used for oneshot clock events\n",
+			ced->name);
+		sh_cmt_clock_event_start(p, 0);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		sh_cmt_stop(p, FLAG_CLOCKEVENT);
+		break;
+	default:
+		break;
+	}
+}
+
+static int sh_cmt_clock_event_next(unsigned long delta,
+				   struct clock_event_device *ced)
+{
+	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
+
+	BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
+	if (likely(p->flags & FLAG_IRQCONTEXT))
+		p->next_match_value = delta;
+	else
+		sh_cmt_set_next(p, delta);
+
+	return 0;
+}
+
+static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
+				       char *name, unsigned long rating)
+{
+	struct clock_event_device *ced = &p->ced;
+
+	memset(ced, 0, sizeof(*ced));
+
+	ced->name = name;
+	ced->features = CLOCK_EVT_FEAT_PERIODIC;
+	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
+	ced->rating = rating;
+	ced->cpumask = cpumask_of(0);
+	ced->set_next_event = sh_cmt_clock_event_next;
+	ced->set_mode = sh_cmt_clock_event_mode;
+
+	pr_info("sh_cmt: %s used for clock events\n", ced->name);
+	ced->mult = 1; /* work around misplaced WARN_ON() in clockevents.c */
+	clockevents_register_device(ced);
+}
+
+int sh_cmt_register(struct sh_cmt_priv *p, char *name,
+		    unsigned long clockevent_rating,
+		    unsigned long clocksource_rating)
+{
+	if (p->width == (sizeof(p->max_match_value) * 8))
+		p->max_match_value = ~0;
+	else
+		p->max_match_value = (1 << p->width) - 1;
+
+	p->match_value = p->max_match_value;
+	spin_lock_init(&p->lock);
+
+	if (clockevent_rating)
+		sh_cmt_register_clockevent(p, name, clockevent_rating);
+
+	return 0;
+}
+
+static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
+{
+	struct sh_cmt_config *cfg = pdev->dev.platform_data;
+	struct resource *res;
+	int irq, ret;
+	ret = -ENXIO;
+
+	memset(p, 0, sizeof(*p));
+	p->pdev = pdev;
+
+	if (!cfg) {
+		dev_err(&p->pdev->dev, "missing platform data\n");
+		goto err0;
+	}
+
+	platform_set_drvdata(pdev, p);
+
+	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
+		goto err0;
+	}
+
+	irq = platform_get_irq(p->pdev, 0);
+	if (irq < 0) {
+		dev_err(&p->pdev->dev, "failed to get irq\n");
+		goto err0;
+	}
+
+	/* map memory, let mapbase point to our channel */
+	p->mapbase = ioremap_nocache(res->start, resource_size(res));
+	if (p->mapbase == NULL) {
+		pr_err("sh_cmt: failed to remap I/O memory\n");
+		goto err0;
+	}
+
+	/* request irq using setup_irq() (too early for request_irq()) */
+	p->irqaction.name = cfg->name;
+	p->irqaction.handler = sh_cmt_interrupt;
+	p->irqaction.dev_id = p;
+	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
+	p->irqaction.mask = CPU_MASK_NONE;
+	ret = setup_irq(irq, &p->irqaction);
+	if (ret) {
+		pr_err("sh_cmt: failed to request irq %d\n", irq);
+		goto err1;
+	}
+
+	/* get hold of clock */
+	p->clk = clk_get(&p->pdev->dev, cfg->clk);
+	if (IS_ERR(p->clk)) {
+		pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk);
+		ret = PTR_ERR(p->clk);
+		goto err2;
+	}
+
+	if (resource_size(res) == 6) {
+		p->width = 16;
+		p->overflow_bit = 0x80;
+		p->clear_bits = ~0xc0;
+	} else {
+		p->width = 32;
+		p->overflow_bit = 0x8000;
+		p->clear_bits = ~0xc000;
+	}
+
+	return sh_cmt_register(p, cfg->name,
+			       cfg->clockevent_rating,
+			       cfg->clocksource_rating);
+ err2:
+	free_irq(irq, p);
+ err1:
+	iounmap(p->mapbase);
+ err0:
+	return ret;
+}
+
+static int __devinit sh_cmt_probe(struct platform_device *pdev)
+{
+	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+	int ret;
+
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (p == NULL) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	ret = sh_cmt_setup(p, pdev);
+	if (ret) {
+		kfree(p);
+
+		platform_set_drvdata(pdev, NULL);
+	}
+	return ret;
+}
+
+static int __devexit sh_cmt_remove(struct platform_device *pdev)
+{
+	return -EBUSY; /* cannot unregister clockevent and clocksource */
+}
+
+static struct platform_driver sh_cmt_device_driver = {
+	.probe		= sh_cmt_probe,
+	.remove		= __devexit_p(sh_cmt_remove),
+	.driver		= {
+		.name	= "sh_cmt",
+	}
+};
+
+static int __init sh_cmt_init(void)
+{
+	return platform_driver_register(&sh_cmt_device_driver);
+}
+
+static void __exit sh_cmt_exit(void)
+{
+	platform_driver_unregister(&sh_cmt_device_driver);
+}
+
+module_init(sh_cmt_init);
+module_exit(sh_cmt_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("SuperH CMT Timer Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index b55cb67..d270e8e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -104,7 +104,8 @@
 
 
 /* internal prototypes */
-static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
+static int __cpufreq_governor(struct cpufreq_policy *policy,
+		unsigned int event);
 static unsigned int __cpufreq_get(unsigned int cpu);
 static void handle_update(struct work_struct *work);
 
@@ -128,7 +129,7 @@
 pure_initcall(init_cpufreq_transition_notifier_list);
 
 static LIST_HEAD(cpufreq_governor_list);
-static DEFINE_MUTEX (cpufreq_governor_mutex);
+static DEFINE_MUTEX(cpufreq_governor_mutex);
 
 struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
 {
@@ -371,7 +372,7 @@
 	struct cpufreq_governor *t;
 
 	list_for_each_entry(t, &cpufreq_governor_list, governor_list)
-		if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN))
+		if (!strnicmp(str_governor, t->name, CPUFREQ_NAME_LEN))
 			return t;
 
 	return NULL;
@@ -429,15 +430,11 @@
 
 		mutex_unlock(&cpufreq_governor_mutex);
 	}
-  out:
+out:
 	return err;
 }
 
 
-/* drivers/base/cpu.c */
-extern struct sysdev_class cpu_sysdev_class;
-
-
 /**
  * cpufreq_per_cpu_attr_read() / show_##file_name() -
  * print out cpufreq information
@@ -450,11 +447,12 @@
 static ssize_t show_##file_name				\
 (struct cpufreq_policy *policy, char *buf)		\
 {							\
-	return sprintf (buf, "%u\n", policy->object);	\
+	return sprintf(buf, "%u\n", policy->object);	\
 }
 
 show_one(cpuinfo_min_freq, cpuinfo.min_freq);
 show_one(cpuinfo_max_freq, cpuinfo.max_freq);
+show_one(cpuinfo_transition_latency, cpuinfo.transition_latency);
 show_one(scaling_min_freq, min);
 show_one(scaling_max_freq, max);
 show_one(scaling_cur_freq, cur);
@@ -476,7 +474,7 @@
 	if (ret)							\
 		return -EINVAL;						\
 									\
-	ret = sscanf (buf, "%u", &new_policy.object);			\
+	ret = sscanf(buf, "%u", &new_policy.object);			\
 	if (ret != 1)							\
 		return -EINVAL;						\
 									\
@@ -486,8 +484,8 @@
 	return ret ? ret : count;					\
 }
 
-store_one(scaling_min_freq,min);
-store_one(scaling_max_freq,max);
+store_one(scaling_min_freq, min);
+store_one(scaling_max_freq, max);
 
 /**
  * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware
@@ -507,12 +505,13 @@
  */
 static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
 {
-	if(policy->policy == CPUFREQ_POLICY_POWERSAVE)
+	if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
 		return sprintf(buf, "powersave\n");
 	else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
 		return sprintf(buf, "performance\n");
 	else if (policy->governor)
-		return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name);
+		return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n",
+				policy->governor->name);
 	return -EINVAL;
 }
 
@@ -531,7 +530,7 @@
 	if (ret)
 		return ret;
 
-	ret = sscanf (buf, "%15s", str_governor);
+	ret = sscanf(buf, "%15s", str_governor);
 	if (ret != 1)
 		return -EINVAL;
 
@@ -575,7 +574,8 @@
 	}
 
 	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
+		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
+		    - (CPUFREQ_NAME_LEN + 2)))
 			goto out;
 		i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
 	}
@@ -594,7 +594,7 @@
 			i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
 		i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
 		if (i >= (PAGE_SIZE - 5))
-		    break;
+			break;
 	}
 	i += sprintf(&buf[i], "\n");
 	return i;
@@ -660,6 +660,7 @@
 define_one_ro0400(cpuinfo_cur_freq);
 define_one_ro(cpuinfo_min_freq);
 define_one_ro(cpuinfo_max_freq);
+define_one_ro(cpuinfo_transition_latency);
 define_one_ro(scaling_available_governors);
 define_one_ro(scaling_driver);
 define_one_ro(scaling_cur_freq);
@@ -673,6 +674,7 @@
 static struct attribute *default_attrs[] = {
 	&cpuinfo_min_freq.attr,
 	&cpuinfo_max_freq.attr,
+	&cpuinfo_transition_latency.attr,
 	&scaling_min_freq.attr,
 	&scaling_max_freq.attr,
 	&affected_cpus.attr,
@@ -684,10 +686,10 @@
 	NULL
 };
 
-#define to_policy(k) container_of(k,struct cpufreq_policy,kobj)
-#define to_attr(a) container_of(a,struct freq_attr,attr)
+#define to_policy(k) container_of(k, struct cpufreq_policy, kobj)
+#define to_attr(a) container_of(a, struct freq_attr, attr)
 
-static ssize_t show(struct kobject *kobj, struct attribute *attr ,char *buf)
+static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
 {
 	struct cpufreq_policy *policy = to_policy(kobj);
 	struct freq_attr *fattr = to_attr(attr);
@@ -754,11 +756,6 @@
 	.release	= cpufreq_sysfs_release,
 };
 
-static struct kobj_type ktype_empty_cpufreq = {
-	.sysfs_ops	= &sysfs_ops,
-	.release	= cpufreq_sysfs_release,
-};
-
 
 /**
  * cpufreq_add_dev - add a CPU device
@@ -858,10 +855,10 @@
 		if (cpu == j)
 			continue;
 
-		/* check for existing affected CPUs.  They may not be aware
-		 * of it due to CPU Hotplug.
+		/* Check for existing affected CPUs.
+		 * They may not be aware of it due to CPU Hotplug.
 		 */
-		managed_policy = cpufreq_cpu_get(j);		// FIXME: Where is this released?  What about error paths?
+		managed_policy = cpufreq_cpu_get(j);		/* FIXME: Where is this released?  What about error paths? */
 		if (unlikely(managed_policy)) {
 
 			/* Set proper policy_cpu */
@@ -892,36 +889,26 @@
 	memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
 
 	/* prepare interface data */
-	if (!cpufreq_driver->hide_interface) {
-		ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
-					   &sys_dev->kobj, "cpufreq");
+	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
+				   "cpufreq");
+	if (ret)
+		goto err_out_driver_exit;
+
+	/* set up files for this cpu device */
+	drv_attr = cpufreq_driver->attr;
+	while ((drv_attr) && (*drv_attr)) {
+		ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
 		if (ret)
 			goto err_out_driver_exit;
-
-		/* set up files for this cpu device */
-		drv_attr = cpufreq_driver->attr;
-		while ((drv_attr) && (*drv_attr)) {
-			ret = sysfs_create_file(&policy->kobj,
-						&((*drv_attr)->attr));
-			if (ret)
-				goto err_out_driver_exit;
-			drv_attr++;
-		}
-		if (cpufreq_driver->get) {
-			ret = sysfs_create_file(&policy->kobj,
-						&cpuinfo_cur_freq.attr);
-			if (ret)
-				goto err_out_driver_exit;
-		}
-		if (cpufreq_driver->target) {
-			ret = sysfs_create_file(&policy->kobj,
-						&scaling_cur_freq.attr);
-			if (ret)
-				goto err_out_driver_exit;
-		}
-	} else {
-		ret = kobject_init_and_add(&policy->kobj, &ktype_empty_cpufreq,
-					   &sys_dev->kobj, "cpufreq");
+		drv_attr++;
+	}
+	if (cpufreq_driver->get) {
+		ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
+		if (ret)
+			goto err_out_driver_exit;
+	}
+	if (cpufreq_driver->target) {
+		ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
 		if (ret)
 			goto err_out_driver_exit;
 	}
@@ -1142,8 +1129,8 @@
  *	@old_freq: CPU frequency the kernel thinks the CPU runs at
  *	@new_freq: CPU frequency the CPU actually runs at
  *
- *	We adjust to current frequency first, and need to clean up later. So either call
- *	to cpufreq_update_policy() or schedule handle_update()).
+ *	We adjust to current frequency first, and need to clean up later.
+ *	So either call to cpufreq_update_policy() or schedule handle_update()).
  */
 static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
 				unsigned int new_freq)
@@ -1625,7 +1612,8 @@
 
 /**
  * cpufreq_get_policy - get the current cpufreq_policy
- * @policy: struct cpufreq_policy into which the current cpufreq_policy is written
+ * @policy: struct cpufreq_policy into which the current cpufreq_policy
+ *	is written
  *
  * Reads the current cpufreq policy.
  */
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 0320962..2ecd95e 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -4,7 +4,7 @@
  *  Copyright (C)  2001 Russell King
  *            (C)  2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
  *                      Jun Nakajima <jun.nakajima@intel.com>
- *            (C)  2004 Alexander Clouter <alex-kernel@digriz.org.uk>
+ *            (C)  2009 Alexander Clouter <alex@digriz.org.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
@@ -13,22 +13,17 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/smp.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ctype.h>
 #include <linux/cpufreq.h>
-#include <linux/sysctl.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/sysfs.h>
 #include <linux/cpu.h>
-#include <linux/kmod.h>
-#include <linux/workqueue.h>
 #include <linux/jiffies.h>
 #include <linux/kernel_stat.h>
-#include <linux/percpu.h>
 #include <linux/mutex.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+#include <linux/ktime.h>
+#include <linux/sched.h>
+
 /*
  * dbs is used in this file as a shortform for demandbased switching
  * It helps to keep variable names smaller, simpler
@@ -43,19 +38,31 @@
  * latency of the processor. The governor will work on any processor with
  * transition latency <= 10mS, using appropriate sampling
  * rate.
- * For CPUs with transition latency > 10mS (mostly drivers
- * with CPUFREQ_ETERNAL), this governor will not work.
+ * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
+ * this governor will not work.
  * All times here are in uS.
  */
 static unsigned int def_sampling_rate;
 #define MIN_SAMPLING_RATE_RATIO			(2)
 /* for correct statistics, we need at least 10 ticks between each measure */
-#define MIN_STAT_SAMPLING_RATE			\
+#define MIN_STAT_SAMPLING_RATE 			\
 			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
 #define MIN_SAMPLING_RATE			\
 			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
+/* Above MIN_SAMPLING_RATE will vanish with its sysfs file soon
+ * Define the minimal settable sampling rate to the greater of:
+ *   - "HW transition latency" * 100 (same as default sampling / 10)
+ *   - MIN_STAT_SAMPLING_RATE
+ * To avoid that userspace shoots itself.
+*/
+static unsigned int minimum_sampling_rate(void)
+{
+	return max(def_sampling_rate / 10, MIN_STAT_SAMPLING_RATE);
+}
+
+/* This will also vanish soon with removing sampling_rate_max */
 #define MAX_SAMPLING_RATE			(500 * def_sampling_rate)
-#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER	(1000)
+#define LATENCY_MULTIPLIER			(1000)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
 #define MAX_SAMPLING_DOWN_FACTOR		(10)
 #define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
@@ -63,12 +70,15 @@
 static void do_dbs_timer(struct work_struct *work);
 
 struct cpu_dbs_info_s {
+	cputime64_t prev_cpu_idle;
+	cputime64_t prev_cpu_wall;
+	cputime64_t prev_cpu_nice;
 	struct cpufreq_policy *cur_policy;
-	unsigned int prev_cpu_idle_up;
-	unsigned int prev_cpu_idle_down;
-	unsigned int enable;
+	struct delayed_work work;
 	unsigned int down_skip;
 	unsigned int requested_freq;
+	int cpu;
+	unsigned int enable:1;
 };
 static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
 
@@ -82,19 +92,18 @@
  * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock
  * is recursive for the same process. -Venki
  */
-static DEFINE_MUTEX (dbs_mutex);
-static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer);
+static DEFINE_MUTEX(dbs_mutex);
 
-struct dbs_tuners {
+static struct workqueue_struct	*kconservative_wq;
+
+static struct dbs_tuners {
 	unsigned int sampling_rate;
 	unsigned int sampling_down_factor;
 	unsigned int up_threshold;
 	unsigned int down_threshold;
 	unsigned int ignore_nice;
 	unsigned int freq_step;
-};
-
-static struct dbs_tuners dbs_tuners_ins = {
+} dbs_tuners_ins = {
 	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
 	.down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
 	.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
@@ -102,18 +111,37 @@
 	.freq_step = 5,
 };
 
-static inline unsigned int get_cpu_idle_time(unsigned int cpu)
+static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu,
+							cputime64_t *wall)
 {
-	unsigned int add_nice = 0, ret;
+	cputime64_t idle_time;
+	cputime64_t cur_wall_time;
+	cputime64_t busy_time;
 
-	if (dbs_tuners_ins.ignore_nice)
-		add_nice = kstat_cpu(cpu).cpustat.nice;
+	cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
+	busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user,
+			kstat_cpu(cpu).cpustat.system);
 
-	ret = kstat_cpu(cpu).cpustat.idle +
-		kstat_cpu(cpu).cpustat.iowait +
-		add_nice;
+	busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.irq);
+	busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.softirq);
+	busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.steal);
+	busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.nice);
 
-	return ret;
+	idle_time = cputime64_sub(cur_wall_time, busy_time);
+	if (wall)
+		*wall = cur_wall_time;
+
+	return idle_time;
+}
+
+static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+{
+	u64 idle_time = get_cpu_idle_time_us(cpu, wall);
+
+	if (idle_time == -1ULL)
+		return get_cpu_idle_time_jiffy(cpu, wall);
+
+	return idle_time;
 }
 
 /* keep track of frequency transitions */
@@ -125,10 +153,21 @@
 	struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info,
 							freq->cpu);
 
+	struct cpufreq_policy *policy;
+
 	if (!this_dbs_info->enable)
 		return 0;
 
-	this_dbs_info->requested_freq = freq->new;
+	policy = this_dbs_info->cur_policy;
+
+	/*
+	 * we only care if our internally tracked freq moves outside
+	 * the 'valid' ranges of freqency available to us otherwise
+	 * we do not change it
+	*/
+	if (this_dbs_info->requested_freq > policy->max
+			|| this_dbs_info->requested_freq < policy->min)
+		this_dbs_info->requested_freq = freq->new;
 
 	return 0;
 }
@@ -140,16 +179,31 @@
 /************************** sysfs interface ************************/
 static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
 {
-	return sprintf (buf, "%u\n", MAX_SAMPLING_RATE);
+	static int print_once;
+
+	if (!print_once) {
+		printk(KERN_INFO "CPUFREQ: conservative sampling_rate_max "
+		       "sysfs file is deprecated - used by: %s\n",
+		       current->comm);
+		print_once = 1;
+	}
+	return sprintf(buf, "%u\n", MAX_SAMPLING_RATE);
 }
 
 static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
 {
-	return sprintf (buf, "%u\n", MIN_SAMPLING_RATE);
+	static int print_once;
+
+	if (!print_once) {
+		printk(KERN_INFO "CPUFREQ: conservative sampling_rate_max "
+		       "sysfs file is deprecated - used by: %s\n", current->comm);
+		print_once = 1;
+	}
+	return sprintf(buf, "%u\n", MIN_SAMPLING_RATE);
 }
 
-#define define_one_ro(_name)				\
-static struct freq_attr _name =				\
+#define define_one_ro(_name)		\
+static struct freq_attr _name =		\
 __ATTR(_name, 0444, show_##_name, NULL)
 
 define_one_ro(sampling_rate_max);
@@ -174,7 +228,8 @@
 {
 	unsigned int input;
 	int ret;
-	ret = sscanf (buf, "%u", &input);
+	ret = sscanf(buf, "%u", &input);
+
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
 
@@ -190,15 +245,13 @@
 {
 	unsigned int input;
 	int ret;
-	ret = sscanf (buf, "%u", &input);
+	ret = sscanf(buf, "%u", &input);
+
+	if (ret != 1)
+		return -EINVAL;
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) {
-		mutex_unlock(&dbs_mutex);
-		return -EINVAL;
-	}
-
-	dbs_tuners_ins.sampling_rate = input;
+	dbs_tuners_ins.sampling_rate = max(input, minimum_sampling_rate());
 	mutex_unlock(&dbs_mutex);
 
 	return count;
@@ -209,10 +262,11 @@
 {
 	unsigned int input;
 	int ret;
-	ret = sscanf (buf, "%u", &input);
+	ret = sscanf(buf, "%u", &input);
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1 || input > 100 || input <= dbs_tuners_ins.down_threshold) {
+	if (ret != 1 || input > 100 ||
+			input <= dbs_tuners_ins.down_threshold) {
 		mutex_unlock(&dbs_mutex);
 		return -EINVAL;
 	}
@@ -228,10 +282,12 @@
 {
 	unsigned int input;
 	int ret;
-	ret = sscanf (buf, "%u", &input);
+	ret = sscanf(buf, "%u", &input);
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1 || input > 100 || input >= dbs_tuners_ins.up_threshold) {
+	/* cannot be lower than 11 otherwise freq will not fall */
+	if (ret != 1 || input < 11 || input > 100 ||
+			input >= dbs_tuners_ins.up_threshold) {
 		mutex_unlock(&dbs_mutex);
 		return -EINVAL;
 	}
@@ -264,12 +320,14 @@
 	}
 	dbs_tuners_ins.ignore_nice = input;
 
-	/* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */
+	/* we need to re-evaluate prev_cpu_idle */
 	for_each_online_cpu(j) {
-		struct cpu_dbs_info_s *j_dbs_info;
-		j_dbs_info = &per_cpu(cpu_dbs_info, j);
-		j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
-		j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up;
+		struct cpu_dbs_info_s *dbs_info;
+		dbs_info = &per_cpu(cpu_dbs_info, j);
+		dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
+						&dbs_info->prev_cpu_wall);
+		if (dbs_tuners_ins.ignore_nice)
+			dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice;
 	}
 	mutex_unlock(&dbs_mutex);
 
@@ -281,7 +339,6 @@
 {
 	unsigned int input;
 	int ret;
-
 	ret = sscanf(buf, "%u", &input);
 
 	if (ret != 1)
@@ -310,7 +367,7 @@
 define_one_rw(ignore_nice_load);
 define_one_rw(freq_step);
 
-static struct attribute * dbs_attributes[] = {
+static struct attribute *dbs_attributes[] = {
 	&sampling_rate_max.attr,
 	&sampling_rate_min.attr,
 	&sampling_rate.attr,
@@ -329,55 +386,78 @@
 
 /************************** sysfs end ************************/
 
-static void dbs_check_cpu(int cpu)
+static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
 {
-	unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
-	unsigned int tmp_idle_ticks, total_idle_ticks;
+	unsigned int load = 0;
 	unsigned int freq_target;
-	unsigned int freq_down_sampling_rate;
-	struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
-	struct cpufreq_policy *policy;
 
-	if (!this_dbs_info->enable)
-		return;
+	struct cpufreq_policy *policy;
+	unsigned int j;
 
 	policy = this_dbs_info->cur_policy;
 
 	/*
-	 * The default safe range is 20% to 80%
-	 * Every sampling_rate, we check
-	 *	- If current idle time is less than 20%, then we try to
-	 *	  increase frequency
-	 * Every sampling_rate*sampling_down_factor, we check
-	 *	- If current idle time is more than 80%, then we try to
-	 *	  decrease frequency
+	 * Every sampling_rate, we check, if current idle time is less
+	 * than 20% (default), then we try to increase frequency
+	 * Every sampling_rate*sampling_down_factor, we check, if current
+	 * idle time is more than 80%, then we try to decrease frequency
 	 *
 	 * Any frequency increase takes it to the maximum frequency.
 	 * Frequency reduction happens at minimum steps of
-	 * 5% (default) of max_frequency
+	 * 5% (default) of maximum frequency
 	 */
 
-	/* Check for frequency increase */
-	idle_ticks = UINT_MAX;
+	/* Get Absolute Load */
+	for_each_cpu(j, policy->cpus) {
+		struct cpu_dbs_info_s *j_dbs_info;
+		cputime64_t cur_wall_time, cur_idle_time;
+		unsigned int idle_time, wall_time;
+
+		j_dbs_info = &per_cpu(cpu_dbs_info, j);
+
+		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
+
+		wall_time = (unsigned int) cputime64_sub(cur_wall_time,
+				j_dbs_info->prev_cpu_wall);
+		j_dbs_info->prev_cpu_wall = cur_wall_time;
+
+		idle_time = (unsigned int) cputime64_sub(cur_idle_time,
+				j_dbs_info->prev_cpu_idle);
+		j_dbs_info->prev_cpu_idle = cur_idle_time;
+
+		if (dbs_tuners_ins.ignore_nice) {
+			cputime64_t cur_nice;
+			unsigned long cur_nice_jiffies;
+
+			cur_nice = cputime64_sub(kstat_cpu(j).cpustat.nice,
+					 j_dbs_info->prev_cpu_nice);
+			/*
+			 * Assumption: nice time between sampling periods will
+			 * be less than 2^32 jiffies for 32 bit sys
+			 */
+			cur_nice_jiffies = (unsigned long)
+					cputime64_to_jiffies64(cur_nice);
+
+			j_dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice;
+			idle_time += jiffies_to_usecs(cur_nice_jiffies);
+		}
+
+		if (unlikely(!wall_time || wall_time < idle_time))
+			continue;
+
+		load = 100 * (wall_time - idle_time) / wall_time;
+	}
+
+	/*
+	 * break out if we 'cannot' reduce the speed as the user might
+	 * want freq_step to be zero
+	 */
+	if (dbs_tuners_ins.freq_step == 0)
+		return;
 
 	/* Check for frequency increase */
-	total_idle_ticks = get_cpu_idle_time(cpu);
-	tmp_idle_ticks = total_idle_ticks -
-		this_dbs_info->prev_cpu_idle_up;
-	this_dbs_info->prev_cpu_idle_up = total_idle_ticks;
-
-	if (tmp_idle_ticks < idle_ticks)
-		idle_ticks = tmp_idle_ticks;
-
-	/* Scale idle ticks by 100 and compare with up and down ticks */
-	idle_ticks *= 100;
-	up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
-			usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
-	if (idle_ticks < up_idle_ticks) {
+	if (load > dbs_tuners_ins.up_threshold) {
 		this_dbs_info->down_skip = 0;
-		this_dbs_info->prev_cpu_idle_down =
-			this_dbs_info->prev_cpu_idle_up;
 
 		/* if we are already at full speed then break out early */
 		if (this_dbs_info->requested_freq == policy->max)
@@ -398,49 +478,24 @@
 		return;
 	}
 
-	/* Check for frequency decrease */
-	this_dbs_info->down_skip++;
-	if (this_dbs_info->down_skip < dbs_tuners_ins.sampling_down_factor)
-		return;
-
-	/* Check for frequency decrease */
-	total_idle_ticks = this_dbs_info->prev_cpu_idle_up;
-	tmp_idle_ticks = total_idle_ticks -
-		this_dbs_info->prev_cpu_idle_down;
-	this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
-
-	if (tmp_idle_ticks < idle_ticks)
-		idle_ticks = tmp_idle_ticks;
-
-	/* Scale idle ticks by 100 and compare with up and down ticks */
-	idle_ticks *= 100;
-	this_dbs_info->down_skip = 0;
-
-	freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
-		dbs_tuners_ins.sampling_down_factor;
-	down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) *
-		usecs_to_jiffies(freq_down_sampling_rate);
-
-	if (idle_ticks > down_idle_ticks) {
-		/*
-		 * if we are already at the lowest speed then break out early
-		 * or if we 'cannot' reduce the speed as the user might want
-		 * freq_target to be zero
-		 */
-		if (this_dbs_info->requested_freq == policy->min
-				|| dbs_tuners_ins.freq_step == 0)
-			return;
-
+	/*
+	 * The optimal frequency is the frequency that is the lowest that
+	 * can support the current CPU usage without triggering the up
+	 * policy. To be safe, we focus 10 points under the threshold.
+	 */
+	if (load < (dbs_tuners_ins.down_threshold - 10)) {
 		freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100;
 
-		/* max freq cannot be less than 100. But who knows.... */
-		if (unlikely(freq_target == 0))
-			freq_target = 5;
-
 		this_dbs_info->requested_freq -= freq_target;
 		if (this_dbs_info->requested_freq < policy->min)
 			this_dbs_info->requested_freq = policy->min;
 
+		/*
+		 * if we cannot reduce the frequency anymore, break out early
+		 */
+		if (policy->cur == policy->min)
+			return;
+
 		__cpufreq_driver_target(policy, this_dbs_info->requested_freq,
 				CPUFREQ_RELATION_H);
 		return;
@@ -449,27 +504,45 @@
 
 static void do_dbs_timer(struct work_struct *work)
 {
-	int i;
-	mutex_lock(&dbs_mutex);
-	for_each_online_cpu(i)
-		dbs_check_cpu(i);
-	schedule_delayed_work(&dbs_work,
-			usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
-	mutex_unlock(&dbs_mutex);
+	struct cpu_dbs_info_s *dbs_info =
+		container_of(work, struct cpu_dbs_info_s, work.work);
+	unsigned int cpu = dbs_info->cpu;
+
+	/* We want all CPUs to do sampling nearly on same jiffy */
+	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+
+	delay -= jiffies % delay;
+
+	if (lock_policy_rwsem_write(cpu) < 0)
+		return;
+
+	if (!dbs_info->enable) {
+		unlock_policy_rwsem_write(cpu);
+		return;
+	}
+
+	dbs_check_cpu(dbs_info);
+
+	queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay);
+	unlock_policy_rwsem_write(cpu);
 }
 
-static inline void dbs_timer_init(void)
+static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
 {
-	init_timer_deferrable(&dbs_work.timer);
-	schedule_delayed_work(&dbs_work,
-			usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
-	return;
+	/* We want all CPUs to do sampling nearly on same jiffy */
+	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+	delay -= jiffies % delay;
+
+	dbs_info->enable = 1;
+	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
+	queue_delayed_work_on(dbs_info->cpu, kconservative_wq, &dbs_info->work,
+				delay);
 }
 
-static inline void dbs_timer_exit(void)
+static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
 {
-	cancel_delayed_work(&dbs_work);
-	return;
+	dbs_info->enable = 0;
+	cancel_delayed_work(&dbs_info->work);
 }
 
 static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
@@ -503,11 +576,13 @@
 			j_dbs_info = &per_cpu(cpu_dbs_info, j);
 			j_dbs_info->cur_policy = policy;
 
-			j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(cpu);
-			j_dbs_info->prev_cpu_idle_down
-				= j_dbs_info->prev_cpu_idle_up;
+			j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
+						&j_dbs_info->prev_cpu_wall);
+			if (dbs_tuners_ins.ignore_nice) {
+				j_dbs_info->prev_cpu_nice =
+						kstat_cpu(j).cpustat.nice;
+			}
 		}
-		this_dbs_info->enable = 1;
 		this_dbs_info->down_skip = 0;
 		this_dbs_info->requested_freq = policy->cur;
 
@@ -523,38 +598,36 @@
 			if (latency == 0)
 				latency = 1;
 
-			def_sampling_rate = 10 * latency *
-					DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
-
-			if (def_sampling_rate < MIN_STAT_SAMPLING_RATE)
-				def_sampling_rate = MIN_STAT_SAMPLING_RATE;
+			def_sampling_rate =
+				max(latency * LATENCY_MULTIPLIER,
+				    MIN_STAT_SAMPLING_RATE);
 
 			dbs_tuners_ins.sampling_rate = def_sampling_rate;
 
-			dbs_timer_init();
 			cpufreq_register_notifier(
 					&dbs_cpufreq_notifier_block,
 					CPUFREQ_TRANSITION_NOTIFIER);
 		}
+		dbs_timer_init(this_dbs_info);
 
 		mutex_unlock(&dbs_mutex);
+
 		break;
 
 	case CPUFREQ_GOV_STOP:
 		mutex_lock(&dbs_mutex);
-		this_dbs_info->enable = 0;
+		dbs_timer_exit(this_dbs_info);
 		sysfs_remove_group(&policy->kobj, &dbs_attr_group);
 		dbs_enable--;
+
 		/*
 		 * Stop the timerschedule work, when this governor
 		 * is used for first time
 		 */
-		if (dbs_enable == 0) {
-			dbs_timer_exit();
+		if (dbs_enable == 0)
 			cpufreq_unregister_notifier(
 					&dbs_cpufreq_notifier_block,
 					CPUFREQ_TRANSITION_NOTIFIER);
-		}
 
 		mutex_unlock(&dbs_mutex);
 
@@ -571,6 +644,7 @@
 					this_dbs_info->cur_policy,
 					policy->min, CPUFREQ_RELATION_L);
 		mutex_unlock(&dbs_mutex);
+
 		break;
 	}
 	return 0;
@@ -588,23 +662,33 @@
 
 static int __init cpufreq_gov_dbs_init(void)
 {
-	return cpufreq_register_governor(&cpufreq_gov_conservative);
+	int err;
+
+	kconservative_wq = create_workqueue("kconservative");
+	if (!kconservative_wq) {
+		printk(KERN_ERR "Creation of kconservative failed\n");
+		return -EFAULT;
+	}
+
+	err = cpufreq_register_governor(&cpufreq_gov_conservative);
+	if (err)
+		destroy_workqueue(kconservative_wq);
+
+	return err;
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
-	/* Make sure that the scheduled work is indeed not running */
-	flush_scheduled_work();
-
 	cpufreq_unregister_governor(&cpufreq_gov_conservative);
+	destroy_workqueue(kconservative_wq);
 }
 
 
-MODULE_AUTHOR ("Alexander Clouter <alex-kernel@digriz.org.uk>");
-MODULE_DESCRIPTION ("'cpufreq_conservative' - A dynamic cpufreq governor for "
+MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
+MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
 		"Low Latency Frequency Transition capable processors "
 		"optimised for use in a battery environment");
-MODULE_LICENSE ("GPL");
+MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
 fs_initcall(cpufreq_gov_dbs_init);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 6f45b16..338f428 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -21,6 +21,7 @@
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
 #include <linux/ktime.h>
+#include <linux/sched.h>
 
 /*
  * dbs is used in this file as a shortform for demandbased switching
@@ -51,8 +52,20 @@
 			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
 #define MIN_SAMPLING_RATE			\
 			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
+/* Above MIN_SAMPLING_RATE will vanish with its sysfs file soon
+ * Define the minimal settable sampling rate to the greater of:
+ *   - "HW transition latency" * 100 (same as default sampling / 10)
+ *   - MIN_STAT_SAMPLING_RATE
+ * To avoid that userspace shoots itself.
+*/
+static unsigned int minimum_sampling_rate(void)
+{
+	return max(def_sampling_rate / 10, MIN_STAT_SAMPLING_RATE);
+}
+
+/* This will also vanish soon with removing sampling_rate_max */
 #define MAX_SAMPLING_RATE			(500 * def_sampling_rate)
-#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER	(1000)
+#define LATENCY_MULTIPLIER			(1000)
 #define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
 
 static void do_dbs_timer(struct work_struct *work);
@@ -65,14 +78,14 @@
 	cputime64_t prev_cpu_wall;
 	cputime64_t prev_cpu_nice;
 	struct cpufreq_policy *cur_policy;
- 	struct delayed_work work;
+	struct delayed_work work;
 	struct cpufreq_frequency_table *freq_table;
 	unsigned int freq_lo;
 	unsigned int freq_lo_jiffies;
 	unsigned int freq_hi_jiffies;
 	int cpu;
 	unsigned int enable:1,
-	             sample_type:1;
+		sample_type:1;
 };
 static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
 
@@ -203,12 +216,28 @@
 /************************** sysfs interface ************************/
 static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
 {
-	return sprintf (buf, "%u\n", MAX_SAMPLING_RATE);
+	static int print_once;
+
+	if (!print_once) {
+		printk(KERN_INFO "CPUFREQ: ondemand sampling_rate_max "
+		       "sysfs file is deprecated - used by: %s\n",
+		       current->comm);
+		print_once = 1;
+	}
+	return sprintf(buf, "%u\n", MAX_SAMPLING_RATE);
 }
 
 static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
 {
-	return sprintf (buf, "%u\n", MIN_SAMPLING_RATE);
+	static int print_once;
+
+	if (!print_once) {
+		printk(KERN_INFO "CPUFREQ: ondemand sampling_rate_min "
+		       "sysfs file is deprecated - used by: %s\n",
+		       current->comm);
+		print_once = 1;
+	}
+	return sprintf(buf, "%u\n", MIN_SAMPLING_RATE);
 }
 
 #define define_one_ro(_name)		\
@@ -238,13 +267,11 @@
 	ret = sscanf(buf, "%u", &input);
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1 || input > MAX_SAMPLING_RATE
-		     || input < MIN_SAMPLING_RATE) {
+	if (ret != 1) {
 		mutex_unlock(&dbs_mutex);
 		return -EINVAL;
 	}
-
-	dbs_tuners_ins.sampling_rate = input;
+	dbs_tuners_ins.sampling_rate = max(input, minimum_sampling_rate());
 	mutex_unlock(&dbs_mutex);
 
 	return count;
@@ -279,14 +306,14 @@
 	unsigned int j;
 
 	ret = sscanf(buf, "%u", &input);
-	if ( ret != 1 )
+	if (ret != 1)
 		return -EINVAL;
 
-	if ( input > 1 )
+	if (input > 1)
 		input = 1;
 
 	mutex_lock(&dbs_mutex);
-	if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */
+	if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
 		mutex_unlock(&dbs_mutex);
 		return count;
 	}
@@ -337,7 +364,7 @@
 define_one_rw(ignore_nice_load);
 define_one_rw(powersave_bias);
 
-static struct attribute * dbs_attributes[] = {
+static struct attribute *dbs_attributes[] = {
 	&sampling_rate_max.attr,
 	&sampling_rate_min.attr,
 	&sampling_rate.attr,
@@ -512,8 +539,7 @@
 		}
 	} else {
 		__cpufreq_driver_target(dbs_info->cur_policy,
-	                        	dbs_info->freq_lo,
-	                        	CPUFREQ_RELATION_H);
+			dbs_info->freq_lo, CPUFREQ_RELATION_H);
 	}
 	queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
 	unlock_policy_rwsem_write(cpu);
@@ -530,7 +556,7 @@
 	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
 	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
 	queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work,
-	                      delay);
+		delay);
 }
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
@@ -591,11 +617,9 @@
 			if (latency == 0)
 				latency = 1;
 
-			def_sampling_rate = latency *
-					DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
-
-			if (def_sampling_rate < MIN_STAT_SAMPLING_RATE)
-				def_sampling_rate = MIN_STAT_SAMPLING_RATE;
+			def_sampling_rate =
+				max(latency * LATENCY_MULTIPLIER,
+				    MIN_STAT_SAMPLING_RATE);
 
 			dbs_tuners_ins.sampling_rate = def_sampling_rate;
 		}
@@ -617,12 +641,10 @@
 		mutex_lock(&dbs_mutex);
 		if (policy->max < this_dbs_info->cur_policy->cur)
 			__cpufreq_driver_target(this_dbs_info->cur_policy,
-			                        policy->max,
-			                        CPUFREQ_RELATION_H);
+				policy->max, CPUFREQ_RELATION_H);
 		else if (policy->min > this_dbs_info->cur_policy->cur)
 			__cpufreq_driver_target(this_dbs_info->cur_policy,
-			                        policy->min,
-			                        CPUFREQ_RELATION_L);
+				policy->min, CPUFREQ_RELATION_L);
 		mutex_unlock(&dbs_mutex);
 		break;
 	}
@@ -677,7 +699,7 @@
 MODULE_AUTHOR("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>");
 MODULE_AUTHOR("Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>");
 MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for "
-                   "Low Latency Frequency Transition capable processors");
+	"Low Latency Frequency Transition capable processors");
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index c0ff97d..5a62d67 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -2,7 +2,7 @@
  *  drivers/cpufreq/cpufreq_stats.c
  *
  *  Copyright (C) 2003-2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
- *	      (C) 2004 Zou Nan hai <nanhai.zou@intel.com>.
+ *  (C) 2004 Zou Nan hai <nanhai.zou@intel.com>.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -23,7 +23,7 @@
 
 static spinlock_t cpufreq_stats_lock;
 
-#define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \
+#define CPUFREQ_STATDEVICE_ATTR(_name, _mode, _show) \
 static struct freq_attr _attr_##_name = {\
 	.attr = {.name = __stringify(_name), .mode = _mode, }, \
 	.show = _show,\
@@ -50,8 +50,7 @@
 	ssize_t(*show) (struct cpufreq_stats *, char *);
 };
 
-static int
-cpufreq_stats_update (unsigned int cpu)
+static int cpufreq_stats_update(unsigned int cpu)
 {
 	struct cpufreq_stats *stat;
 	unsigned long long cur_time;
@@ -68,8 +67,7 @@
 	return 0;
 }
 
-static ssize_t
-show_total_trans(struct cpufreq_policy *policy, char *buf)
+static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf)
 {
 	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
 	if (!stat)
@@ -78,8 +76,7 @@
 			per_cpu(cpufreq_stats_table, stat->cpu)->total_trans);
 }
 
-static ssize_t
-show_time_in_state(struct cpufreq_policy *policy, char *buf)
+static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
 {
 	ssize_t len = 0;
 	int i;
@@ -89,14 +86,14 @@
 	cpufreq_stats_update(stat->cpu);
 	for (i = 0; i < stat->state_num; i++) {
 		len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i],
-			(unsigned long long)cputime64_to_clock_t(stat->time_in_state[i]));
+			(unsigned long long)
+			cputime64_to_clock_t(stat->time_in_state[i]));
 	}
 	return len;
 }
 
 #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
-static ssize_t
-show_trans_table(struct cpufreq_policy *policy, char *buf)
+static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
 {
 	ssize_t len = 0;
 	int i, j;
@@ -139,11 +136,11 @@
 		return PAGE_SIZE;
 	return len;
 }
-CPUFREQ_STATDEVICE_ATTR(trans_table,0444,show_trans_table);
+CPUFREQ_STATDEVICE_ATTR(trans_table, 0444, show_trans_table);
 #endif
 
-CPUFREQ_STATDEVICE_ATTR(total_trans,0444,show_total_trans);
-CPUFREQ_STATDEVICE_ATTR(time_in_state,0444,show_time_in_state);
+CPUFREQ_STATDEVICE_ATTR(total_trans, 0444, show_total_trans);
+CPUFREQ_STATDEVICE_ATTR(time_in_state, 0444, show_time_in_state);
 
 static struct attribute *default_attrs[] = {
 	&_attr_total_trans.attr,
@@ -158,8 +155,7 @@
 	.name = "stats"
 };
 
-static int
-freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
+static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
 {
 	int index;
 	for (index = 0; index < stat->max_state; index++)
@@ -183,8 +179,7 @@
 		cpufreq_cpu_put(policy);
 }
 
-static int
-cpufreq_stats_create_table (struct cpufreq_policy *policy,
+static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
 		struct cpufreq_frequency_table *table)
 {
 	unsigned int i, j, count = 0, ret = 0;
@@ -194,7 +189,8 @@
 	unsigned int cpu = policy->cpu;
 	if (per_cpu(cpufreq_stats_table, cpu))
 		return -EBUSY;
-	if ((stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL)
+	stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL);
+	if ((stat) == NULL)
 		return -ENOMEM;
 
 	data = cpufreq_cpu_get(cpu);
@@ -203,13 +199,14 @@
 		goto error_get_fail;
 	}
 
-	if ((ret = sysfs_create_group(&data->kobj, &stats_attr_group)))
+	ret = sysfs_create_group(&data->kobj, &stats_attr_group);
+	if (ret)
 		goto error_out;
 
 	stat->cpu = cpu;
 	per_cpu(cpufreq_stats_table, cpu) = stat;
 
-	for (i=0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
+	for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
 		unsigned int freq = table[i].frequency;
 		if (freq == CPUFREQ_ENTRY_INVALID)
 			continue;
@@ -255,9 +252,8 @@
 	return ret;
 }
 
-static int
-cpufreq_stat_notifier_policy (struct notifier_block *nb, unsigned long val,
-		void *data)
+static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
+		unsigned long val, void *data)
 {
 	int ret;
 	struct cpufreq_policy *policy = data;
@@ -268,14 +264,14 @@
 	table = cpufreq_frequency_get_table(cpu);
 	if (!table)
 		return 0;
-	if ((ret = cpufreq_stats_create_table(policy, table)))
+	ret = cpufreq_stats_create_table(policy, table);
+	if (ret)
 		return ret;
 	return 0;
 }
 
-static int
-cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val,
-		void *data)
+static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
+		unsigned long val, void *data)
 {
 	struct cpufreq_freqs *freq = data;
 	struct cpufreq_stats *stat;
@@ -340,19 +336,20 @@
 	.notifier_call = cpufreq_stat_notifier_trans
 };
 
-static int
-__init cpufreq_stats_init(void)
+static int __init cpufreq_stats_init(void)
 {
 	int ret;
 	unsigned int cpu;
 
 	spin_lock_init(&cpufreq_stats_lock);
-	if ((ret = cpufreq_register_notifier(&notifier_policy_block,
-				CPUFREQ_POLICY_NOTIFIER)))
+	ret = cpufreq_register_notifier(&notifier_policy_block,
+				CPUFREQ_POLICY_NOTIFIER);
+	if (ret)
 		return ret;
 
-	if ((ret = cpufreq_register_notifier(&notifier_trans_block,
-				CPUFREQ_TRANSITION_NOTIFIER))) {
+	ret = cpufreq_register_notifier(&notifier_trans_block,
+				CPUFREQ_TRANSITION_NOTIFIER);
+	if (ret) {
 		cpufreq_unregister_notifier(&notifier_policy_block,
 				CPUFREQ_POLICY_NOTIFIER);
 		return ret;
@@ -364,8 +361,7 @@
 	}
 	return 0;
 }
-static void
-__exit cpufreq_stats_exit(void)
+static void __exit cpufreq_stats_exit(void)
 {
 	unsigned int cpu;
 
@@ -379,10 +375,10 @@
 	}
 }
 
-MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>");
-MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats "
+MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");
+MODULE_DESCRIPTION("'cpufreq_stats' - A driver to export cpufreq stats "
 				"through sysfs filesystem");
-MODULE_LICENSE ("GPL");
+MODULE_LICENSE("GPL");
 
 module_init(cpufreq_stats_init);
 module_exit(cpufreq_stats_exit);
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 1442bba..66d2d1d 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -24,9 +24,6 @@
 #include <linux/sysfs.h>
 #include <linux/mutex.h>
 
-#include <asm/uaccess.h>
-
-
 /**
  * A few values needed by the userspace governor
  */
@@ -37,7 +34,7 @@
 							userspace */
 static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
 
-static DEFINE_MUTEX	(userspace_mutex);
+static DEFINE_MUTEX(userspace_mutex);
 static int cpus_using_userspace_governor;
 
 #define dprintk(msg...) \
@@ -46,9 +43,9 @@
 /* keep track of frequency transitions */
 static int
 userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-                       void *data)
+	void *data)
 {
-        struct cpufreq_freqs *freq = data;
+	struct cpufreq_freqs *freq = data;
 
 	if (!per_cpu(cpu_is_managed, freq->cpu))
 		return 0;
@@ -57,11 +54,11 @@
 			freq->cpu, freq->new);
 	per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
 
-        return 0;
+	return 0;
 }
 
 static struct notifier_block userspace_cpufreq_notifier_block = {
-        .notifier_call  = userspace_cpufreq_notifier
+	.notifier_call  = userspace_cpufreq_notifier
 };
 
 
@@ -93,8 +90,11 @@
 	 * We're safe from concurrent calls to ->target() here
 	 * as we hold the userspace_mutex lock. If we were calling
 	 * cpufreq_driver_target, a deadlock situation might occur:
-	 * A: cpufreq_set (lock userspace_mutex) -> cpufreq_driver_target(lock policy->lock)
-	 * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_mutex)
+	 * A: cpufreq_set (lock userspace_mutex) ->
+	 *      cpufreq_driver_target(lock policy->lock)
+	 * B: cpufreq_set_policy(lock policy->lock) ->
+	 *      __cpufreq_governor ->
+	 *         cpufreq_governor_userspace (lock userspace_mutex)
 	 */
 	ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
 
@@ -210,9 +210,10 @@
 }
 
 
-MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>, Russell King <rmk@arm.linux.org.uk>");
-MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, "
+		"Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'");
+MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
 fs_initcall(cpufreq_gov_userspace_init);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 9071d80..a9bd3a0 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -28,7 +28,7 @@
 	unsigned int max_freq = 0;
 	unsigned int i;
 
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		unsigned int freq = table[i].frequency;
 		if (freq == CPUFREQ_ENTRY_INVALID) {
 			dprintk("table entry %u is invalid, skipping\n", i);
@@ -70,7 +70,7 @@
 	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
 				     policy->cpuinfo.max_freq);
 
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		unsigned int freq = table[i].frequency;
 		if (freq == CPUFREQ_ENTRY_INVALID)
 			continue;
@@ -125,13 +125,13 @@
 	if (!cpu_online(policy->cpu))
 		return -EINVAL;
 
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		unsigned int freq = table[i].frequency;
 		if (freq == CPUFREQ_ENTRY_INVALID)
 			continue;
 		if ((freq < policy->min) || (freq > policy->max))
 			continue;
-		switch(relation) {
+		switch (relation) {
 		case CPUFREQ_RELATION_H:
 			if (freq <= target_freq) {
 				if (freq >= optimal.frequency) {
@@ -178,7 +178,7 @@
 /**
  * show_available_freqs - show available frequencies for the specified CPU
  */
-static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
+static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
 {
 	unsigned int i = 0;
 	unsigned int cpu = policy->cpu;
@@ -190,7 +190,7 @@
 
 	table = per_cpu(show_table, cpu);
 
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
 			continue;
 		count += sprintf(&buf[count], "%d ", table[i].frequency);
@@ -234,6 +234,6 @@
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
 
-MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
-MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION("CPUfreq frequency table helpers");
+MODULE_LICENSE("GPL");
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index e522144..01afd75 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -86,7 +86,7 @@
 config CRYPTO_SHA1_S390
 	tristate "SHA1 digest algorithm"
 	depends on S390
-	select CRYPTO_ALGAPI
+	select CRYPTO_HASH
 	help
 	  This is the s390 hardware accelerated implementation of the
 	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
@@ -94,7 +94,7 @@
 config CRYPTO_SHA256_S390
 	tristate "SHA256 digest algorithm"
 	depends on S390
-	select CRYPTO_ALGAPI
+	select CRYPTO_HASH
 	help
 	  This is the s390 hardware accelerated implementation of the
 	  SHA256 secure hash standard (DFIPS 180-2).
@@ -105,7 +105,7 @@
 config CRYPTO_SHA512_S390
 	tristate "SHA384 and SHA512 digest algorithm"
 	depends on S390
-	select CRYPTO_ALGAPI
+	select CRYPTO_HASH
 	help
 	  This is the s390 hardware accelerated implementation of the
 	  SHA512 secure hash standard.
@@ -200,4 +200,13 @@
 	help
 	  Driver for the IXP4xx NPE crypto engine.
 
+config CRYPTO_DEV_PPC4XX
+	tristate "Driver AMCC PPC4xx crypto accelerator"
+	depends on PPC && 4xx
+	select CRYPTO_HASH
+	select CRYPTO_ALGAPI
+	select CRYPTO_BLKCIPHER
+	help
+	  This option allows you to have support for AMCC crypto acceleration.
+
 endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 73557b2..9bf4a2b 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -4,3 +4,4 @@
 obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
 obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
 obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o
+obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
diff --git a/drivers/crypto/amcc/Makefile b/drivers/crypto/amcc/Makefile
new file mode 100644
index 0000000..aa376e8
--- /dev/null
+++ b/drivers/crypto/amcc/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += crypto4xx.o
+crypto4xx-objs :=  crypto4xx_core.o crypto4xx_alg.o crypto4xx_sa.o
diff --git a/drivers/crypto/amcc/crypto4xx_alg.c b/drivers/crypto/amcc/crypto4xx_alg.c
new file mode 100644
index 0000000..61b6e1b
--- /dev/null
+++ b/drivers/crypto/amcc/crypto4xx_alg.c
@@ -0,0 +1,293 @@
+/**
+ * AMCC SoC PPC4xx Crypto Driver
+ *
+ * Copyright (c) 2008 Applied Micro Circuits Corporation.
+ * All rights reserved. James Hsiao <jhsiao@amcc.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.
+ *
+ * This file implements the Linux crypto algorithms.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock_types.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <linux/hash.h>
+#include <crypto/internal/hash.h>
+#include <linux/dma-mapping.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/sha.h>
+#include "crypto4xx_reg_def.h"
+#include "crypto4xx_sa.h"
+#include "crypto4xx_core.h"
+
+void set_dynamic_sa_command_0(struct dynamic_sa_ctl *sa, u32 save_h,
+			      u32 save_iv, u32 ld_h, u32 ld_iv, u32 hdr_proc,
+			      u32 h, u32 c, u32 pad_type, u32 op_grp, u32 op,
+			      u32 dir)
+{
+	sa->sa_command_0.w = 0;
+	sa->sa_command_0.bf.save_hash_state = save_h;
+	sa->sa_command_0.bf.save_iv = save_iv;
+	sa->sa_command_0.bf.load_hash_state = ld_h;
+	sa->sa_command_0.bf.load_iv = ld_iv;
+	sa->sa_command_0.bf.hdr_proc = hdr_proc;
+	sa->sa_command_0.bf.hash_alg = h;
+	sa->sa_command_0.bf.cipher_alg = c;
+	sa->sa_command_0.bf.pad_type = pad_type & 3;
+	sa->sa_command_0.bf.extend_pad = pad_type >> 2;
+	sa->sa_command_0.bf.op_group = op_grp;
+	sa->sa_command_0.bf.opcode = op;
+	sa->sa_command_0.bf.dir = dir;
+}
+
+void set_dynamic_sa_command_1(struct dynamic_sa_ctl *sa, u32 cm, u32 hmac_mc,
+			      u32 cfb, u32 esn, u32 sn_mask, u32 mute,
+			      u32 cp_pad, u32 cp_pay, u32 cp_hdr)
+{
+	sa->sa_command_1.w = 0;
+	sa->sa_command_1.bf.crypto_mode31 = (cm & 4) >> 2;
+	sa->sa_command_1.bf.crypto_mode9_8 = cm & 3;
+	sa->sa_command_1.bf.feedback_mode = cfb,
+	sa->sa_command_1.bf.sa_rev = 1;
+	sa->sa_command_1.bf.extended_seq_num = esn;
+	sa->sa_command_1.bf.seq_num_mask = sn_mask;
+	sa->sa_command_1.bf.mutable_bit_proc = mute;
+	sa->sa_command_1.bf.copy_pad = cp_pad;
+	sa->sa_command_1.bf.copy_payload = cp_pay;
+	sa->sa_command_1.bf.copy_hdr = cp_hdr;
+}
+
+int crypto4xx_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+
+	ctx->direction = DIR_OUTBOUND;
+	ctx->hash_final = 0;
+	ctx->is_hash = 0;
+	ctx->pd_ctl = 0x1;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->nbytes, req->info,
+				  get_dynamic_sa_iv_size(ctx));
+}
+
+int crypto4xx_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+
+	ctx->direction = DIR_INBOUND;
+	ctx->hash_final = 0;
+	ctx->is_hash = 0;
+	ctx->pd_ctl = 1;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->nbytes, req->info,
+				  get_dynamic_sa_iv_size(ctx));
+}
+
+/**
+ * AES Functions
+ */
+static int crypto4xx_setkey_aes(struct crypto_ablkcipher *cipher,
+				const u8 *key,
+				unsigned int keylen,
+				unsigned char cm,
+				u8 fb)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct dynamic_sa_ctl *sa;
+	int    rc;
+
+	if (keylen != AES_KEYSIZE_256 &&
+		keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_128) {
+		crypto_ablkcipher_set_flags(cipher,
+				CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	/* Create SA */
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		crypto4xx_free_sa(ctx);
+
+	rc = crypto4xx_alloc_sa(ctx, SA_AES128_LEN + (keylen-16) / 4);
+	if (rc)
+		return rc;
+
+	if (ctx->state_record_dma_addr == 0) {
+		rc = crypto4xx_alloc_state_record(ctx);
+		if (rc) {
+			crypto4xx_free_sa(ctx);
+			return rc;
+		}
+	}
+	/* Setup SA */
+	sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+	ctx->hash_final = 0;
+
+	set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+				 SA_NO_HEADER_PROC, SA_HASH_ALG_NULL,
+				 SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO,
+				 SA_OP_GROUP_BASIC, SA_OPCODE_DECRYPT,
+				 DIR_INBOUND);
+
+	set_dynamic_sa_command_1(sa, cm, SA_HASH_MODE_HASH,
+				 fb, SA_EXTENDED_SN_OFF,
+				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+				 SA_NOT_COPY_HDR);
+	crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx),
+			    key, keylen);
+	sa->sa_contents = SA_AES_CONTENTS | (keylen << 2);
+	sa->sa_command_1.bf.key_len = keylen >> 3;
+	ctx->is_hash = 0;
+	ctx->direction = DIR_INBOUND;
+	memcpy(ctx->sa_in + get_dynamic_sa_offset_state_ptr_field(ctx),
+			(void *)&ctx->state_record_dma_addr, 4);
+	ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(ctx);
+
+	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+	sa = (struct dynamic_sa_ctl *) ctx->sa_out;
+	sa->sa_command_0.bf.dir = DIR_OUTBOUND;
+
+	return 0;
+}
+
+int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
+			     const u8 *key, unsigned int keylen)
+{
+	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_CBC,
+				    CRYPTO_FEEDBACK_MODE_NO_FB);
+}
+
+/**
+ * HASH SHA1 Functions
+ */
+static int crypto4xx_hash_alg_init(struct crypto_tfm *tfm,
+				   unsigned int sa_len,
+				   unsigned char ha,
+				   unsigned char hm)
+{
+	struct crypto_alg *alg = tfm->__crt_alg;
+	struct crypto4xx_alg *my_alg = crypto_alg_to_crypto4xx_alg(alg);
+	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct dynamic_sa_ctl *sa;
+	struct dynamic_sa_hash160 *sa_in;
+	int rc;
+
+	ctx->dev   = my_alg->dev;
+	ctx->is_hash = 1;
+	ctx->hash_final = 0;
+
+	/* Create SA */
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		crypto4xx_free_sa(ctx);
+
+	rc = crypto4xx_alloc_sa(ctx, sa_len);
+	if (rc)
+		return rc;
+
+	if (ctx->state_record_dma_addr == 0) {
+		crypto4xx_alloc_state_record(ctx);
+		if (!ctx->state_record_dma_addr) {
+			crypto4xx_free_sa(ctx);
+			return -ENOMEM;
+		}
+	}
+
+	tfm->crt_ahash.reqsize = sizeof(struct crypto4xx_ctx);
+	sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA,
+				 SA_NO_HEADER_PROC, ha, SA_CIPHER_ALG_NULL,
+				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
+				 SA_OPCODE_HASH, DIR_INBOUND);
+	set_dynamic_sa_command_1(sa, 0, SA_HASH_MODE_HASH,
+				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
+				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+				 SA_NOT_COPY_HDR);
+	ctx->direction = DIR_INBOUND;
+	sa->sa_contents = SA_HASH160_CONTENTS;
+	sa_in = (struct dynamic_sa_hash160 *) ctx->sa_in;
+	/* Need to zero hash digest in SA */
+	memset(sa_in->inner_digest, 0, sizeof(sa_in->inner_digest));
+	memset(sa_in->outer_digest, 0, sizeof(sa_in->outer_digest));
+	sa_in->state_ptr = ctx->state_record_dma_addr;
+	ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(ctx);
+
+	return 0;
+}
+
+int crypto4xx_hash_init(struct ahash_request *req)
+{
+	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+	int ds;
+	struct dynamic_sa_ctl *sa;
+
+	sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+	ds = crypto_ahash_digestsize(
+			__crypto_ahash_cast(req->base.tfm));
+	sa->sa_command_0.bf.digest_len = ds >> 2;
+	sa->sa_command_0.bf.load_hash_state = SA_LOAD_HASH_FROM_SA;
+	ctx->is_hash = 1;
+	ctx->direction = DIR_INBOUND;
+
+	return 0;
+}
+
+int crypto4xx_hash_update(struct ahash_request *req)
+{
+	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+
+	ctx->is_hash = 1;
+	ctx->hash_final = 0;
+	ctx->pd_ctl = 0x11;
+	ctx->direction = DIR_INBOUND;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src,
+				  (struct scatterlist *) req->result,
+				  req->nbytes, NULL, 0);
+}
+
+int crypto4xx_hash_final(struct ahash_request *req)
+{
+	return 0;
+}
+
+int crypto4xx_hash_digest(struct ahash_request *req)
+{
+	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+
+	ctx->hash_final = 1;
+	ctx->pd_ctl = 0x11;
+	ctx->direction = DIR_INBOUND;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src,
+				  (struct scatterlist *) req->result,
+				  req->nbytes, NULL, 0);
+}
+
+/**
+ * SHA1 Algorithm
+ */
+int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm)
+{
+	return crypto4xx_hash_alg_init(tfm, SA_HASH160_LEN, SA_HASH_ALG_SHA1,
+				       SA_HASH_MODE_HASH);
+}
+
+
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
new file mode 100644
index 0000000..4c0dfb2
--- /dev/null
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -0,0 +1,1310 @@
+/**
+ * AMCC SoC PPC4xx Crypto Driver
+ *
+ * Copyright (c) 2008 Applied Micro Circuits Corporation.
+ * All rights reserved. James Hsiao <jhsiao@amcc.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.
+ *
+ * This file implements AMCC crypto offload Linux device driver for use with
+ * Linux CryptoAPI.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock_types.h>
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <asm/dcr.h>
+#include <asm/dcr-regs.h>
+#include <asm/cacheflush.h>
+#include <crypto/internal/hash.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/sha.h>
+#include "crypto4xx_reg_def.h"
+#include "crypto4xx_core.h"
+#include "crypto4xx_sa.h"
+
+#define PPC4XX_SEC_VERSION_STR			"0.5"
+
+/**
+ * PPC4xx Crypto Engine Initialization Routine
+ */
+static void crypto4xx_hw_init(struct crypto4xx_device *dev)
+{
+	union ce_ring_size ring_size;
+	union ce_ring_contol ring_ctrl;
+	union ce_part_ring_size part_ring_size;
+	union ce_io_threshold io_threshold;
+	u32 rand_num;
+	union ce_pe_dma_cfg pe_dma_cfg;
+
+	writel(PPC4XX_BYTE_ORDER, dev->ce_base + CRYPTO4XX_BYTE_ORDER_CFG);
+	/* setup pe dma, include reset sg, pdr and pe, then release reset */
+	pe_dma_cfg.w = 0;
+	pe_dma_cfg.bf.bo_sgpd_en = 1;
+	pe_dma_cfg.bf.bo_data_en = 0;
+	pe_dma_cfg.bf.bo_sa_en = 1;
+	pe_dma_cfg.bf.bo_pd_en = 1;
+	pe_dma_cfg.bf.dynamic_sa_en = 1;
+	pe_dma_cfg.bf.reset_sg = 1;
+	pe_dma_cfg.bf.reset_pdr = 1;
+	pe_dma_cfg.bf.reset_pe = 1;
+	writel(pe_dma_cfg.w, dev->ce_base + CRYPTO4XX_PE_DMA_CFG);
+	/* un reset pe,sg and pdr */
+	pe_dma_cfg.bf.pe_mode = 0;
+	pe_dma_cfg.bf.reset_sg = 0;
+	pe_dma_cfg.bf.reset_pdr = 0;
+	pe_dma_cfg.bf.reset_pe = 0;
+	pe_dma_cfg.bf.bo_td_en = 0;
+	writel(pe_dma_cfg.w, dev->ce_base + CRYPTO4XX_PE_DMA_CFG);
+	writel(dev->pdr_pa, dev->ce_base + CRYPTO4XX_PDR_BASE);
+	writel(dev->pdr_pa, dev->ce_base + CRYPTO4XX_RDR_BASE);
+	writel(PPC4XX_PRNG_CTRL_AUTO_EN, dev->ce_base + CRYPTO4XX_PRNG_CTRL);
+	get_random_bytes(&rand_num, sizeof(rand_num));
+	writel(rand_num, dev->ce_base + CRYPTO4XX_PRNG_SEED_L);
+	get_random_bytes(&rand_num, sizeof(rand_num));
+	writel(rand_num, dev->ce_base + CRYPTO4XX_PRNG_SEED_H);
+	ring_size.w = 0;
+	ring_size.bf.ring_offset = PPC4XX_PD_SIZE;
+	ring_size.bf.ring_size   = PPC4XX_NUM_PD;
+	writel(ring_size.w, dev->ce_base + CRYPTO4XX_RING_SIZE);
+	ring_ctrl.w = 0;
+	writel(ring_ctrl.w, dev->ce_base + CRYPTO4XX_RING_CTRL);
+	writel(PPC4XX_DC_3DES_EN, dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
+	writel(dev->gdr_pa, dev->ce_base + CRYPTO4XX_GATH_RING_BASE);
+	writel(dev->sdr_pa, dev->ce_base + CRYPTO4XX_SCAT_RING_BASE);
+	part_ring_size.w = 0;
+	part_ring_size.bf.sdr_size = PPC4XX_SDR_SIZE;
+	part_ring_size.bf.gdr_size = PPC4XX_GDR_SIZE;
+	writel(part_ring_size.w, dev->ce_base + CRYPTO4XX_PART_RING_SIZE);
+	writel(PPC4XX_SD_BUFFER_SIZE, dev->ce_base + CRYPTO4XX_PART_RING_CFG);
+	io_threshold.w = 0;
+	io_threshold.bf.output_threshold = PPC4XX_OUTPUT_THRESHOLD;
+	io_threshold.bf.input_threshold  = PPC4XX_INPUT_THRESHOLD;
+	writel(io_threshold.w, dev->ce_base + CRYPTO4XX_IO_THRESHOLD);
+	writel(0, dev->ce_base + CRYPTO4XX_PDR_BASE_UADDR);
+	writel(0, dev->ce_base + CRYPTO4XX_RDR_BASE_UADDR);
+	writel(0, dev->ce_base + CRYPTO4XX_PKT_SRC_UADDR);
+	writel(0, dev->ce_base + CRYPTO4XX_PKT_DEST_UADDR);
+	writel(0, dev->ce_base + CRYPTO4XX_SA_UADDR);
+	writel(0, dev->ce_base + CRYPTO4XX_GATH_RING_BASE_UADDR);
+	writel(0, dev->ce_base + CRYPTO4XX_SCAT_RING_BASE_UADDR);
+	/* un reset pe,sg and pdr */
+	pe_dma_cfg.bf.pe_mode = 1;
+	pe_dma_cfg.bf.reset_sg = 0;
+	pe_dma_cfg.bf.reset_pdr = 0;
+	pe_dma_cfg.bf.reset_pe = 0;
+	pe_dma_cfg.bf.bo_td_en = 0;
+	writel(pe_dma_cfg.w, dev->ce_base + CRYPTO4XX_PE_DMA_CFG);
+	/*clear all pending interrupt*/
+	writel(PPC4XX_INTERRUPT_CLR, dev->ce_base + CRYPTO4XX_INT_CLR);
+	writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT);
+	writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT);
+	writel(PPC4XX_INT_CFG, dev->ce_base + CRYPTO4XX_INT_CFG);
+	writel(PPC4XX_PD_DONE_INT, dev->ce_base + CRYPTO4XX_INT_EN);
+}
+
+int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size)
+{
+	ctx->sa_in = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4,
+					&ctx->sa_in_dma_addr, GFP_ATOMIC);
+	if (ctx->sa_in == NULL)
+		return -ENOMEM;
+
+	ctx->sa_out = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4,
+					 &ctx->sa_out_dma_addr, GFP_ATOMIC);
+	if (ctx->sa_out == NULL) {
+		dma_free_coherent(ctx->dev->core_dev->device,
+				  ctx->sa_len * 4,
+				  ctx->sa_in, ctx->sa_in_dma_addr);
+		return -ENOMEM;
+	}
+
+	memset(ctx->sa_in, 0, size * 4);
+	memset(ctx->sa_out, 0, size * 4);
+	ctx->sa_len = size;
+
+	return 0;
+}
+
+void crypto4xx_free_sa(struct crypto4xx_ctx *ctx)
+{
+	if (ctx->sa_in != NULL)
+		dma_free_coherent(ctx->dev->core_dev->device, ctx->sa_len * 4,
+				  ctx->sa_in, ctx->sa_in_dma_addr);
+	if (ctx->sa_out != NULL)
+		dma_free_coherent(ctx->dev->core_dev->device, ctx->sa_len * 4,
+				  ctx->sa_out, ctx->sa_out_dma_addr);
+
+	ctx->sa_in_dma_addr = 0;
+	ctx->sa_out_dma_addr = 0;
+	ctx->sa_len = 0;
+}
+
+u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx)
+{
+	ctx->state_record = dma_alloc_coherent(ctx->dev->core_dev->device,
+				sizeof(struct sa_state_record),
+				&ctx->state_record_dma_addr, GFP_ATOMIC);
+	if (!ctx->state_record_dma_addr)
+		return -ENOMEM;
+	memset(ctx->state_record, 0, sizeof(struct sa_state_record));
+
+	return 0;
+}
+
+void crypto4xx_free_state_record(struct crypto4xx_ctx *ctx)
+{
+	if (ctx->state_record != NULL)
+		dma_free_coherent(ctx->dev->core_dev->device,
+				  sizeof(struct sa_state_record),
+				  ctx->state_record,
+				  ctx->state_record_dma_addr);
+	ctx->state_record_dma_addr = 0;
+}
+
+/**
+ * alloc memory for the gather ring
+ * no need to alloc buf for the ring
+ * gdr_tail, gdr_head and gdr_count are initialized by this function
+ */
+static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev)
+{
+	int i;
+	struct pd_uinfo *pd_uinfo;
+	dev->pdr = dma_alloc_coherent(dev->core_dev->device,
+				      sizeof(struct ce_pd) * PPC4XX_NUM_PD,
+				      &dev->pdr_pa, GFP_ATOMIC);
+	if (!dev->pdr)
+		return -ENOMEM;
+
+	dev->pdr_uinfo = kzalloc(sizeof(struct pd_uinfo) * PPC4XX_NUM_PD,
+				GFP_KERNEL);
+	if (!dev->pdr_uinfo) {
+		dma_free_coherent(dev->core_dev->device,
+				  sizeof(struct ce_pd) * PPC4XX_NUM_PD,
+				  dev->pdr,
+				  dev->pdr_pa);
+		return -ENOMEM;
+	}
+	memset(dev->pdr, 0,  sizeof(struct ce_pd) * PPC4XX_NUM_PD);
+	dev->shadow_sa_pool = dma_alloc_coherent(dev->core_dev->device,
+				   256 * PPC4XX_NUM_PD,
+				   &dev->shadow_sa_pool_pa,
+				   GFP_ATOMIC);
+	if (!dev->shadow_sa_pool)
+		return -ENOMEM;
+
+	dev->shadow_sr_pool = dma_alloc_coherent(dev->core_dev->device,
+			 sizeof(struct sa_state_record) * PPC4XX_NUM_PD,
+			 &dev->shadow_sr_pool_pa, GFP_ATOMIC);
+	if (!dev->shadow_sr_pool)
+		return -ENOMEM;
+	for (i = 0; i < PPC4XX_NUM_PD; i++) {
+		pd_uinfo = (struct pd_uinfo *) (dev->pdr_uinfo +
+						sizeof(struct pd_uinfo) * i);
+
+		/* alloc 256 bytes which is enough for any kind of dynamic sa */
+		pd_uinfo->sa_va = dev->shadow_sa_pool + 256 * i;
+		pd_uinfo->sa_pa = dev->shadow_sa_pool_pa + 256 * i;
+
+		/* alloc state record */
+		pd_uinfo->sr_va = dev->shadow_sr_pool +
+		    sizeof(struct sa_state_record) * i;
+		pd_uinfo->sr_pa = dev->shadow_sr_pool_pa +
+		    sizeof(struct sa_state_record) * i;
+	}
+
+	return 0;
+}
+
+static void crypto4xx_destroy_pdr(struct crypto4xx_device *dev)
+{
+	if (dev->pdr != NULL)
+		dma_free_coherent(dev->core_dev->device,
+				  sizeof(struct ce_pd) * PPC4XX_NUM_PD,
+				  dev->pdr, dev->pdr_pa);
+	if (dev->shadow_sa_pool)
+		dma_free_coherent(dev->core_dev->device, 256 * PPC4XX_NUM_PD,
+				  dev->shadow_sa_pool, dev->shadow_sa_pool_pa);
+	if (dev->shadow_sr_pool)
+		dma_free_coherent(dev->core_dev->device,
+			sizeof(struct sa_state_record) * PPC4XX_NUM_PD,
+			dev->shadow_sr_pool, dev->shadow_sr_pool_pa);
+
+	kfree(dev->pdr_uinfo);
+}
+
+static u32 crypto4xx_get_pd_from_pdr_nolock(struct crypto4xx_device *dev)
+{
+	u32 retval;
+	u32 tmp;
+
+	retval = dev->pdr_head;
+	tmp = (dev->pdr_head + 1) % PPC4XX_NUM_PD;
+
+	if (tmp == dev->pdr_tail)
+		return ERING_WAS_FULL;
+
+	dev->pdr_head = tmp;
+
+	return retval;
+}
+
+static u32 crypto4xx_put_pd_to_pdr(struct crypto4xx_device *dev, u32 idx)
+{
+	struct pd_uinfo *pd_uinfo;
+	unsigned long flags;
+
+	pd_uinfo = (struct pd_uinfo *)(dev->pdr_uinfo +
+				       sizeof(struct pd_uinfo) * idx);
+	spin_lock_irqsave(&dev->core_dev->lock, flags);
+	if (dev->pdr_tail != PPC4XX_LAST_PD)
+		dev->pdr_tail++;
+	else
+		dev->pdr_tail = 0;
+	pd_uinfo->state = PD_ENTRY_FREE;
+	spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+
+	return 0;
+}
+
+static struct ce_pd *crypto4xx_get_pdp(struct crypto4xx_device *dev,
+				       dma_addr_t *pd_dma, u32 idx)
+{
+	*pd_dma = dev->pdr_pa + sizeof(struct ce_pd) * idx;
+
+	return dev->pdr + sizeof(struct ce_pd) * idx;
+}
+
+/**
+ * alloc memory for the gather ring
+ * no need to alloc buf for the ring
+ * gdr_tail, gdr_head and gdr_count are initialized by this function
+ */
+static u32 crypto4xx_build_gdr(struct crypto4xx_device *dev)
+{
+	dev->gdr = dma_alloc_coherent(dev->core_dev->device,
+				      sizeof(struct ce_gd) * PPC4XX_NUM_GD,
+				      &dev->gdr_pa, GFP_ATOMIC);
+	if (!dev->gdr)
+		return -ENOMEM;
+
+	memset(dev->gdr, 0, sizeof(struct ce_gd) * PPC4XX_NUM_GD);
+
+	return 0;
+}
+
+static inline void crypto4xx_destroy_gdr(struct crypto4xx_device *dev)
+{
+	dma_free_coherent(dev->core_dev->device,
+			  sizeof(struct ce_gd) * PPC4XX_NUM_GD,
+			  dev->gdr, dev->gdr_pa);
+}
+
+/*
+ * when this function is called.
+ * preemption or interrupt must be disabled
+ */
+u32 crypto4xx_get_n_gd(struct crypto4xx_device *dev, int n)
+{
+	u32 retval;
+	u32 tmp;
+	if (n >= PPC4XX_NUM_GD)
+		return ERING_WAS_FULL;
+
+	retval = dev->gdr_head;
+	tmp = (dev->gdr_head + n) % PPC4XX_NUM_GD;
+	if (dev->gdr_head > dev->gdr_tail) {
+		if (tmp < dev->gdr_head && tmp >= dev->gdr_tail)
+			return ERING_WAS_FULL;
+	} else if (dev->gdr_head < dev->gdr_tail) {
+		if (tmp < dev->gdr_head || tmp >= dev->gdr_tail)
+			return ERING_WAS_FULL;
+	}
+	dev->gdr_head = tmp;
+
+	return retval;
+}
+
+static u32 crypto4xx_put_gd_to_gdr(struct crypto4xx_device *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->core_dev->lock, flags);
+	if (dev->gdr_tail == dev->gdr_head) {
+		spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+		return 0;
+	}
+
+	if (dev->gdr_tail != PPC4XX_LAST_GD)
+		dev->gdr_tail++;
+	else
+		dev->gdr_tail = 0;
+
+	spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+
+	return 0;
+}
+
+static inline struct ce_gd *crypto4xx_get_gdp(struct crypto4xx_device *dev,
+					      dma_addr_t *gd_dma, u32 idx)
+{
+	*gd_dma = dev->gdr_pa + sizeof(struct ce_gd) * idx;
+
+	return (struct ce_gd *) (dev->gdr + sizeof(struct ce_gd) * idx);
+}
+
+/**
+ * alloc memory for the scatter ring
+ * need to alloc buf for the ring
+ * sdr_tail, sdr_head and sdr_count are initialized by this function
+ */
+static u32 crypto4xx_build_sdr(struct crypto4xx_device *dev)
+{
+	int i;
+	struct ce_sd *sd_array;
+
+	/* alloc memory for scatter descriptor ring */
+	dev->sdr = dma_alloc_coherent(dev->core_dev->device,
+				      sizeof(struct ce_sd) * PPC4XX_NUM_SD,
+				      &dev->sdr_pa, GFP_ATOMIC);
+	if (!dev->sdr)
+		return -ENOMEM;
+
+	dev->scatter_buffer_size = PPC4XX_SD_BUFFER_SIZE;
+	dev->scatter_buffer_va =
+		dma_alloc_coherent(dev->core_dev->device,
+			dev->scatter_buffer_size * PPC4XX_NUM_SD,
+			&dev->scatter_buffer_pa, GFP_ATOMIC);
+	if (!dev->scatter_buffer_va) {
+		dma_free_coherent(dev->core_dev->device,
+				  sizeof(struct ce_sd) * PPC4XX_NUM_SD,
+				  dev->sdr, dev->sdr_pa);
+		return -ENOMEM;
+	}
+
+	sd_array = dev->sdr;
+
+	for (i = 0; i < PPC4XX_NUM_SD; i++) {
+		sd_array[i].ptr = dev->scatter_buffer_pa +
+				  dev->scatter_buffer_size * i;
+	}
+
+	return 0;
+}
+
+static void crypto4xx_destroy_sdr(struct crypto4xx_device *dev)
+{
+	if (dev->sdr != NULL)
+		dma_free_coherent(dev->core_dev->device,
+				  sizeof(struct ce_sd) * PPC4XX_NUM_SD,
+				  dev->sdr, dev->sdr_pa);
+
+	if (dev->scatter_buffer_va != NULL)
+		dma_free_coherent(dev->core_dev->device,
+				  dev->scatter_buffer_size * PPC4XX_NUM_SD,
+				  dev->scatter_buffer_va,
+				  dev->scatter_buffer_pa);
+}
+
+/*
+ * when this function is called.
+ * preemption or interrupt must be disabled
+ */
+static u32 crypto4xx_get_n_sd(struct crypto4xx_device *dev, int n)
+{
+	u32 retval;
+	u32 tmp;
+
+	if (n >= PPC4XX_NUM_SD)
+		return ERING_WAS_FULL;
+
+	retval = dev->sdr_head;
+	tmp = (dev->sdr_head + n) % PPC4XX_NUM_SD;
+	if (dev->sdr_head > dev->gdr_tail) {
+		if (tmp < dev->sdr_head && tmp >= dev->sdr_tail)
+			return ERING_WAS_FULL;
+	} else if (dev->sdr_head < dev->sdr_tail) {
+		if (tmp < dev->sdr_head || tmp >= dev->sdr_tail)
+			return ERING_WAS_FULL;
+	} /* the head = tail, or empty case is already take cared */
+	dev->sdr_head = tmp;
+
+	return retval;
+}
+
+static u32 crypto4xx_put_sd_to_sdr(struct crypto4xx_device *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->core_dev->lock, flags);
+	if (dev->sdr_tail == dev->sdr_head) {
+		spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+		return 0;
+	}
+	if (dev->sdr_tail != PPC4XX_LAST_SD)
+		dev->sdr_tail++;
+	else
+		dev->sdr_tail = 0;
+	spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+
+	return 0;
+}
+
+static inline struct ce_sd *crypto4xx_get_sdp(struct crypto4xx_device *dev,
+					      dma_addr_t *sd_dma, u32 idx)
+{
+	*sd_dma = dev->sdr_pa + sizeof(struct ce_sd) * idx;
+
+	return  (struct ce_sd *)(dev->sdr + sizeof(struct ce_sd) * idx);
+}
+
+static u32 crypto4xx_fill_one_page(struct crypto4xx_device *dev,
+				   dma_addr_t *addr, u32 *length,
+				   u32 *idx, u32 *offset, u32 *nbytes)
+{
+	u32 len;
+
+	if (*length > dev->scatter_buffer_size) {
+		memcpy(phys_to_virt(*addr),
+			dev->scatter_buffer_va +
+			*idx * dev->scatter_buffer_size + *offset,
+			dev->scatter_buffer_size);
+		*offset = 0;
+		*length -= dev->scatter_buffer_size;
+		*nbytes -= dev->scatter_buffer_size;
+		if (*idx == PPC4XX_LAST_SD)
+			*idx = 0;
+		else
+			(*idx)++;
+		*addr = *addr +  dev->scatter_buffer_size;
+		return 1;
+	} else if (*length < dev->scatter_buffer_size) {
+		memcpy(phys_to_virt(*addr),
+			dev->scatter_buffer_va +
+			*idx * dev->scatter_buffer_size + *offset, *length);
+		if ((*offset + *length) == dev->scatter_buffer_size) {
+			if (*idx == PPC4XX_LAST_SD)
+				*idx = 0;
+			else
+				(*idx)++;
+			*nbytes -= *length;
+			*offset = 0;
+		} else {
+			*nbytes -= *length;
+			*offset += *length;
+		}
+
+		return 0;
+	} else {
+		len = (*nbytes <= dev->scatter_buffer_size) ?
+				(*nbytes) : dev->scatter_buffer_size;
+		memcpy(phys_to_virt(*addr),
+			dev->scatter_buffer_va +
+			*idx * dev->scatter_buffer_size + *offset,
+			len);
+		*offset = 0;
+		*nbytes -= len;
+
+		if (*idx == PPC4XX_LAST_SD)
+			*idx = 0;
+		else
+			(*idx)++;
+
+		return 0;
+    }
+}
+
+static void crypto4xx_copy_pkt_to_dst(struct crypto4xx_device *dev,
+				      struct ce_pd *pd,
+				      struct pd_uinfo *pd_uinfo,
+				      u32 nbytes,
+				      struct scatterlist *dst)
+{
+	dma_addr_t addr;
+	u32 this_sd;
+	u32 offset;
+	u32 len;
+	u32 i;
+	u32 sg_len;
+	struct scatterlist *sg;
+
+	this_sd = pd_uinfo->first_sd;
+	offset = 0;
+	i = 0;
+
+	while (nbytes) {
+		sg = &dst[i];
+		sg_len = sg->length;
+		addr = dma_map_page(dev->core_dev->device, sg_page(sg),
+				sg->offset, sg->length, DMA_TO_DEVICE);
+
+		if (offset == 0) {
+			len = (nbytes <= sg->length) ? nbytes : sg->length;
+			while (crypto4xx_fill_one_page(dev, &addr, &len,
+				&this_sd, &offset, &nbytes))
+				;
+			if (!nbytes)
+				return;
+			i++;
+		} else {
+			len = (nbytes <= (dev->scatter_buffer_size - offset)) ?
+				nbytes : (dev->scatter_buffer_size - offset);
+			len = (sg->length < len) ? sg->length : len;
+			while (crypto4xx_fill_one_page(dev, &addr, &len,
+					       &this_sd, &offset, &nbytes))
+				;
+			if (!nbytes)
+				return;
+			sg_len -= len;
+			if (sg_len) {
+				addr += len;
+				while (crypto4xx_fill_one_page(dev, &addr,
+					&sg_len, &this_sd, &offset, &nbytes))
+					;
+			}
+			i++;
+		}
+	}
+}
+
+static u32 crypto4xx_copy_digest_to_dst(struct pd_uinfo *pd_uinfo,
+					struct crypto4xx_ctx *ctx)
+{
+	struct dynamic_sa_ctl *sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+	struct sa_state_record *state_record =
+				(struct sa_state_record *) pd_uinfo->sr_va;
+
+	if (sa->sa_command_0.bf.hash_alg == SA_HASH_ALG_SHA1) {
+		memcpy((void *) pd_uinfo->dest_va, state_record->save_digest,
+		       SA_HASH_ALG_SHA1_DIGEST_SIZE);
+	}
+
+	return 0;
+}
+
+static void crypto4xx_ret_sg_desc(struct crypto4xx_device *dev,
+				  struct pd_uinfo *pd_uinfo)
+{
+	int i;
+	if (pd_uinfo->num_gd) {
+		for (i = 0; i < pd_uinfo->num_gd; i++)
+			crypto4xx_put_gd_to_gdr(dev);
+		pd_uinfo->first_gd = 0xffffffff;
+		pd_uinfo->num_gd = 0;
+	}
+	if (pd_uinfo->num_sd) {
+		for (i = 0; i < pd_uinfo->num_sd; i++)
+			crypto4xx_put_sd_to_sdr(dev);
+
+		pd_uinfo->first_sd = 0xffffffff;
+		pd_uinfo->num_sd = 0;
+	}
+}
+
+static u32 crypto4xx_ablkcipher_done(struct crypto4xx_device *dev,
+				     struct pd_uinfo *pd_uinfo,
+				     struct ce_pd *pd)
+{
+	struct crypto4xx_ctx *ctx;
+	struct ablkcipher_request *ablk_req;
+	struct scatterlist *dst;
+	dma_addr_t addr;
+
+	ablk_req = ablkcipher_request_cast(pd_uinfo->async_req);
+	ctx  = crypto_tfm_ctx(ablk_req->base.tfm);
+
+	if (pd_uinfo->using_sd) {
+		crypto4xx_copy_pkt_to_dst(dev, pd, pd_uinfo, ablk_req->nbytes,
+					  ablk_req->dst);
+	} else {
+		dst = pd_uinfo->dest_va;
+		addr = dma_map_page(dev->core_dev->device, sg_page(dst),
+				    dst->offset, dst->length, DMA_FROM_DEVICE);
+	}
+	crypto4xx_ret_sg_desc(dev, pd_uinfo);
+	if (ablk_req->base.complete != NULL)
+		ablk_req->base.complete(&ablk_req->base, 0);
+
+	return 0;
+}
+
+static u32 crypto4xx_ahash_done(struct crypto4xx_device *dev,
+				struct pd_uinfo *pd_uinfo)
+{
+	struct crypto4xx_ctx *ctx;
+	struct ahash_request *ahash_req;
+
+	ahash_req = ahash_request_cast(pd_uinfo->async_req);
+	ctx  = crypto_tfm_ctx(ahash_req->base.tfm);
+
+	crypto4xx_copy_digest_to_dst(pd_uinfo,
+				     crypto_tfm_ctx(ahash_req->base.tfm));
+	crypto4xx_ret_sg_desc(dev, pd_uinfo);
+	/* call user provided callback function x */
+	if (ahash_req->base.complete != NULL)
+		ahash_req->base.complete(&ahash_req->base, 0);
+
+	return 0;
+}
+
+static u32 crypto4xx_pd_done(struct crypto4xx_device *dev, u32 idx)
+{
+	struct ce_pd *pd;
+	struct pd_uinfo *pd_uinfo;
+
+	pd =  dev->pdr + sizeof(struct ce_pd)*idx;
+	pd_uinfo = dev->pdr_uinfo + sizeof(struct pd_uinfo)*idx;
+	if (crypto_tfm_alg_type(pd_uinfo->async_req->tfm) ==
+			CRYPTO_ALG_TYPE_ABLKCIPHER)
+		return crypto4xx_ablkcipher_done(dev, pd_uinfo, pd);
+	else
+		return crypto4xx_ahash_done(dev, pd_uinfo);
+}
+
+/**
+ * Note: Only use this function to copy items that is word aligned.
+ */
+void crypto4xx_memcpy_le(unsigned int *dst,
+			 const unsigned char *buf,
+			 int len)
+{
+	u8 *tmp;
+	for (; len >= 4; buf += 4, len -= 4)
+		*dst++ = cpu_to_le32(*(unsigned int *) buf);
+
+	tmp = (u8 *)dst;
+	switch (len) {
+	case 3:
+		*tmp++ = 0;
+		*tmp++ = *(buf+2);
+		*tmp++ = *(buf+1);
+		*tmp++ = *buf;
+		break;
+	case 2:
+		*tmp++ = 0;
+		*tmp++ = 0;
+		*tmp++ = *(buf+1);
+		*tmp++ = *buf;
+		break;
+	case 1:
+		*tmp++ = 0;
+		*tmp++ = 0;
+		*tmp++ = 0;
+		*tmp++ = *buf;
+		break;
+	default:
+		break;
+	}
+}
+
+static void crypto4xx_stop_all(struct crypto4xx_core_device *core_dev)
+{
+	crypto4xx_destroy_pdr(core_dev->dev);
+	crypto4xx_destroy_gdr(core_dev->dev);
+	crypto4xx_destroy_sdr(core_dev->dev);
+	dev_set_drvdata(core_dev->device, NULL);
+	iounmap(core_dev->dev->ce_base);
+	kfree(core_dev->dev);
+	kfree(core_dev);
+}
+
+void crypto4xx_return_pd(struct crypto4xx_device *dev,
+			 u32 pd_entry, struct ce_pd *pd,
+			 struct pd_uinfo *pd_uinfo)
+{
+	/* irq should be already disabled */
+	dev->pdr_head = pd_entry;
+	pd->pd_ctl.w = 0;
+	pd->pd_ctl_len.w = 0;
+	pd_uinfo->state = PD_ENTRY_FREE;
+}
+
+/*
+ * derive number of elements in scatterlist
+ * Shamlessly copy from talitos.c
+ */
+static int get_sg_count(struct scatterlist *sg_list, int nbytes)
+{
+	struct scatterlist *sg = sg_list;
+	int sg_nents = 0;
+
+	while (nbytes) {
+		sg_nents++;
+		if (sg->length > nbytes)
+			break;
+		nbytes -= sg->length;
+		sg = sg_next(sg);
+	}
+
+	return sg_nents;
+}
+
+static u32 get_next_gd(u32 current)
+{
+	if (current != PPC4XX_LAST_GD)
+		return current + 1;
+	else
+		return 0;
+}
+
+static u32 get_next_sd(u32 current)
+{
+	if (current != PPC4XX_LAST_SD)
+		return current + 1;
+	else
+		return 0;
+}
+
+u32 crypto4xx_build_pd(struct crypto_async_request *req,
+		       struct crypto4xx_ctx *ctx,
+		       struct scatterlist *src,
+		       struct scatterlist *dst,
+		       unsigned int datalen,
+		       void *iv, u32 iv_len)
+{
+	struct crypto4xx_device *dev = ctx->dev;
+	dma_addr_t addr, pd_dma, sd_dma, gd_dma;
+	struct dynamic_sa_ctl *sa;
+	struct scatterlist *sg;
+	struct ce_gd *gd;
+	struct ce_pd *pd;
+	u32 num_gd, num_sd;
+	u32 fst_gd = 0xffffffff;
+	u32 fst_sd = 0xffffffff;
+	u32 pd_entry;
+	unsigned long flags;
+	struct pd_uinfo *pd_uinfo = NULL;
+	unsigned int nbytes = datalen, idx;
+	unsigned int ivlen = 0;
+	u32 gd_idx = 0;
+
+	/* figure how many gd is needed */
+	num_gd = get_sg_count(src, datalen);
+	if (num_gd == 1)
+		num_gd = 0;
+
+	/* figure how many sd is needed */
+	if (sg_is_last(dst) || ctx->is_hash) {
+		num_sd = 0;
+	} else {
+		if (datalen > PPC4XX_SD_BUFFER_SIZE) {
+			num_sd = datalen / PPC4XX_SD_BUFFER_SIZE;
+			if (datalen % PPC4XX_SD_BUFFER_SIZE)
+				num_sd++;
+		} else {
+			num_sd = 1;
+		}
+	}
+
+	/*
+	 * The follow section of code needs to be protected
+	 * The gather ring and scatter ring needs to be consecutive
+	 * In case of run out of any kind of descriptor, the descriptor
+	 * already got must be return the original place.
+	 */
+	spin_lock_irqsave(&dev->core_dev->lock, flags);
+	if (num_gd) {
+		fst_gd = crypto4xx_get_n_gd(dev, num_gd);
+		if (fst_gd == ERING_WAS_FULL) {
+			spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+			return -EAGAIN;
+		}
+	}
+	if (num_sd) {
+		fst_sd = crypto4xx_get_n_sd(dev, num_sd);
+		if (fst_sd == ERING_WAS_FULL) {
+			if (num_gd)
+				dev->gdr_head = fst_gd;
+			spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+			return -EAGAIN;
+		}
+	}
+	pd_entry = crypto4xx_get_pd_from_pdr_nolock(dev);
+	if (pd_entry == ERING_WAS_FULL) {
+		if (num_gd)
+			dev->gdr_head = fst_gd;
+		if (num_sd)
+			dev->sdr_head = fst_sd;
+		spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+		return -EAGAIN;
+	}
+	spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+
+	pd_uinfo = (struct pd_uinfo *)(dev->pdr_uinfo +
+				       sizeof(struct pd_uinfo) * pd_entry);
+	pd = crypto4xx_get_pdp(dev, &pd_dma, pd_entry);
+	pd_uinfo->async_req = req;
+	pd_uinfo->num_gd = num_gd;
+	pd_uinfo->num_sd = num_sd;
+
+	if (iv_len || ctx->is_hash) {
+		ivlen = iv_len;
+		pd->sa = pd_uinfo->sa_pa;
+		sa = (struct dynamic_sa_ctl *) pd_uinfo->sa_va;
+		if (ctx->direction == DIR_INBOUND)
+			memcpy(sa, ctx->sa_in, ctx->sa_len * 4);
+		else
+			memcpy(sa, ctx->sa_out, ctx->sa_len * 4);
+
+		memcpy((void *) sa + ctx->offset_to_sr_ptr,
+			&pd_uinfo->sr_pa, 4);
+
+		if (iv_len)
+			crypto4xx_memcpy_le(pd_uinfo->sr_va, iv, iv_len);
+	} else {
+		if (ctx->direction == DIR_INBOUND) {
+			pd->sa = ctx->sa_in_dma_addr;
+			sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+		} else {
+			pd->sa = ctx->sa_out_dma_addr;
+			sa = (struct dynamic_sa_ctl *) ctx->sa_out;
+		}
+	}
+	pd->sa_len = ctx->sa_len;
+	if (num_gd) {
+		/* get first gd we are going to use */
+		gd_idx = fst_gd;
+		pd_uinfo->first_gd = fst_gd;
+		pd_uinfo->num_gd = num_gd;
+		gd = crypto4xx_get_gdp(dev, &gd_dma, gd_idx);
+		pd->src = gd_dma;
+		/* enable gather */
+		sa->sa_command_0.bf.gather = 1;
+		idx = 0;
+		src = &src[0];
+		/* walk the sg, and setup gather array */
+		while (nbytes) {
+			sg = &src[idx];
+			addr = dma_map_page(dev->core_dev->device, sg_page(sg),
+				    sg->offset, sg->length, DMA_TO_DEVICE);
+			gd->ptr = addr;
+			gd->ctl_len.len = sg->length;
+			gd->ctl_len.done = 0;
+			gd->ctl_len.ready = 1;
+			if (sg->length >= nbytes)
+				break;
+			nbytes -= sg->length;
+			gd_idx = get_next_gd(gd_idx);
+			gd = crypto4xx_get_gdp(dev, &gd_dma, gd_idx);
+			idx++;
+		}
+	} else {
+		pd->src = (u32)dma_map_page(dev->core_dev->device, sg_page(src),
+				src->offset, src->length, DMA_TO_DEVICE);
+		/*
+		 * Disable gather in sa command
+		 */
+		sa->sa_command_0.bf.gather = 0;
+		/*
+		 * Indicate gather array is not used
+		 */
+		pd_uinfo->first_gd = 0xffffffff;
+		pd_uinfo->num_gd = 0;
+	}
+	if (ctx->is_hash || sg_is_last(dst)) {
+		/*
+		 * we know application give us dst a whole piece of memory
+		 * no need to use scatter ring.
+		 * In case of is_hash, the icv is always at end of src data.
+		 */
+		pd_uinfo->using_sd = 0;
+		pd_uinfo->first_sd = 0xffffffff;
+		pd_uinfo->num_sd = 0;
+		pd_uinfo->dest_va = dst;
+		sa->sa_command_0.bf.scatter = 0;
+		if (ctx->is_hash)
+			pd->dest = virt_to_phys((void *)dst);
+		else
+			pd->dest = (u32)dma_map_page(dev->core_dev->device,
+					sg_page(dst), dst->offset,
+					dst->length, DMA_TO_DEVICE);
+	} else {
+		struct ce_sd *sd = NULL;
+		u32 sd_idx = fst_sd;
+		nbytes = datalen;
+		sa->sa_command_0.bf.scatter = 1;
+		pd_uinfo->using_sd = 1;
+		pd_uinfo->dest_va = dst;
+		pd_uinfo->first_sd = fst_sd;
+		pd_uinfo->num_sd = num_sd;
+		sd = crypto4xx_get_sdp(dev, &sd_dma, sd_idx);
+		pd->dest = sd_dma;
+		/* setup scatter descriptor */
+		sd->ctl.done = 0;
+		sd->ctl.rdy = 1;
+		/* sd->ptr should be setup by sd_init routine*/
+		idx = 0;
+		if (nbytes >= PPC4XX_SD_BUFFER_SIZE)
+			nbytes -= PPC4XX_SD_BUFFER_SIZE;
+		else
+			nbytes = 0;
+		while (nbytes) {
+			sd_idx = get_next_sd(sd_idx);
+			sd = crypto4xx_get_sdp(dev, &sd_dma, sd_idx);
+			/* setup scatter descriptor */
+			sd->ctl.done = 0;
+			sd->ctl.rdy = 1;
+			if (nbytes >= PPC4XX_SD_BUFFER_SIZE)
+				nbytes -= PPC4XX_SD_BUFFER_SIZE;
+			else
+				/*
+				 * SD entry can hold PPC4XX_SD_BUFFER_SIZE,
+				 * which is more than nbytes, so done.
+				 */
+				nbytes = 0;
+		}
+	}
+
+	sa->sa_command_1.bf.hash_crypto_offset = 0;
+	pd->pd_ctl.w = ctx->pd_ctl;
+	pd->pd_ctl_len.w = 0x00400000 | (ctx->bypass << 24) | datalen;
+	pd_uinfo->state = PD_ENTRY_INUSE;
+	wmb();
+	/* write any value to push engine to read a pd */
+	writel(1, dev->ce_base + CRYPTO4XX_INT_DESCR_RD);
+	return -EINPROGRESS;
+}
+
+/**
+ * Algorithm Registration Functions
+ */
+static int crypto4xx_alg_init(struct crypto_tfm *tfm)
+{
+	struct crypto_alg *alg = tfm->__crt_alg;
+	struct crypto4xx_alg *amcc_alg = crypto_alg_to_crypto4xx_alg(alg);
+	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->dev = amcc_alg->dev;
+	ctx->sa_in = NULL;
+	ctx->sa_out = NULL;
+	ctx->sa_in_dma_addr = 0;
+	ctx->sa_out_dma_addr = 0;
+	ctx->sa_len = 0;
+
+	if (alg->cra_type == &crypto_ablkcipher_type)
+		tfm->crt_ablkcipher.reqsize = sizeof(struct crypto4xx_ctx);
+	else if (alg->cra_type == &crypto_ahash_type)
+		tfm->crt_ahash.reqsize = sizeof(struct crypto4xx_ctx);
+
+	return 0;
+}
+
+static void crypto4xx_alg_exit(struct crypto_tfm *tfm)
+{
+	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto4xx_free_sa(ctx);
+	crypto4xx_free_state_record(ctx);
+}
+
+int crypto4xx_register_alg(struct crypto4xx_device *sec_dev,
+			   struct crypto_alg *crypto_alg, int array_size)
+{
+	struct crypto4xx_alg *alg;
+	int i;
+	int rc = 0;
+
+	for (i = 0; i < array_size; i++) {
+		alg = kzalloc(sizeof(struct crypto4xx_alg), GFP_KERNEL);
+		if (!alg)
+			return -ENOMEM;
+
+		alg->alg = crypto_alg[i];
+		INIT_LIST_HEAD(&alg->alg.cra_list);
+		if (alg->alg.cra_init == NULL)
+			alg->alg.cra_init = crypto4xx_alg_init;
+		if (alg->alg.cra_exit == NULL)
+			alg->alg.cra_exit = crypto4xx_alg_exit;
+		alg->dev = sec_dev;
+		rc = crypto_register_alg(&alg->alg);
+		if (rc) {
+			list_del(&alg->entry);
+			kfree(alg);
+		} else {
+			list_add_tail(&alg->entry, &sec_dev->alg_list);
+		}
+	}
+
+	return 0;
+}
+
+static void crypto4xx_unregister_alg(struct crypto4xx_device *sec_dev)
+{
+	struct crypto4xx_alg *alg, *tmp;
+
+	list_for_each_entry_safe(alg, tmp, &sec_dev->alg_list, entry) {
+		list_del(&alg->entry);
+		crypto_unregister_alg(&alg->alg);
+		kfree(alg);
+	}
+}
+
+static void crypto4xx_bh_tasklet_cb(unsigned long data)
+{
+	struct device *dev = (struct device *)data;
+	struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
+	struct pd_uinfo *pd_uinfo;
+	struct ce_pd *pd;
+	u32 tail;
+
+	while (core_dev->dev->pdr_head != core_dev->dev->pdr_tail) {
+		tail = core_dev->dev->pdr_tail;
+		pd_uinfo = core_dev->dev->pdr_uinfo +
+			sizeof(struct pd_uinfo)*tail;
+		pd =  core_dev->dev->pdr + sizeof(struct ce_pd) * tail;
+		if ((pd_uinfo->state == PD_ENTRY_INUSE) &&
+				   pd->pd_ctl.bf.pe_done &&
+				   !pd->pd_ctl.bf.host_ready) {
+			pd->pd_ctl.bf.pe_done = 0;
+			crypto4xx_pd_done(core_dev->dev, tail);
+			crypto4xx_put_pd_to_pdr(core_dev->dev, tail);
+			pd_uinfo->state = PD_ENTRY_FREE;
+		} else {
+			/* if tail not done, break */
+			break;
+		}
+	}
+}
+
+/**
+ * Top Half of isr.
+ */
+static irqreturn_t crypto4xx_ce_interrupt_handler(int irq, void *data)
+{
+	struct device *dev = (struct device *)data;
+	struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
+
+	if (core_dev->dev->ce_base == 0)
+		return 0;
+
+	writel(PPC4XX_INTERRUPT_CLR,
+	       core_dev->dev->ce_base + CRYPTO4XX_INT_CLR);
+	tasklet_schedule(&core_dev->tasklet);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * Supported Crypto Algorithms
+ */
+struct crypto_alg crypto4xx_alg[] = {
+	/* Crypto AES modes */
+	{
+		.cra_name 	= "cbc(aes)",
+		.cra_driver_name = "cbc-aes-ppc4xx",
+		.cra_priority 	= CRYPTO4XX_CRYPTO_PRIORITY,
+		.cra_flags 	= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+		.cra_blocksize 	= AES_BLOCK_SIZE,
+		.cra_ctxsize 	= sizeof(struct crypto4xx_ctx),
+		.cra_alignmask 	= 0,
+		.cra_type 	= &crypto_ablkcipher_type,
+		.cra_module 	= THIS_MODULE,
+		.cra_u 		= {
+			.ablkcipher = {
+				.min_keysize 	= AES_MIN_KEY_SIZE,
+				.max_keysize 	= AES_MAX_KEY_SIZE,
+				.ivsize		= AES_IV_SIZE,
+				.setkey 	= crypto4xx_setkey_aes_cbc,
+				.encrypt 	= crypto4xx_encrypt,
+				.decrypt 	= crypto4xx_decrypt,
+			}
+		}
+	},
+	/* Hash SHA1 */
+	{
+		.cra_name	= "sha1",
+		.cra_driver_name = "sha1-ppc4xx",
+		.cra_priority	= CRYPTO4XX_CRYPTO_PRIORITY,
+		.cra_flags	= CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+		.cra_blocksize	= SHA1_BLOCK_SIZE,
+		.cra_ctxsize	= sizeof(struct crypto4xx_ctx),
+		.cra_alignmask	= 0,
+		.cra_type	= &crypto_ahash_type,
+		.cra_init	= crypto4xx_sha1_alg_init,
+		.cra_module	= THIS_MODULE,
+		.cra_u		= {
+			.ahash = {
+				.digestsize 	= SHA1_DIGEST_SIZE,
+				.init		= crypto4xx_hash_init,
+				.update		= crypto4xx_hash_update,
+				.final  	= crypto4xx_hash_final,
+				.digest 	= crypto4xx_hash_digest,
+			}
+		}
+	},
+};
+
+/**
+ * Module Initialization Routine
+ */
+static int __init crypto4xx_probe(struct of_device *ofdev,
+				  const struct of_device_id *match)
+{
+	int rc;
+	struct resource res;
+	struct device *dev = &ofdev->dev;
+	struct crypto4xx_core_device *core_dev;
+
+	rc = of_address_to_resource(ofdev->node, 0, &res);
+	if (rc)
+		return -ENODEV;
+
+	if (of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-crypto")) {
+		mtdcri(SDR0, PPC460EX_SDR0_SRST,
+		       mfdcri(SDR0, PPC460EX_SDR0_SRST) | PPC460EX_CE_RESET);
+		mtdcri(SDR0, PPC460EX_SDR0_SRST,
+		       mfdcri(SDR0, PPC460EX_SDR0_SRST) & ~PPC460EX_CE_RESET);
+	} else if (of_find_compatible_node(NULL, NULL,
+			"amcc,ppc405ex-crypto")) {
+		mtdcri(SDR0, PPC405EX_SDR0_SRST,
+		       mfdcri(SDR0, PPC405EX_SDR0_SRST) | PPC405EX_CE_RESET);
+		mtdcri(SDR0, PPC405EX_SDR0_SRST,
+		       mfdcri(SDR0, PPC405EX_SDR0_SRST) & ~PPC405EX_CE_RESET);
+	} else if (of_find_compatible_node(NULL, NULL,
+			"amcc,ppc460sx-crypto")) {
+		mtdcri(SDR0, PPC460SX_SDR0_SRST,
+		       mfdcri(SDR0, PPC460SX_SDR0_SRST) | PPC460SX_CE_RESET);
+		mtdcri(SDR0, PPC460SX_SDR0_SRST,
+		       mfdcri(SDR0, PPC460SX_SDR0_SRST) & ~PPC460SX_CE_RESET);
+	} else {
+		printk(KERN_ERR "Crypto Function Not supported!\n");
+		return -EINVAL;
+	}
+
+	core_dev = kzalloc(sizeof(struct crypto4xx_core_device), GFP_KERNEL);
+	if (!core_dev)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, core_dev);
+	core_dev->ofdev = ofdev;
+	core_dev->dev = kzalloc(sizeof(struct crypto4xx_device), GFP_KERNEL);
+	if (!core_dev->dev)
+		goto err_alloc_dev;
+
+	core_dev->dev->core_dev = core_dev;
+	core_dev->device = dev;
+	spin_lock_init(&core_dev->lock);
+	INIT_LIST_HEAD(&core_dev->dev->alg_list);
+	rc = crypto4xx_build_pdr(core_dev->dev);
+	if (rc)
+		goto err_build_pdr;
+
+	rc = crypto4xx_build_gdr(core_dev->dev);
+	if (rc)
+		goto err_build_gdr;
+
+	rc = crypto4xx_build_sdr(core_dev->dev);
+	if (rc)
+		goto err_build_sdr;
+
+	/* Init tasklet for bottom half processing */
+	tasklet_init(&core_dev->tasklet, crypto4xx_bh_tasklet_cb,
+		     (unsigned long) dev);
+
+	/* Register for Crypto isr, Crypto Engine IRQ */
+	core_dev->irq = irq_of_parse_and_map(ofdev->node, 0);
+	rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0,
+			 core_dev->dev->name, dev);
+	if (rc)
+		goto err_request_irq;
+
+	core_dev->dev->ce_base = of_iomap(ofdev->node, 0);
+	if (!core_dev->dev->ce_base) {
+		dev_err(dev, "failed to of_iomap\n");
+		goto err_iomap;
+	}
+
+	/* need to setup pdr, rdr, gdr and sdr before this */
+	crypto4xx_hw_init(core_dev->dev);
+
+	/* Register security algorithms with Linux CryptoAPI */
+	rc = crypto4xx_register_alg(core_dev->dev, crypto4xx_alg,
+			       ARRAY_SIZE(crypto4xx_alg));
+	if (rc)
+		goto err_start_dev;
+
+	return 0;
+
+err_start_dev:
+	iounmap(core_dev->dev->ce_base);
+err_iomap:
+	free_irq(core_dev->irq, dev);
+	irq_dispose_mapping(core_dev->irq);
+	tasklet_kill(&core_dev->tasklet);
+err_request_irq:
+	crypto4xx_destroy_sdr(core_dev->dev);
+err_build_sdr:
+	crypto4xx_destroy_gdr(core_dev->dev);
+err_build_gdr:
+	crypto4xx_destroy_pdr(core_dev->dev);
+err_build_pdr:
+	kfree(core_dev->dev);
+err_alloc_dev:
+	kfree(core_dev);
+
+	return rc;
+}
+
+static int __exit crypto4xx_remove(struct of_device *ofdev)
+{
+	struct device *dev = &ofdev->dev;
+	struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
+
+	free_irq(core_dev->irq, dev);
+	irq_dispose_mapping(core_dev->irq);
+
+	tasklet_kill(&core_dev->tasklet);
+	/* Un-register with Linux CryptoAPI */
+	crypto4xx_unregister_alg(core_dev->dev);
+	/* Free all allocated memory */
+	crypto4xx_stop_all(core_dev);
+
+	return 0;
+}
+
+static struct of_device_id crypto4xx_match[] = {
+	{ .compatible      = "amcc,ppc4xx-crypto",},
+	{ },
+};
+
+static struct of_platform_driver crypto4xx_driver = {
+	.name		= "crypto4xx",
+	.match_table	= crypto4xx_match,
+	.probe		= crypto4xx_probe,
+	.remove		= crypto4xx_remove,
+};
+
+static int __init crypto4xx_init(void)
+{
+	return of_register_platform_driver(&crypto4xx_driver);
+}
+
+static void __exit crypto4xx_exit(void)
+{
+	of_unregister_platform_driver(&crypto4xx_driver);
+}
+
+module_init(crypto4xx_init);
+module_exit(crypto4xx_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Hsiao <jhsiao@amcc.com>");
+MODULE_DESCRIPTION("Driver for AMCC PPC4xx crypto accelerator");
+
diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h
new file mode 100644
index 0000000..1ef1034
--- /dev/null
+++ b/drivers/crypto/amcc/crypto4xx_core.h
@@ -0,0 +1,177 @@
+/**
+ * AMCC SoC PPC4xx Crypto Driver
+ *
+ * Copyright (c) 2008 Applied Micro Circuits Corporation.
+ * All rights reserved. James Hsiao <jhsiao@amcc.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.
+ *
+ * This is the header file for AMCC Crypto offload Linux device driver for
+ * use with Linux CryptoAPI.
+
+ */
+
+#ifndef __CRYPTO4XX_CORE_H__
+#define __CRYPTO4XX_CORE_H__
+
+#define PPC460SX_SDR0_SRST                      0x201
+#define PPC405EX_SDR0_SRST                      0x200
+#define PPC460EX_SDR0_SRST                      0x201
+#define PPC460EX_CE_RESET                       0x08000000
+#define PPC460SX_CE_RESET                       0x20000000
+#define PPC405EX_CE_RESET                       0x00000008
+
+#define CRYPTO4XX_CRYPTO_PRIORITY		300
+#define PPC4XX_LAST_PD				63
+#define PPC4XX_NUM_PD				64
+#define PPC4XX_LAST_GD				1023
+#define PPC4XX_NUM_GD				1024
+#define PPC4XX_LAST_SD				63
+#define PPC4XX_NUM_SD				64
+#define PPC4XX_SD_BUFFER_SIZE			2048
+
+#define PD_ENTRY_INUSE				1
+#define PD_ENTRY_FREE				0
+#define ERING_WAS_FULL				0xffffffff
+
+struct crypto4xx_device;
+
+struct pd_uinfo {
+	struct crypto4xx_device *dev;
+	u32   state;
+	u32 using_sd;
+	u32 first_gd;		/* first gather discriptor
+				used by this packet */
+	u32 num_gd;             /* number of gather discriptor
+				used by this packet */
+	u32 first_sd;		/* first scatter discriptor
+				used by this packet */
+	u32 num_sd;		/* number of scatter discriptors
+				used by this packet */
+	void *sa_va;		/* shadow sa, when using cp from ctx->sa */
+	u32 sa_pa;
+	void *sr_va;		/* state record for shadow sa */
+	u32 sr_pa;
+	struct scatterlist *dest_va;
+	struct crypto_async_request *async_req; 	/* base crypto request
+							for this packet */
+};
+
+struct crypto4xx_device {
+	struct crypto4xx_core_device *core_dev;
+	char *name;
+	u64  ce_phy_address;
+	void __iomem *ce_base;
+
+	void *pdr;			/* base address of packet
+					descriptor ring */
+	dma_addr_t pdr_pa;		/* physical address used to
+					program ce pdr_base_register */
+	void *gdr;                      /* gather descriptor ring */
+	dma_addr_t gdr_pa;		/* physical address used to
+					program ce gdr_base_register */
+	void *sdr;			/* scatter descriptor ring */
+	dma_addr_t sdr_pa;		/* physical address used to
+					program ce sdr_base_register */
+	void *scatter_buffer_va;
+	dma_addr_t scatter_buffer_pa;
+	u32 scatter_buffer_size;
+
+	void *shadow_sa_pool;		/* pool of memory for sa in pd_uinfo */
+	dma_addr_t shadow_sa_pool_pa;
+	void *shadow_sr_pool;		/* pool of memory for sr in pd_uinfo */
+	dma_addr_t shadow_sr_pool_pa;
+	u32 pdr_tail;
+	u32 pdr_head;
+	u32 gdr_tail;
+	u32 gdr_head;
+	u32 sdr_tail;
+	u32 sdr_head;
+	void *pdr_uinfo;
+	struct list_head alg_list;	/* List of algorithm supported
+					by this device */
+};
+
+struct crypto4xx_core_device {
+	struct device *device;
+	struct of_device *ofdev;
+	struct crypto4xx_device *dev;
+	u32 int_status;
+	u32 irq;
+	struct tasklet_struct tasklet;
+	spinlock_t lock;
+};
+
+struct crypto4xx_ctx {
+	struct crypto4xx_device *dev;
+	void *sa_in;
+	dma_addr_t sa_in_dma_addr;
+	void *sa_out;
+	dma_addr_t sa_out_dma_addr;
+	void *state_record;
+	dma_addr_t state_record_dma_addr;
+	u32 sa_len;
+	u32 offset_to_sr_ptr;           /* offset to state ptr, in dynamic sa */
+	u32 direction;
+	u32 next_hdr;
+	u32 save_iv;
+	u32 pd_ctl_len;
+	u32 pd_ctl;
+	u32 bypass;
+	u32 is_hash;
+	u32 hash_final;
+};
+
+struct crypto4xx_req_ctx {
+	struct crypto4xx_device *dev;	/* Device in which
+					operation to send to */
+	void *sa;
+	u32 sa_dma_addr;
+	u16 sa_len;
+};
+
+struct crypto4xx_alg {
+	struct list_head  entry;
+	struct crypto_alg alg;
+	struct crypto4xx_device *dev;
+};
+
+#define crypto_alg_to_crypto4xx_alg(x) \
+		container_of(x, struct crypto4xx_alg, alg)
+
+extern int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size);
+extern void crypto4xx_free_sa(struct crypto4xx_ctx *ctx);
+extern u32 crypto4xx_alloc_sa_rctx(struct crypto4xx_ctx *ctx,
+				   struct crypto4xx_ctx *rctx);
+extern void crypto4xx_free_sa_rctx(struct crypto4xx_ctx *rctx);
+extern void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
+extern u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx);
+extern u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx);
+extern u32 get_dynamic_sa_offset_key_field(struct crypto4xx_ctx *ctx);
+extern u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx);
+extern void crypto4xx_memcpy_le(unsigned int *dst,
+				const unsigned char *buf, int len);
+extern u32 crypto4xx_build_pd(struct crypto_async_request *req,
+			      struct crypto4xx_ctx *ctx,
+			      struct scatterlist *src,
+			      struct scatterlist *dst,
+			      unsigned int datalen,
+			      void *iv, u32 iv_len);
+extern int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
+				    const u8 *key, unsigned int keylen);
+extern int crypto4xx_encrypt(struct ablkcipher_request *req);
+extern int crypto4xx_decrypt(struct ablkcipher_request *req);
+extern int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm);
+extern int crypto4xx_hash_digest(struct ahash_request *req);
+extern int crypto4xx_hash_final(struct ahash_request *req);
+extern int crypto4xx_hash_update(struct ahash_request *req);
+extern int crypto4xx_hash_init(struct ahash_request *req);
+#endif
diff --git a/drivers/crypto/amcc/crypto4xx_reg_def.h b/drivers/crypto/amcc/crypto4xx_reg_def.h
new file mode 100644
index 0000000..7d4edb0
--- /dev/null
+++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
@@ -0,0 +1,284 @@
+/**
+ * AMCC SoC PPC4xx Crypto Driver
+ *
+ * Copyright (c) 2008 Applied Micro Circuits Corporation.
+ * All rights reserved. James Hsiao <jhsiao@amcc.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.
+ *
+ * This filr defines the register set for Security Subsystem
+ */
+
+#ifndef __CRYPTO4XX_REG_DEF_H__
+#define __CRYPTO4XX_REG_DEF_H__
+
+/* CRYPTO4XX Register offset */
+#define CRYPTO4XX_DESCRIPTOR			0x00000000
+#define CRYPTO4XX_CTRL_STAT			0x00000000
+#define CRYPTO4XX_SOURCE			0x00000004
+#define CRYPTO4XX_DEST				0x00000008
+#define CRYPTO4XX_SA				0x0000000C
+#define CRYPTO4XX_SA_LENGTH			0x00000010
+#define CRYPTO4XX_LENGTH			0x00000014
+
+#define CRYPTO4XX_PE_DMA_CFG			0x00000040
+#define CRYPTO4XX_PE_DMA_STAT			0x00000044
+#define CRYPTO4XX_PDR_BASE			0x00000048
+#define CRYPTO4XX_RDR_BASE			0x0000004c
+#define CRYPTO4XX_RING_SIZE			0x00000050
+#define CRYPTO4XX_RING_CTRL			0x00000054
+#define CRYPTO4XX_INT_RING_STAT			0x00000058
+#define CRYPTO4XX_EXT_RING_STAT			0x0000005c
+#define CRYPTO4XX_IO_THRESHOLD			0x00000060
+#define CRYPTO4XX_GATH_RING_BASE		0x00000064
+#define CRYPTO4XX_SCAT_RING_BASE		0x00000068
+#define CRYPTO4XX_PART_RING_SIZE		0x0000006c
+#define CRYPTO4XX_PART_RING_CFG		        0x00000070
+
+#define CRYPTO4XX_PDR_BASE_UADDR		0x00000080
+#define CRYPTO4XX_RDR_BASE_UADDR		0x00000084
+#define CRYPTO4XX_PKT_SRC_UADDR			0x00000088
+#define CRYPTO4XX_PKT_DEST_UADDR		0x0000008c
+#define CRYPTO4XX_SA_UADDR			0x00000090
+#define CRYPTO4XX_GATH_RING_BASE_UADDR		0x000000A0
+#define CRYPTO4XX_SCAT_RING_BASE_UADDR		0x000000A4
+
+#define CRYPTO4XX_SEQ_RD			0x00000408
+#define CRYPTO4XX_SEQ_MASK_RD			0x0000040C
+
+#define CRYPTO4XX_SA_CMD_0			0x00010600
+#define CRYPTO4XX_SA_CMD_1			0x00010604
+
+#define CRYPTO4XX_STATE_PTR			0x000106dc
+#define CRYPTO4XX_STATE_IV			0x00010700
+#define CRYPTO4XX_STATE_HASH_BYTE_CNT_0		0x00010710
+#define CRYPTO4XX_STATE_HASH_BYTE_CNT_1		0x00010714
+
+#define CRYPTO4XX_STATE_IDIGEST_0		0x00010718
+#define CRYPTO4XX_STATE_IDIGEST_1		0x0001071c
+
+#define CRYPTO4XX_DATA_IN			0x00018000
+#define CRYPTO4XX_DATA_OUT			0x0001c000
+
+#define CRYPTO4XX_INT_UNMASK_STAT		0x000500a0
+#define CRYPTO4XX_INT_MASK_STAT			0x000500a4
+#define CRYPTO4XX_INT_CLR			0x000500a4
+#define CRYPTO4XX_INT_EN			0x000500a8
+
+#define CRYPTO4XX_INT_PKA			0x00000002
+#define CRYPTO4XX_INT_PDR_DONE			0x00008000
+#define CRYPTO4XX_INT_MA_WR_ERR			0x00020000
+#define CRYPTO4XX_INT_MA_RD_ERR			0x00010000
+#define CRYPTO4XX_INT_PE_ERR			0x00000200
+#define CRYPTO4XX_INT_USER_DMA_ERR		0x00000040
+#define CRYPTO4XX_INT_SLAVE_ERR			0x00000010
+#define CRYPTO4XX_INT_MASTER_ERR		0x00000008
+#define CRYPTO4XX_INT_ERROR			0x00030258
+
+#define CRYPTO4XX_INT_CFG			0x000500ac
+#define CRYPTO4XX_INT_DESCR_RD			0x000500b0
+#define CRYPTO4XX_INT_DESCR_CNT			0x000500b4
+#define CRYPTO4XX_INT_TIMEOUT_CNT		0x000500b8
+
+#define CRYPTO4XX_DEVICE_CTRL			0x00060080
+#define CRYPTO4XX_DEVICE_ID			0x00060084
+#define CRYPTO4XX_DEVICE_INFO			0x00060088
+#define CRYPTO4XX_DMA_USER_SRC			0x00060094
+#define CRYPTO4XX_DMA_USER_DEST			0x00060098
+#define CRYPTO4XX_DMA_USER_CMD			0x0006009C
+
+#define CRYPTO4XX_DMA_CFG	        	0x000600d4
+#define CRYPTO4XX_BYTE_ORDER_CFG 		0x000600d8
+#define CRYPTO4XX_ENDIAN_CFG			0x000600d8
+
+#define CRYPTO4XX_PRNG_STAT			0x00070000
+#define CRYPTO4XX_PRNG_CTRL			0x00070004
+#define CRYPTO4XX_PRNG_SEED_L			0x00070008
+#define CRYPTO4XX_PRNG_SEED_H			0x0007000c
+
+#define CRYPTO4XX_PRNG_RES_0			0x00070020
+#define CRYPTO4XX_PRNG_RES_1			0x00070024
+#define CRYPTO4XX_PRNG_RES_2			0x00070028
+#define CRYPTO4XX_PRNG_RES_3			0x0007002C
+
+#define CRYPTO4XX_PRNG_LFSR_L			0x00070030
+#define CRYPTO4XX_PRNG_LFSR_H			0x00070034
+
+/**
+ * Initilize CRYPTO ENGINE registers, and memory bases.
+ */
+#define PPC4XX_PDR_POLL				0x3ff
+#define PPC4XX_OUTPUT_THRESHOLD			2
+#define PPC4XX_INPUT_THRESHOLD			2
+#define PPC4XX_PD_SIZE				6
+#define PPC4XX_CTX_DONE_INT			0x2000
+#define PPC4XX_PD_DONE_INT			0x8000
+#define PPC4XX_BYTE_ORDER			0x22222
+#define PPC4XX_INTERRUPT_CLR			0x3ffff
+#define PPC4XX_PRNG_CTRL_AUTO_EN		0x3
+#define PPC4XX_DC_3DES_EN			1
+#define PPC4XX_INT_DESCR_CNT			4
+#define PPC4XX_INT_TIMEOUT_CNT			0
+#define PPC4XX_INT_CFG				1
+/**
+ * all follow define are ad hoc
+ */
+#define PPC4XX_RING_RETRY			100
+#define PPC4XX_RING_POLL			100
+#define PPC4XX_SDR_SIZE				PPC4XX_NUM_SD
+#define PPC4XX_GDR_SIZE				PPC4XX_NUM_GD
+
+/**
+  * Generic Security Association (SA) with all possible fields. These will
+ * never likely used except for reference purpose. These structure format
+ * can be not changed as the hardware expects them to be layout as defined.
+ * Field can be removed or reduced but ordering can not be changed.
+ */
+#define CRYPTO4XX_DMA_CFG_OFFSET		0x40
+union ce_pe_dma_cfg {
+	struct {
+		u32 rsv:7;
+		u32 dir_host:1;
+		u32 rsv1:2;
+		u32 bo_td_en:1;
+		u32 dis_pdr_upd:1;
+		u32 bo_sgpd_en:1;
+		u32 bo_data_en:1;
+		u32 bo_sa_en:1;
+		u32 bo_pd_en:1;
+		u32 rsv2:4;
+		u32 dynamic_sa_en:1;
+		u32 pdr_mode:2;
+		u32 pe_mode:1;
+		u32 rsv3:5;
+		u32 reset_sg:1;
+		u32 reset_pdr:1;
+		u32 reset_pe:1;
+	} bf;
+    u32 w;
+} __attribute__((packed));
+
+#define CRYPTO4XX_PDR_BASE_OFFSET		0x48
+#define CRYPTO4XX_RDR_BASE_OFFSET		0x4c
+#define CRYPTO4XX_RING_SIZE_OFFSET		0x50
+union ce_ring_size {
+	struct {
+		u32 ring_offset:16;
+		u32 rsv:6;
+		u32 ring_size:10;
+	} bf;
+    u32 w;
+} __attribute__((packed));
+
+#define CRYPTO4XX_RING_CONTROL_OFFSET		0x54
+union ce_ring_contol {
+	struct {
+		u32 continuous:1;
+		u32 rsv:5;
+		u32 ring_retry_divisor:10;
+		u32 rsv1:4;
+		u32 ring_poll_divisor:10;
+	} bf;
+    u32 w;
+} __attribute__((packed));
+
+#define CRYPTO4XX_IO_THRESHOLD_OFFSET		0x60
+union ce_io_threshold {
+	struct {
+		u32 rsv:6;
+		u32 output_threshold:10;
+		u32 rsv1:6;
+		u32 input_threshold:10;
+	} bf;
+    u32 w;
+} __attribute__((packed));
+
+#define CRYPTO4XX_GATHER_RING_BASE_OFFSET	0x64
+#define CRYPTO4XX_SCATTER_RING_BASE_OFFSET	0x68
+
+union ce_part_ring_size  {
+	struct {
+		u32 sdr_size:16;
+		u32 gdr_size:16;
+	} bf;
+    u32 w;
+} __attribute__((packed));
+
+#define MAX_BURST_SIZE_32			0
+#define MAX_BURST_SIZE_64			1
+#define MAX_BURST_SIZE_128			2
+#define MAX_BURST_SIZE_256			3
+
+/* gather descriptor control length */
+struct gd_ctl_len {
+	u32 len:16;
+	u32 rsv:14;
+	u32 done:1;
+	u32 ready:1;
+} __attribute__((packed));
+
+struct ce_gd {
+	u32 ptr;
+	struct gd_ctl_len ctl_len;
+} __attribute__((packed));
+
+struct sd_ctl {
+	u32 ctl:30;
+	u32 done:1;
+	u32 rdy:1;
+} __attribute__((packed));
+
+struct ce_sd {
+    u32 ptr;
+	struct sd_ctl ctl;
+} __attribute__((packed));
+
+#define PD_PAD_CTL_32	0x10
+#define PD_PAD_CTL_64	0x20
+#define PD_PAD_CTL_128	0x40
+#define PD_PAD_CTL_256	0x80
+union ce_pd_ctl {
+	struct {
+		u32 pd_pad_ctl:8;
+		u32 status:8;
+		u32 next_hdr:8;
+		u32 rsv:2;
+		u32 cached_sa:1;
+		u32 hash_final:1;
+		u32 init_arc4:1;
+		u32 rsv1:1;
+		u32 pe_done:1;
+		u32 host_ready:1;
+	} bf;
+	u32 w;
+} __attribute__((packed));
+
+union ce_pd_ctl_len {
+	struct {
+		u32 bypass:8;
+		u32 pe_done:1;
+		u32 host_ready:1;
+		u32 rsv:2;
+		u32 pkt_len:20;
+	} bf;
+	u32 w;
+} __attribute__((packed));
+
+struct ce_pd {
+	union ce_pd_ctl   pd_ctl;
+	u32 src;
+	u32 dest;
+	u32 sa;                 /* get from ctx->sa_dma_addr */
+	u32 sa_len;             /* only if dynamic sa is used */
+	union ce_pd_ctl_len pd_ctl_len;
+
+} __attribute__((packed));
+#endif
diff --git a/drivers/crypto/amcc/crypto4xx_sa.c b/drivers/crypto/amcc/crypto4xx_sa.c
new file mode 100644
index 0000000..466fd94
--- /dev/null
+++ b/drivers/crypto/amcc/crypto4xx_sa.c
@@ -0,0 +1,108 @@
+/**
+ * AMCC SoC PPC4xx Crypto Driver
+ *
+ * Copyright (c) 2008 Applied Micro Circuits Corporation.
+ * All rights reserved. James Hsiao <jhsiao@amcc.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.
+ *
+ * @file crypto4xx_sa.c
+ *
+ * This file implements the security context
+ * assoicate format.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mod_devicetable.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock_types.h>
+#include <linux/highmem.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/des.h>
+#include "crypto4xx_reg_def.h"
+#include "crypto4xx_sa.h"
+#include "crypto4xx_core.h"
+
+u32 get_dynamic_sa_offset_iv_field(struct crypto4xx_ctx *ctx)
+{
+	u32 offset;
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction == DIR_INBOUND)
+		cts.w = ((struct dynamic_sa_ctl *)(ctx->sa_in))->sa_contents;
+	else
+		cts.w = ((struct dynamic_sa_ctl *)(ctx->sa_out))->sa_contents;
+	offset = cts.bf.key_size
+		+ cts.bf.inner_size
+		+ cts.bf.outer_size
+		+ cts.bf.spi
+		+ cts.bf.seq_num0
+		+ cts.bf.seq_num1
+		+ cts.bf.seq_num_mask0
+		+ cts.bf.seq_num_mask1
+		+ cts.bf.seq_num_mask2
+		+ cts.bf.seq_num_mask3;
+
+	return sizeof(struct dynamic_sa_ctl) + offset * 4;
+}
+
+u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx)
+{
+	u32 offset;
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction == DIR_INBOUND)
+		cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents;
+	else
+		cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents;
+	offset = cts.bf.key_size
+		+ cts.bf.inner_size
+		+ cts.bf.outer_size
+		+ cts.bf.spi
+		+ cts.bf.seq_num0
+		+ cts.bf.seq_num1
+		+ cts.bf.seq_num_mask0
+		+ cts.bf.seq_num_mask1
+		+ cts.bf.seq_num_mask2
+		+ cts.bf.seq_num_mask3
+		+ cts.bf.iv0
+		+ cts.bf.iv1
+		+ cts.bf.iv2
+		+ cts.bf.iv3;
+
+	return sizeof(struct dynamic_sa_ctl) + offset * 4;
+}
+
+u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx)
+{
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction == DIR_INBOUND)
+		cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents;
+	else
+		cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents;
+	return (cts.bf.iv0 + cts.bf.iv1 + cts.bf.iv2 + cts.bf.iv3) * 4;
+}
+
+u32 get_dynamic_sa_offset_key_field(struct crypto4xx_ctx *ctx)
+{
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction == DIR_INBOUND)
+		cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents;
+	else
+		cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents;
+
+	return sizeof(struct dynamic_sa_ctl);
+}
diff --git a/drivers/crypto/amcc/crypto4xx_sa.h b/drivers/crypto/amcc/crypto4xx_sa.h
new file mode 100644
index 0000000..4b83ed7
--- /dev/null
+++ b/drivers/crypto/amcc/crypto4xx_sa.h
@@ -0,0 +1,243 @@
+/**
+ * AMCC SoC PPC4xx Crypto Driver
+ *
+ * Copyright (c) 2008 Applied Micro Circuits Corporation.
+ * All rights reserved. James Hsiao <jhsiao@amcc.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.
+ *
+ * This file defines the security context
+ * assoicate format.
+ */
+
+#ifndef __CRYPTO4XX_SA_H__
+#define __CRYPTO4XX_SA_H__
+
+#define AES_IV_SIZE				16
+
+/**
+ * Contents of Dynamic Security Association (SA) with all possible fields
+ */
+union dynamic_sa_contents {
+	struct {
+		u32 arc4_state_ptr:1;
+		u32 arc4_ij_ptr:1;
+		u32 state_ptr:1;
+		u32 iv3:1;
+		u32 iv2:1;
+		u32 iv1:1;
+		u32 iv0:1;
+		u32 seq_num_mask3:1;
+		u32 seq_num_mask2:1;
+		u32 seq_num_mask1:1;
+		u32 seq_num_mask0:1;
+		u32 seq_num1:1;
+		u32 seq_num0:1;
+		u32 spi:1;
+		u32 outer_size:5;
+		u32 inner_size:5;
+		u32 key_size:4;
+		u32 cmd_size:4;
+	} bf;
+	u32 w;
+} __attribute__((packed));
+
+#define DIR_OUTBOUND				0
+#define DIR_INBOUND				1
+#define SA_OP_GROUP_BASIC			0
+#define SA_OPCODE_ENCRYPT			0
+#define SA_OPCODE_DECRYPT			0
+#define SA_OPCODE_HASH				3
+#define SA_CIPHER_ALG_DES			0
+#define SA_CIPHER_ALG_3DES			1
+#define SA_CIPHER_ALG_ARC4			2
+#define SA_CIPHER_ALG_AES			3
+#define SA_CIPHER_ALG_KASUMI			4
+#define SA_CIPHER_ALG_NULL			15
+
+#define SA_HASH_ALG_MD5				0
+#define SA_HASH_ALG_SHA1			1
+#define SA_HASH_ALG_NULL			15
+#define SA_HASH_ALG_SHA1_DIGEST_SIZE		20
+
+#define SA_LOAD_HASH_FROM_SA			0
+#define SA_LOAD_HASH_FROM_STATE			2
+#define SA_NOT_LOAD_HASH			3
+#define SA_LOAD_IV_FROM_SA			0
+#define SA_LOAD_IV_FROM_INPUT			1
+#define SA_LOAD_IV_FROM_STATE			2
+#define SA_LOAD_IV_GEN_IV			3
+
+#define SA_PAD_TYPE_CONSTANT			2
+#define SA_PAD_TYPE_ZERO			3
+#define SA_PAD_TYPE_TLS				5
+#define SA_PAD_TYPE_DTLS			5
+#define SA_NOT_SAVE_HASH			0
+#define SA_SAVE_HASH				1
+#define SA_NOT_SAVE_IV				0
+#define SA_SAVE_IV				1
+#define SA_HEADER_PROC				1
+#define SA_NO_HEADER_PROC			0
+
+union sa_command_0 {
+	struct {
+		u32 scatter:1;
+		u32 gather:1;
+		u32 save_hash_state:1;
+		u32 save_iv:1;
+		u32 load_hash_state:2;
+		u32 load_iv:2;
+		u32 digest_len:4;
+		u32 hdr_proc:1;
+		u32 extend_pad:1;
+		u32 stream_cipher_pad:1;
+		u32 rsv:1;
+		u32 hash_alg:4;
+		u32 cipher_alg:4;
+		u32 pad_type:2;
+		u32 op_group:2;
+		u32 dir:1;
+		u32 opcode:3;
+	} bf;
+	u32 w;
+} __attribute__((packed));
+
+#define CRYPTO_MODE_ECB				0
+#define CRYPTO_MODE_CBC				1
+
+#define CRYPTO_FEEDBACK_MODE_NO_FB		0
+#define CRYPTO_FEEDBACK_MODE_64BIT_OFB		0
+#define CRYPTO_FEEDBACK_MODE_8BIT_CFB		1
+#define CRYPTO_FEEDBACK_MODE_1BIT_CFB		2
+#define CRYPTO_FEEDBACK_MODE_128BIT_CFB		3
+
+#define SA_AES_KEY_LEN_128			2
+#define SA_AES_KEY_LEN_192			3
+#define SA_AES_KEY_LEN_256			4
+
+#define SA_REV2					1
+/**
+ * The follow defines bits sa_command_1
+ * In Basic hash mode  this bit define simple hash or hmac.
+ * In IPsec mode, this bit define muting control.
+ */
+#define SA_HASH_MODE_HASH			0
+#define SA_HASH_MODE_HMAC			1
+#define SA_MC_ENABLE				0
+#define SA_MC_DISABLE				1
+#define SA_NOT_COPY_HDR				0
+#define SA_COPY_HDR				1
+#define SA_NOT_COPY_PAD				0
+#define SA_COPY_PAD				1
+#define SA_NOT_COPY_PAYLOAD			0
+#define SA_COPY_PAYLOAD				1
+#define SA_EXTENDED_SN_OFF			0
+#define SA_EXTENDED_SN_ON			1
+#define SA_SEQ_MASK_OFF				0
+#define SA_SEQ_MASK_ON				1
+
+union sa_command_1 {
+	struct {
+		u32 crypto_mode31:1;
+		u32 save_arc4_state:1;
+		u32 arc4_stateful:1;
+		u32 key_len:5;
+		u32 hash_crypto_offset:8;
+		u32 sa_rev:2;
+		u32 byte_offset:1;
+		u32 hmac_muting:1;
+		u32 feedback_mode:2;
+		u32 crypto_mode9_8:2;
+		u32 extended_seq_num:1;
+		u32 seq_num_mask:1;
+		u32 mutable_bit_proc:1;
+		u32 ip_version:1;
+		u32 copy_pad:1;
+		u32 copy_payload:1;
+		u32 copy_hdr:1;
+		u32 rsv1:1;
+	} bf;
+	u32 w;
+} __attribute__((packed));
+
+struct dynamic_sa_ctl {
+	u32 sa_contents;
+	union sa_command_0 sa_command_0;
+	union sa_command_1 sa_command_1;
+} __attribute__((packed));
+
+/**
+ * State Record for Security Association (SA)
+ */
+struct  sa_state_record {
+	u32 save_iv[4];
+	u32 save_hash_byte_cnt[2];
+	u32 save_digest[16];
+} __attribute__((packed));
+
+/**
+ * Security Association (SA) for AES128
+ *
+ */
+struct dynamic_sa_aes128 {
+	struct dynamic_sa_ctl	ctrl;
+	u32 key[4];
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+
+#define SA_AES128_LEN		(sizeof(struct dynamic_sa_aes128)/4)
+#define SA_AES128_CONTENTS	0x3e000042
+
+/*
+ * Security Association (SA) for AES192
+ */
+struct dynamic_sa_aes192 {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[6];
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+
+#define SA_AES192_LEN		(sizeof(struct dynamic_sa_aes192)/4)
+#define SA_AES192_CONTENTS	0x3e000062
+
+/**
+ * Security Association (SA) for AES256
+ */
+struct dynamic_sa_aes256 {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[8];
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+
+#define SA_AES256_LEN		(sizeof(struct dynamic_sa_aes256)/4)
+#define SA_AES256_CONTENTS	0x3e000082
+#define SA_AES_CONTENTS		0x3e000002
+
+/**
+ * Security Association (SA) for HASH160: HMAC-SHA1
+ */
+struct dynamic_sa_hash160 {
+	struct dynamic_sa_ctl ctrl;
+	u32 inner_digest[5];
+	u32 outer_digest[5];
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_HASH160_LEN		(sizeof(struct dynamic_sa_hash160)/4)
+#define SA_HASH160_CONTENTS     0x2000a502
+
+#endif
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c
index 33bd753..25b743a 100644
--- a/drivers/dca/dca-core.c
+++ b/drivers/dca/dca-core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 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
diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c
index 10c3c49..55dd88d 100644
--- a/drivers/dio/dio.c
+++ b/drivers/dio/dio.c
@@ -182,7 +182,7 @@
 
 	/* Initialize the DIO bus */ 
 	INIT_LIST_HEAD(&dio_bus.devices);
-	strcpy(dio_bus.dev.bus_id, "dio");
+	dev_set_name(&dio_bus.dev, "dio");
 	error = device_register(&dio_bus.dev);
 	if (error) {
 		pr_err("DIO: Error registering dio_bus\n");
@@ -237,7 +237,7 @@
 		dev->scode = scode;
 		dev->resource.start = pa;
 		dev->resource.end = pa + DIO_SIZE(scode, va);
-		sprintf(dev->dev.bus_id,"%02x", scode);
+		dev_set_name(&dev->dev, "%02x", scode);
 
                 /* read the ID byte(s) and encode if necessary. */
 		prid = DIO_ID(va);
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 732fa1e..e190d8b 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -430,13 +430,15 @@
 static void __exit dmatest_exit(void)
 {
 	struct dmatest_chan *dtc, *_dtc;
+	struct dma_chan *chan;
 
 	list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
 		list_del(&dtc->node);
+		chan = dtc->chan;
 		dmatest_cleanup_channel(dtc);
 		pr_debug("dmatest: dropped channel %s\n",
-			 dma_chan_name(dtc->chan));
-		dma_release_channel(dtc->chan);
+			 dma_chan_name(chan));
+		dma_release_channel(chan);
 	}
 }
 module_exit(dmatest_exit);
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index a97c07e..20ad3d2 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -1011,7 +1011,7 @@
 	dma_writel(dw, CFG, DW_CFG_DMA_EN);
 
 	printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
-			pdev->dev.bus_id, dw->dma.chancnt);
+			dev_name(&pdev->dev), dw->dma.chancnt);
 
 	dma_async_device_register(&dw->dma);
 
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 70126a6..86d6da4 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -158,7 +158,8 @@
 
 static void dma_halt(struct fsl_dma_chan *fsl_chan)
 {
-	int i = 0;
+	int i;
+
 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
 		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA,
 		32);
@@ -166,8 +167,11 @@
 		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS
 		| FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32);
 
-	while (!dma_is_idle(fsl_chan) && (i++ < 100))
+	for (i = 0; i < 100; i++) {
+		if (dma_is_idle(fsl_chan))
+			break;
 		udelay(10);
+	}
 	if (i >= 100 && !dma_is_idle(fsl_chan))
 		dev_err(fsl_chan->dev, "DMA halt timeout!\n");
 }
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
index 4105d65..ed83dd9 100644
--- a/drivers/dma/ioat.c
+++ b/drivers/dma/ioat.c
@@ -1,6 +1,6 @@
 /*
  * Intel I/OAT DMA Linux driver
- * Copyright(c) 2007 Intel Corporation.
+ * Copyright(c) 2007 - 2009 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c
index 6cf622d..c012a1e 100644
--- a/drivers/dma/ioat_dca.c
+++ b/drivers/dma/ioat_dca.c
@@ -1,6 +1,6 @@
 /*
  * Intel I/OAT DMA Linux driver
- * Copyright(c) 2007 Intel Corporation.
+ * Copyright(c) 2007 - 2009 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -49,6 +49,23 @@
 
 #define DCA_TAG_MAP_MASK 0xDF
 
+/* expected tag map bytes for I/OAT ver.2 */
+#define DCA2_TAG_MAP_BYTE0 0x80
+#define DCA2_TAG_MAP_BYTE1 0x0
+#define DCA2_TAG_MAP_BYTE2 0x81
+#define DCA2_TAG_MAP_BYTE3 0x82
+#define DCA2_TAG_MAP_BYTE4 0x82
+
+/* verify if tag map matches expected values */
+static inline int dca2_tag_map_valid(u8 *tag_map)
+{
+	return ((tag_map[0] == DCA2_TAG_MAP_BYTE0) &&
+		(tag_map[1] == DCA2_TAG_MAP_BYTE1) &&
+		(tag_map[2] == DCA2_TAG_MAP_BYTE2) &&
+		(tag_map[3] == DCA2_TAG_MAP_BYTE3) &&
+		(tag_map[4] == DCA2_TAG_MAP_BYTE4));
+}
+
 /*
  * "Legacy" DCA systems do not implement the DCA register set in the
  * I/OAT device.  Software needs direct support for their tag mappings.
@@ -452,6 +469,13 @@
 			ioatdca->tag_map[i] = 0;
 	}
 
+	if (!dca2_tag_map_valid(ioatdca->tag_map)) {
+		dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, "
+			"disabling DCA\n");
+		free_dca_provider(dca);
+		return NULL;
+	}
+
 	err = register_dca_provider(dca, &pdev->dev);
 	if (err) {
 		free_dca_provider(dca);
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index b3759c4..5905cd3 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -1,6 +1,6 @@
 /*
  * Intel I/OAT DMA Linux driver
- * Copyright(c) 2004 - 2007 Intel Corporation.
+ * Copyright(c) 2004 - 2009 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -189,11 +189,13 @@
 		ioat_chan->xfercap = xfercap;
 		ioat_chan->desccount = 0;
 		INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2);
-		if (ioat_chan->device->version != IOAT_VER_1_2) {
-			writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE
-					| IOAT_DMA_DCA_ANY_CPU,
-				ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
-		}
+		if (ioat_chan->device->version == IOAT_VER_2_0)
+			writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE |
+			       IOAT_DMA_DCA_ANY_CPU,
+			       ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
+		else if (ioat_chan->device->version == IOAT_VER_3_0)
+			writel(IOAT_DMA_DCA_ANY_CPU,
+			       ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
 		spin_lock_init(&ioat_chan->cleanup_lock);
 		spin_lock_init(&ioat_chan->desc_lock);
 		INIT_LIST_HEAD(&ioat_chan->free_desc);
@@ -1169,9 +1171,8 @@
 				 * up if the client is done with the descriptor
 				 */
 				if (async_tx_test_ack(&desc->async_tx)) {
-					list_del(&desc->node);
-					list_add_tail(&desc->node,
-						      &ioat_chan->free_desc);
+					list_move_tail(&desc->node,
+						       &ioat_chan->free_desc);
 				} else
 					desc->async_tx.cookie = 0;
 			} else {
@@ -1362,6 +1363,7 @@
 	dma_cookie_t cookie;
 	int err = 0;
 	struct completion cmp;
+	unsigned long tmo;
 
 	src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
 	if (!src)
@@ -1413,9 +1415,10 @@
 	}
 	device->common.device_issue_pending(dma_chan);
 
-	wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));
+	tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));
 
-	if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
+	if (tmo == 0 ||
+	    device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
 					!= DMA_SUCCESS) {
 		dev_err(&device->pdev->dev,
 			"Self-test copy timed out, disabling\n");
@@ -1657,6 +1660,13 @@
 		" %d channels, device version 0x%02x, driver version %s\n",
 		device->common.chancnt, device->version, IOAT_DMA_VERSION);
 
+	if (!device->common.chancnt) {
+		dev_err(&device->pdev->dev,
+			"Intel(R) I/OAT DMA Engine problem found: "
+			"zero channels detected\n");
+		goto err_setup_interrupts;
+	}
+
 	err = ioat_dma_setup_interrupts(device);
 	if (err)
 		goto err_setup_interrupts;
@@ -1696,6 +1706,9 @@
 	struct dma_chan *chan, *_chan;
 	struct ioat_dma_chan *ioat_chan;
 
+	if (device->version != IOAT_VER_3_0)
+		cancel_delayed_work(&device->work);
+
 	ioat_dma_remove_interrupts(device);
 
 	dma_async_device_unregister(&device->common);
@@ -1707,10 +1720,6 @@
 	pci_release_regions(device->pdev);
 	pci_disable_device(device->pdev);
 
-	if (device->version != IOAT_VER_3_0) {
-		cancel_delayed_work(&device->work);
-	}
-
 	list_for_each_entry_safe(chan, _chan,
 				 &device->common.channels, device_node) {
 		ioat_chan = to_ioat_chan(chan);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index a3306d0..a52ff4b 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2009 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
@@ -29,7 +29,7 @@
 #include <linux/pci_ids.h>
 #include <net/tcp.h>
 
-#define IOAT_DMA_VERSION  "3.30"
+#define IOAT_DMA_VERSION  "3.64"
 
 enum ioat_interrupt {
 	none = 0,
@@ -135,12 +135,14 @@
 	#ifdef CONFIG_NET_DMA
 	switch (dev->version) {
 	case IOAT_VER_1_2:
-	case IOAT_VER_3_0:
 		sysctl_tcp_dma_copybreak = 4096;
 		break;
 	case IOAT_VER_2_0:
 		sysctl_tcp_dma_copybreak = 2048;
 		break;
+	case IOAT_VER_3_0:
+		sysctl_tcp_dma_copybreak = 262144;
+		break;
 	}
 	#endif
 }
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
index f1ae2c7..afa57ee 100644
--- a/drivers/dma/ioatdma_hw.h
+++ b/drivers/dma/ioatdma_hw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2009 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
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
index 827cb50..49bc277 100644
--- a/drivers/dma/ioatdma_registers.h
+++ b/drivers/dma/ioatdma_registers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2009 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
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 647374a..16adbe6 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -928,19 +928,19 @@
 
 	for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
 		xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
-		if (!xor_srcs[src_idx])
-			while (src_idx--) {
+		if (!xor_srcs[src_idx]) {
+			while (src_idx--)
 				__free_page(xor_srcs[src_idx]);
-				return -ENOMEM;
-			}
+			return -ENOMEM;
+		}
 	}
 
 	dest = alloc_page(GFP_KERNEL);
-	if (!dest)
-		while (src_idx--) {
+	if (!dest) {
+		while (src_idx--)
 			__free_page(xor_srcs[src_idx]);
-			return -ENOMEM;
-		}
+		return -ENOMEM;
+	}
 
 	/* Fill in src buffers */
 	for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index 1f154d0..ae50a9d 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -729,7 +729,7 @@
 
 	ichan->status = IPU_CHANNEL_READY;
 
-	spin_unlock_irqrestore(ipu->lock, flags);
+	spin_unlock_irqrestore(&ipu->lock, flags);
 
 	return 0;
 }
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 5d5d5b3..cb7f26f 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -1019,19 +1019,19 @@
 
 	for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
 		xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
-		if (!xor_srcs[src_idx])
-			while (src_idx--) {
+		if (!xor_srcs[src_idx]) {
+			while (src_idx--)
 				__free_page(xor_srcs[src_idx]);
-				return -ENOMEM;
-			}
+			return -ENOMEM;
+		}
 	}
 
 	dest = alloc_page(GFP_KERNEL);
-	if (!dest)
-		while (src_idx--) {
+	if (!dest) {
+		while (src_idx--)
 			__free_page(xor_srcs[src_idx]);
-			return -ENOMEM;
-		}
+		return -ENOMEM;
+	}
 
 	/* Fill in src buffers */
 	for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index 24f3ca8..cb0f639 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -198,7 +198,7 @@
 	mci->edac_cap = EDAC_FLAG_EC | EDAC_FLAG_SECDED;
 	mci->mod_name = "cell_edac";
 	mci->ctl_name = "MIC";
-	mci->dev_name = pdev->dev.bus_id;
+	mci->dev_name = dev_name(&pdev->dev);
 	mci->edac_check = cell_edac_check;
 	cell_edac_init_csrows(mci);
 
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 853ef37..4637a4a 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -218,7 +218,7 @@
 	pci->dev = &op->dev;
 	pci->mod_name = EDAC_MOD_STR;
 	pci->ctl_name = pdata->name;
-	pci->dev_name = op->dev.bus_id;
+	pci->dev_name = dev_name(&op->dev);
 
 	if (edac_op_state == EDAC_OPSTATE_POLL)
 		pci->edac_check = mpc85xx_pci_check;
diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c
index 083ce8d..5131aaa 100644
--- a/drivers/edac/mv64x60_edac.c
+++ b/drivers/edac/mv64x60_edac.c
@@ -121,7 +121,7 @@
 	pdata->irq = NO_IRQ;
 	platform_set_drvdata(pdev, pci);
 	pci->dev = &pdev->dev;
-	pci->dev_name = pdev->dev.bus_id;
+	pci->dev_name = dev_name(&pdev->dev);
 	pci->mod_name = EDAC_MOD_STR;
 	pci->ctl_name = pdata->name;
 
@@ -294,7 +294,7 @@
 	pdata->irq = NO_IRQ;
 	edac_dev->dev = &pdev->dev;
 	platform_set_drvdata(pdev, edac_dev);
-	edac_dev->dev_name = pdev->dev.bus_id;
+	edac_dev->dev_name = dev_name(&pdev->dev);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
@@ -462,7 +462,7 @@
 	pdata->irq = NO_IRQ;
 	edac_dev->dev = &pdev->dev;
 	platform_set_drvdata(pdev, edac_dev);
-	edac_dev->dev_name = pdev->dev.bus_id;
+	edac_dev->dev_name = dev_name(&pdev->dev);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
@@ -713,7 +713,7 @@
 	platform_set_drvdata(pdev, mci);
 	pdata->name = "mv64x60_mc_err";
 	pdata->irq = NO_IRQ;
-	mci->dev_name = pdev->dev.bus_id;
+	mci->dev_name = dev_name(&pdev->dev);
 	pdata->edac_idx = edac_mc_idx++;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index c950bf8..66958b3 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -200,7 +200,7 @@
 	edev->dev.bus = &eisa_bus_type;
 	edev->dev.dma_mask = &edev->dma_mask;
 	edev->dev.coherent_dma_mask = edev->dma_mask;
-	sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot);
+	dev_set_name(&edev->dev, "%02X:%02X", root->bus_nr, slot);
 
 	for (i = 0; i < EISA_MAX_RESOURCES; i++) {
 #ifdef CONFIG_EISA_NAMES
@@ -301,7 +301,7 @@
 	struct eisa_device *edev;
 
         printk (KERN_INFO "EISA: Probing bus %d at %s\n",
-		root->bus_nr, root->dev->bus_id);
+		root->bus_nr, dev_name(root->dev));
 
 	/* First try to get hold of slot 0. If there is no device
 	 * here, simply fail, unless root->force_probe is set. */
diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/bt8xxgpio.c
index 7a11682..984b587 100644
--- a/drivers/gpio/bt8xxgpio.c
+++ b/drivers/gpio/bt8xxgpio.c
@@ -160,7 +160,7 @@
 {
 	struct gpio_chip *c = &bg->gpio;
 
-	c->label = bg->pdev->dev.bus_id;
+	c->label = dev_name(&bg->pdev->dev);
 	c->owner = THIS_MODULE;
 	c->direction_input = bt8xxgpio_gpio_direction_input;
 	c->get = bt8xxgpio_gpio_get;
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 5aa6780..186d081 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -359,8 +359,8 @@
 	DRM_DEBUG("adding \"%s\" to sysfs\n",
 		  drm_get_connector_name(connector));
 
-	snprintf(connector->kdev.bus_id, BUS_ID_SIZE, "card%d-%s",
-		 dev->primary->index, drm_get_connector_name(connector));
+	dev_set_name(&connector->kdev, "card%d-%s",
+		     dev->primary->index, drm_get_connector_name(connector));
 	ret = device_register(&connector->kdev);
 
 	if (ret) {
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 6dab63b..6d21b9e 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1105,7 +1105,7 @@
 					 1024 * 1024,
 					 MTRR_TYPE_WRCOMB, 1);
 	if (dev_priv->mm.gtt_mtrr < 0) {
-		DRM_INFO("MTRR allocation failed\n.  Graphics "
+		DRM_INFO("MTRR allocation failed.  Graphics "
 			 "performance may suffer.\n");
 	}
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 17fa408..d6cc986 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -279,7 +279,6 @@
 	u8 saveAR_INDEX;
 	u8 saveAR[21];
 	u8 saveDACMASK;
-	u8 saveDACDATA[256*3]; /* 256 3-byte colors */
 	u8 saveCR[37];
 
 	struct {
@@ -457,6 +456,12 @@
 
 	/** for phy allocated objects */
 	struct drm_i915_gem_phys_object *phys_obj;
+
+	/**
+	 * Used for checking the object doesn't appear more than once
+	 * in an execbuffer object list.
+	 */
+	int in_execbuffer;
 };
 
 /**
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 85685bf..37427e4 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1476,7 +1476,7 @@
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	int regnum = obj_priv->fence_reg;
 	int tile_width;
-	uint32_t val;
+	uint32_t fence_reg, val;
 	uint32_t pitch_val;
 
 	if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
@@ -1503,7 +1503,11 @@
 	val |= pitch_val << I830_FENCE_PITCH_SHIFT;
 	val |= I830_FENCE_REG_VALID;
 
-	I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
+	if (regnum < 8)
+		fence_reg = FENCE_REG_830_0 + (regnum * 4);
+	else
+		fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4);
+	I915_WRITE(fence_reg, val);
 }
 
 static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
@@ -1557,7 +1561,8 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	struct drm_i915_fence_reg *reg = NULL;
-	int i, ret;
+	struct drm_i915_gem_object *old_obj_priv = NULL;
+	int i, ret, avail;
 
 	switch (obj_priv->tiling_mode) {
 	case I915_TILING_NONE:
@@ -1580,25 +1585,46 @@
 	}
 
 	/* First try to find a free reg */
+try_again:
+	avail = 0;
 	for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
 		reg = &dev_priv->fence_regs[i];
 		if (!reg->obj)
 			break;
+
+		old_obj_priv = reg->obj->driver_private;
+		if (!old_obj_priv->pin_count)
+		    avail++;
 	}
 
 	/* None available, try to steal one or wait for a user to finish */
 	if (i == dev_priv->num_fence_regs) {
-		struct drm_i915_gem_object *old_obj_priv = NULL;
+		uint32_t seqno = dev_priv->mm.next_gem_seqno;
 		loff_t offset;
 
-try_again:
-		/* Could try to use LRU here instead... */
+		if (avail == 0)
+			return -ENOMEM;
+
 		for (i = dev_priv->fence_reg_start;
 		     i < dev_priv->num_fence_regs; i++) {
+			uint32_t this_seqno;
+
 			reg = &dev_priv->fence_regs[i];
 			old_obj_priv = reg->obj->driver_private;
-			if (!old_obj_priv->pin_count)
+
+			if (old_obj_priv->pin_count)
+				continue;
+
+			/* i915 uses fences for GPU access to tiled buffers */
+			if (IS_I965G(dev) || !old_obj_priv->active)
 				break;
+
+			/* find the seqno of the first available fence */
+			this_seqno = old_obj_priv->last_rendering_seqno;
+			if (this_seqno != 0 &&
+			    reg->obj->write_domain == 0 &&
+			    i915_seqno_passed(seqno, this_seqno))
+				seqno = this_seqno;
 		}
 
 		/*
@@ -1606,15 +1632,25 @@
 		 * objects to finish before trying again.
 		 */
 		if (i == dev_priv->num_fence_regs) {
-			ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0);
-			if (ret) {
-				WARN(ret != -ERESTARTSYS,
-				     "switch to GTT domain failed: %d\n", ret);
-				return ret;
+			if (seqno == dev_priv->mm.next_gem_seqno) {
+				i915_gem_flush(dev,
+					       I915_GEM_GPU_DOMAINS,
+					       I915_GEM_GPU_DOMAINS);
+				seqno = i915_add_request(dev,
+							 I915_GEM_GPU_DOMAINS);
+				if (seqno == 0)
+					return -ENOMEM;
 			}
+
+			ret = i915_wait_request(dev, seqno);
+			if (ret)
+				return ret;
 			goto try_again;
 		}
 
+		BUG_ON(old_obj_priv->active ||
+		       (reg->obj->write_domain & I915_GEM_GPU_DOMAINS));
+
 		/*
 		 * Zap this virtual mapping so we can set up a fence again
 		 * for this object next time we need it.
@@ -1655,8 +1691,17 @@
 
 	if (IS_I965G(dev))
 		I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
-	else
-		I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0);
+	else {
+		uint32_t fence_reg;
+
+		if (obj_priv->fence_reg < 8)
+			fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4;
+		else
+			fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg -
+						       8) * 4;
+
+		I915_WRITE(fence_reg, 0);
+	}
 
 	dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
 	obj_priv->fence_reg = I915_FENCE_REG_NONE;
@@ -2469,6 +2514,7 @@
 	struct drm_i915_gem_exec_object *exec_list = NULL;
 	struct drm_gem_object **object_list = NULL;
 	struct drm_gem_object *batch_obj;
+	struct drm_i915_gem_object *obj_priv;
 	int ret, i, pinned = 0;
 	uint64_t exec_offset;
 	uint32_t seqno, flush_domains;
@@ -2533,6 +2579,15 @@
 			ret = -EBADF;
 			goto err;
 		}
+
+		obj_priv = object_list[i]->driver_private;
+		if (obj_priv->in_execbuffer) {
+			DRM_ERROR("Object %p appears more than once in object list\n",
+				   object_list[i]);
+			ret = -EBADF;
+			goto err;
+		}
+		obj_priv->in_execbuffer = true;
 	}
 
 	/* Pin and relocate */
@@ -2674,8 +2729,13 @@
 	for (i = 0; i < pinned; i++)
 		i915_gem_object_unpin(object_list[i]);
 
-	for (i = 0; i < args->buffer_count; i++)
+	for (i = 0; i < args->buffer_count; i++) {
+		if (object_list[i]) {
+			obj_priv = object_list[i]->driver_private;
+			obj_priv->in_execbuffer = false;
+		}
 		drm_gem_object_unreference(object_list[i]);
+	}
 
 	mutex_unlock(&dev->struct_mutex);
 
@@ -2712,17 +2772,24 @@
 		ret = i915_gem_object_bind_to_gtt(obj, alignment);
 		if (ret != 0) {
 			if (ret != -EBUSY && ret != -ERESTARTSYS)
-				DRM_ERROR("Failure to bind: %d", ret);
+				DRM_ERROR("Failure to bind: %d\n", ret);
 			return ret;
 		}
-		/*
-		 * Pre-965 chips need a fence register set up in order to
-		 * properly handle tiled surfaces.
-		 */
-		if (!IS_I965G(dev) &&
-		    obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-		    obj_priv->tiling_mode != I915_TILING_NONE)
-			i915_gem_object_get_fence_reg(obj, true);
+	}
+	/*
+	 * Pre-965 chips need a fence register set up in order to
+	 * properly handle tiled surfaces.
+	 */
+	if (!IS_I965G(dev) &&
+	    obj_priv->fence_reg == I915_FENCE_REG_NONE &&
+	    obj_priv->tiling_mode != I915_TILING_NONE) {
+		ret = i915_gem_object_get_fence_reg(obj, true);
+		if (ret != 0) {
+			if (ret != -EBUSY && ret != -ERESTARTSYS)
+				DRM_ERROR("Failure to install fence: %d\n",
+					  ret);
+			return ret;
+		}
 	}
 	obj_priv->pin_count++;
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 9d6539a..90600d8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -184,6 +184,7 @@
  * Fence registers
  */
 #define FENCE_REG_830_0			0x2000
+#define FENCE_REG_945_8			0x3000
 #define   I830_FENCE_START_MASK		0x07f80000
 #define   I830_FENCE_TILING_Y_SHIFT	12
 #define   I830_FENCE_SIZE_BITS(size)	((ffs((size) >> 19) - 1) << 8)
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 5d84027..d669cc2 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -119,11 +119,6 @@
 
 	/* VGA color palette registers */
 	dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
-	/* DACCRX automatically increments during read */
-	I915_WRITE8(VGA_DACRX, 0);
-	/* Read 3 bytes of color data from each index */
-	for (i = 0; i < 256 * 3; i++)
-		dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);
 
 	/* MSR bits */
 	dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
@@ -225,12 +220,6 @@
 
 	/* VGA color palette registers */
 	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
-	/* DACCRX automatically increments during read */
-	I915_WRITE8(VGA_DACWX, 0);
-	/* Read 3 bytes of color data from each index */
-	for (i = 0; i < 256 * 3; i++)
-		I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);
-
 }
 
 int i915_save_state(struct drm_device *dev)
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 4940e4d..1f5b5d4 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -306,7 +306,7 @@
 	return 0;
 bail:
 	file->private_data = NULL;
-	kfree(list->hiddev);
+	kfree(list);
 	return res;
 }
 
@@ -323,7 +323,7 @@
  */
 static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
 {
-	DECLARE_WAITQUEUE(wait, current);
+	DEFINE_WAIT(wait);
 	struct hiddev_list *list = file->private_data;
 	int event_size;
 	int retval;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index b84bf06..b4eea02 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -543,8 +543,8 @@
 	help
 	  If you say yes here you get support for National Semiconductor LM90,
 	  LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim
-	  MAX6646, MAX6647, MAX6649, MAX6657, MAX6658, MAX6659, MAX6680 and
-	  MAX6681 sensor chips.
+	  MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
+	  MAX6680, MAX6681 and MAX6692 sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm90.
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index e52b388..ad2b343 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -760,8 +760,11 @@
 
 	for (i = 0; i < offset_count; i++)
 		if ((x = abituguru3_read(data, bank, offset + i, count,
-				buf + i * count)) != count)
-			return i * count + (i && (x < 0)) ? 0 : x;
+				buf + i * count)) != count) {
+			if (x < 0)
+				return x;
+			return i * count + x;
+		}
 
 	return i * count;
 }
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index 1692de3..18a1ba8 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -617,7 +617,7 @@
 static int f75375_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
-	struct f75375_data *data = i2c_get_clientdata(client);
+	struct f75375_data *data;
 	struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
 	int err;
 
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 95a99c5..9157247 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -213,7 +213,7 @@
 
 #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\
 					((val)+500)/1000),-128,127))
-#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000)
+#define TEMP_FROM_REG(val) ((val) * 1000)
 
 #define PWM_TO_REG(val)   ((val) >> 1)
 #define PWM_FROM_REG(val) (((val)&0x7f) << 1)
@@ -267,9 +267,9 @@
 	u8 has_fan;		/* Bitfield, fans enabled */
 	u16 fan[5];		/* Register values, possibly combined */
 	u16 fan_min[5];		/* Register values, possibly combined */
-	u8 temp[3];		/* Register value */
-	u8 temp_high[3];	/* Register value */
-	u8 temp_low[3];		/* Register value */
+	s8 temp[3];		/* Register value */
+	s8 temp_high[3];	/* Register value */
+	s8 temp_low[3];		/* Register value */
 	u8 sensor;		/* Register value */
 	u8 fan_div[3];		/* Register encoding, shifted right */
 	u8 vid;			/* Register encoding, combined */
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index cfc1ee9..b251d86 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -72,6 +72,7 @@
 #define	LM85_COMPANY_SMSC		0x5c
 #define	LM85_VERSTEP_VMASK              0xf0
 #define	LM85_VERSTEP_GENERIC		0x60
+#define	LM85_VERSTEP_GENERIC2		0x70
 #define	LM85_VERSTEP_LM85C		0x60
 #define	LM85_VERSTEP_LM85B		0x62
 #define	LM85_VERSTEP_ADM1027		0x60
@@ -334,6 +335,7 @@
 static const struct i2c_device_id lm85_id[] = {
 	{ "adm1027", adm1027 },
 	{ "adt7463", adt7463 },
+	{ "adt7468", adt7468 },
 	{ "lm85", any_chip },
 	{ "lm85b", lm85b },
 	{ "lm85c", lm85c },
@@ -408,7 +410,8 @@
 	struct lm85_data *data = lm85_update_device(dev);
 	int vid;
 
-	if (data->type == adt7463 && (data->vid & 0x80)) {
+	if ((data->type == adt7463 || data->type == adt7468) &&
+	    (data->vid & 0x80)) {
 		/* 6-pin VID (VRM 10) */
 		vid = vid_from_reg(data->vid & 0x3f, data->vrm);
 	} else {
@@ -1153,7 +1156,8 @@
 			address, company, verstep);
 
 		/* All supported chips have the version in common */
-		if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC) {
+		if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC &&
+		    (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) {
 			dev_dbg(&adapter->dev, "Autodetection failed: "
 				"unsupported version\n");
 			return -ENODEV;
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 96a7018..1aff757 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -32,10 +32,10 @@
  * supported by this driver. These chips lack the remote temperature
  * offset feature.
  *
- * This driver also supports the MAX6646, MAX6647 and MAX6649 chips
- * made by Maxim.  These are again similar to the LM86, but they use
- * unsigned temperature values and can report temperatures from 0 to
- * 145 degrees.
+ * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and
+ * MAX6692 chips made by Maxim.  These are again similar to the LM86,
+ * but they use unsigned temperature values and can report temperatures
+ * from 0 to 145 degrees.
  *
  * This driver also supports the MAX6680 and MAX6681, two other sensor
  * chips made by Maxim. These are quite similar to the other Maxim
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index e7d9848..fbb9030 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -841,7 +841,7 @@
 
 	if (client->driver && !is_newstyle_driver(client->driver)) {
 		client->dev.release = i2c_client_release;
-		client->dev.uevent_suppress = 1;
+		dev_set_uevent_suppress(&client->dev, 1);
 	} else
 		client->dev.release = i2c_client_dev_release;
 
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index e072903..640c992 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -56,8 +56,12 @@
 
 comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
 
+config IDE_XFER_MODE
+	bool
+
 config IDE_TIMINGS
 	bool
+	select IDE_XFER_MODE
 
 config IDE_ATAPI
 	bool
@@ -698,6 +702,7 @@
 config BLK_DEV_IDE_AU1XXX
        bool "IDE for AMD Alchemy Au1200"
        depends on SOC_AU1200
+       select IDE_XFER_MODE
 choice
        prompt "IDE Mode for AMD Alchemy Au1200"
        default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
@@ -721,6 +726,11 @@
 	depends on SOC_TX4939
 	select BLK_DEV_IDEDMA_SFF
 
+config BLK_DEV_IDE_AT91
+	tristate "Atmel AT91 (SAM9, CAP9, AT572D940HF) IDE support"
+	depends on ARM && ARCH_AT91 && !ARCH_AT91RM9200 && !ARCH_AT91X40
+	select IDE_TIMINGS
+
 config IDE_ARM
 	tristate "ARM IDE support"
 	depends on ARM && (ARCH_RPC || ARCH_SHARK)
@@ -866,6 +876,7 @@
 
 config BLK_DEV_DTC2278
 	tristate "DTC-2278 support"
+	select IDE_XFER_MODE
 	select IDE_LEGACY
 	help
 	  This driver is enabled at runtime using the "dtc2278.probe" kernel
@@ -897,6 +908,7 @@
 
 config BLK_DEV_UMC8672
 	tristate "UMC-8672 support"
+	select IDE_XFER_MODE
 	select IDE_LEGACY
 	help
 	  This driver is enabled at runtime using the "umc8672.probe" kernel
@@ -910,5 +922,6 @@
 config BLK_DEV_IDEDMA
 	def_bool BLK_DEV_IDEDMA_SFF || \
 		 BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+	select IDE_XFER_MODE
 
 endif # IDE
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index d0e3d7d..9b4bbe1 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -5,9 +5,11 @@
 EXTRA_CFLAGS				+= -Idrivers/ide
 
 ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
-	      ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o ide-sysfs.o
+	      ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \
+	      ide-io-std.o ide-eh.o
 
 # core IDE code
+ide-core-$(CONFIG_IDE_XFER_MODE)	+= ide-pio-blacklist.o ide-xfer-mode.o
 ide-core-$(CONFIG_IDE_TIMINGS)		+= ide-timings.o
 ide-core-$(CONFIG_IDE_ATAPI)		+= ide-atapi.o
 ide-core-$(CONFIG_BLK_DEV_IDEPCI)	+= setup-pci.o
@@ -116,3 +118,4 @@
 
 obj-$(CONFIG_BLK_DEV_IDE_TX4938)	+= tx4938ide.o
 obj-$(CONFIG_BLK_DEV_IDE_TX4939)	+= tx4939ide.o
+obj-$(CONFIG_BLK_DEV_IDE_AT91)		+= at91_ide.o
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
index 4485b9c..878f8ec 100644
--- a/drivers/ide/aec62xx.c
+++ b/drivers/ide/aec62xx.c
@@ -139,7 +139,7 @@
 	drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
 }
 
-static unsigned int init_chipset_aec62xx(struct pci_dev *dev)
+static int init_chipset_aec62xx(struct pci_dev *dev)
 {
 	/* These are necessary to get AEC6280 Macintosh cards to work */
 	if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
@@ -156,7 +156,7 @@
 		pci_write_config_byte(dev, 0x4a, reg4ah | 0x80);
 	}
 
-	return dev->irq;
+	return 0;
 }
 
 static u8 atp86x_cable_detect(ide_hwif_t *hwif)
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index 66f4308..d3513b6 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -212,7 +212,7 @@
  *	appropriate also sets up the 1533 southbridge.
  */
 
-static unsigned int init_chipset_ali15x3(struct pci_dev *dev)
+static int init_chipset_ali15x3(struct pci_dev *dev)
 {
 	unsigned long flags;
 	u8 tmpbyte;
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index 77267c8..628cd2e 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -140,7 +140,7 @@
  * The initialization callback.  Initialize drive independent registers.
  */
 
-static unsigned int init_chipset_amd74xx(struct pci_dev *dev)
+static int init_chipset_amd74xx(struct pci_dev *dev)
 {
 	u8 t = 0, offset = amd_offset(dev);
 
@@ -172,7 +172,7 @@
 		t |= 0xf0;
 	pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
 
-	return dev->irq;
+	return 0;
 }
 
 static u8 amd_cable_detect(ide_hwif_t *hwif)
@@ -183,14 +183,6 @@
 		return ATA_CBL_PATA40;
 }
 
-static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
-{
-	struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-	if (hwif->irq == 0) /* 0 is bogus but will do for now */
-		hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
-}
-
 static const struct ide_port_ops amd_port_ops = {
 	.set_pio_mode		= amd_set_pio_mode,
 	.set_dma_mode		= amd_set_drive,
@@ -207,7 +199,6 @@
 	{								\
 		.name		= DRV_NAME,				\
 		.init_chipset	= init_chipset_amd74xx,			\
-		.init_hwif	= init_hwif_amd74xx,			\
 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},	\
 		.port_ops	= &amd_port_ops,			\
 		.host_flags	= IDE_HFLAGS_AMD,			\
@@ -221,7 +212,6 @@
 	{								\
 		.name		= DRV_NAME,				\
 		.init_chipset	= init_chipset_amd74xx,			\
-		.init_hwif	= init_hwif_amd74xx,			\
 		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},	\
 		.port_ops	= &amd_port_ops,			\
 		.host_flags	= IDE_HFLAGS_AMD,			\
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c
new file mode 100644
index 0000000..1bb50f4
--- /dev/null
+++ b/drivers/ide/at91_ide.c
@@ -0,0 +1,467 @@
+/*
+ * IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller
+ * with Compact Flash True IDE logic
+ *
+ * Copyright (c) 2008, 2009 Kelvatek 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/ide.h>
+#include <linux/platform_device.h>
+
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/at91sam9263.h>
+#include <mach/at91sam9_smc.h>
+#include <mach/at91sam9263_matrix.h>
+
+#define DRV_NAME "at91_ide"
+
+#define perr(fmt, args...) pr_err(DRV_NAME ": " fmt, ##args)
+#define pdbg(fmt, args...) pr_debug("%s " fmt, __func__, ##args)
+
+/*
+ * Access to IDE device is possible through EBI Static Memory Controller
+ * with Compact Flash logic. For details see EBI and SMC datasheet sections
+ * of any microcontroller from AT91SAM9 family.
+ *
+ * Within SMC chip select address space, lines A[23:21] distinguish Compact
+ * Flash modes (I/O, common memory, attribute memory, True IDE). IDE modes are:
+ *   0x00c0000 - True IDE
+ *   0x00e0000 - Alternate True IDE (Alt Status Register)
+ *
+ * On True IDE mode Task File and Data Register are mapped at the same address.
+ * To distinguish access between these two different bus data width is used:
+ * 8Bit for Task File, 16Bit for Data I/O.
+ *
+ * After initialization we do 8/16 bit flipping (changes in SMC MODE register)
+ * only inside IDE callback routines which are serialized by IDE layer,
+ * so no additional locking needed.
+ */
+
+#define TASK_FILE	0x00c00000
+#define ALT_MODE	0x00e00000
+#define REGS_SIZE	8
+
+#define enter_16bit(cs, mode) do {					\
+	mode = at91_sys_read(AT91_SMC_MODE(cs));			\
+	at91_sys_write(AT91_SMC_MODE(cs), mode | AT91_SMC_DBW_16);	\
+} while (0)
+
+#define leave_16bit(cs, mode) at91_sys_write(AT91_SMC_MODE(cs), mode);
+
+static void set_smc_timings(const u8 chipselect, const u16 cycle,
+			    const u16 setup, const u16 pulse,
+			    const u16 data_float, int use_iordy)
+{
+	unsigned long mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
+			     AT91_SMC_BAT_SELECT;
+
+	/* disable or enable waiting for IORDY signal */
+	if (use_iordy)
+		mode |= AT91_SMC_EXNWMODE_READY;
+
+	/* add data float cycles if needed */
+	if (data_float)
+		mode |= AT91_SMC_TDF_(data_float);
+
+	at91_sys_write(AT91_SMC_MODE(chipselect), mode);
+
+	/* setup timings in SMC */
+	at91_sys_write(AT91_SMC_SETUP(chipselect), AT91_SMC_NWESETUP_(setup) |
+						   AT91_SMC_NCS_WRSETUP_(0) |
+						   AT91_SMC_NRDSETUP_(setup) |
+						   AT91_SMC_NCS_RDSETUP_(0));
+	at91_sys_write(AT91_SMC_PULSE(chipselect), AT91_SMC_NWEPULSE_(pulse) |
+						   AT91_SMC_NCS_WRPULSE_(cycle) |
+						   AT91_SMC_NRDPULSE_(pulse) |
+						   AT91_SMC_NCS_RDPULSE_(cycle));
+	at91_sys_write(AT91_SMC_CYCLE(chipselect), AT91_SMC_NWECYCLE_(cycle) |
+						   AT91_SMC_NRDCYCLE_(cycle));
+}
+
+static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz)
+{
+	u64 tmp = ns;
+
+	tmp *= mck_hz;
+	tmp += 1000*1000*1000 - 1; /* round up */
+	do_div(tmp, 1000*1000*1000);
+	return (unsigned int) tmp;
+}
+
+static void apply_timings(const u8 chipselect, const u8 pio,
+			  const struct ide_timing *timing, int use_iordy)
+{
+	unsigned int t0, t1, t2, t6z;
+	unsigned int cycle, setup, pulse, data_float;
+	unsigned int mck_hz;
+	struct clk *mck;
+
+	/* see table 22 of Compact Flash standard 4.1 for the meaning,
+	 * we do not stretch active (t2) time, so setup (t1) + hold time (th)
+	 * assure at least minimal recovery (t2i) time */
+	t0 = timing->cyc8b;
+	t1 = timing->setup;
+	t2 = timing->act8b;
+	t6z = (pio < 5) ? 30 : 20;
+
+	pdbg("t0=%u t1=%u t2=%u t6z=%u\n", t0, t1, t2, t6z);
+
+	mck = clk_get(NULL, "mck");
+	BUG_ON(IS_ERR(mck));
+	mck_hz = clk_get_rate(mck);
+	pdbg("mck_hz=%u\n", mck_hz);
+
+	cycle = calc_mck_cycles(t0, mck_hz);
+	setup = calc_mck_cycles(t1, mck_hz);
+	pulse = calc_mck_cycles(t2, mck_hz);
+	data_float = calc_mck_cycles(t6z, mck_hz);
+
+	pdbg("cycle=%u setup=%u pulse=%u data_float=%u\n",
+	     cycle, setup, pulse, data_float);
+
+	set_smc_timings(chipselect, cycle, setup, pulse, data_float, use_iordy);
+}
+
+static void at91_ide_input_data(ide_drive_t *drive, struct request *rq,
+				void *buf, unsigned int len)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+	u8 chipselect = hwif->select_data;
+	unsigned long mode;
+
+	pdbg("cs %u buf %p len %d\n", chipselect, buf, len);
+
+	len++;
+
+	enter_16bit(chipselect, mode);
+	__ide_mm_insw((void __iomem *) io_ports->data_addr, buf, len / 2);
+	leave_16bit(chipselect, mode);
+}
+
+static void at91_ide_output_data(ide_drive_t *drive, struct request *rq,
+				 void *buf, unsigned int len)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+	u8 chipselect = hwif->select_data;
+	unsigned long mode;
+
+	pdbg("cs %u buf %p len %d\n", chipselect,  buf, len);
+
+	enter_16bit(chipselect, mode);
+	__ide_mm_outsw((void __iomem *) io_ports->data_addr, buf, len / 2);
+	leave_16bit(chipselect, mode);
+}
+
+static u8 ide_mm_inb(unsigned long port)
+{
+	return readb((void __iomem *) port);
+}
+
+static void ide_mm_outb(u8 value, unsigned long port)
+{
+	writeb(value, (void __iomem *) port);
+}
+
+static void at91_ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+	struct ide_taskfile *tf = &task->tf;
+	u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+
+	if (task->tf_flags & IDE_TFLAG_FLAGGED)
+		HIHI = 0xFF;
+
+	if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+		u16 data = (tf->hob_data << 8) | tf->data;
+
+		at91_ide_output_data(drive, NULL, &data, 2);
+	}
+
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+		ide_mm_outb(tf->hob_feature, io_ports->feature_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+		ide_mm_outb(tf->hob_nsect, io_ports->nsect_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+		ide_mm_outb(tf->hob_lbal, io_ports->lbal_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+		ide_mm_outb(tf->hob_lbam, io_ports->lbam_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+		ide_mm_outb(tf->hob_lbah, io_ports->lbah_addr);
+
+	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+		ide_mm_outb(tf->feature, io_ports->feature_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+		ide_mm_outb(tf->nsect, io_ports->nsect_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+		ide_mm_outb(tf->lbal, io_ports->lbal_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+		ide_mm_outb(tf->lbam, io_ports->lbam_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+		ide_mm_outb(tf->lbah, io_ports->lbah_addr);
+
+	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+		ide_mm_outb((tf->device & HIHI) | drive->select, io_ports->device_addr);
+}
+
+static void at91_ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+	struct ide_taskfile *tf = &task->tf;
+
+	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+		u16 data;
+
+		at91_ide_input_data(drive, NULL, &data, 2);
+		tf->data = data & 0xff;
+		tf->hob_data = (data >> 8) & 0xff;
+	}
+
+	/* be sure we're looking at the low order bits */
+	ide_mm_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+		tf->feature = ide_mm_inb(io_ports->feature_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+		tf->nsect  = ide_mm_inb(io_ports->nsect_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+		tf->lbal   = ide_mm_inb(io_ports->lbal_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+		tf->lbam   = ide_mm_inb(io_ports->lbam_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+		tf->lbah   = ide_mm_inb(io_ports->lbah_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+		tf->device = ide_mm_inb(io_ports->device_addr);
+
+	if (task->tf_flags & IDE_TFLAG_LBA48) {
+		ide_mm_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+			tf->hob_feature = ide_mm_inb(io_ports->feature_addr);
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+			tf->hob_nsect   = ide_mm_inb(io_ports->nsect_addr);
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+			tf->hob_lbal    = ide_mm_inb(io_ports->lbal_addr);
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+			tf->hob_lbam    = ide_mm_inb(io_ports->lbam_addr);
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+			tf->hob_lbah    = ide_mm_inb(io_ports->lbah_addr);
+	}
+}
+
+static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+	struct ide_timing *timing;
+	u8 chipselect = drive->hwif->select_data;
+	int use_iordy = 0;
+
+	pdbg("chipselect %u pio %u\n", chipselect, pio);
+
+	timing = ide_timing_find_mode(XFER_PIO_0 + pio);
+	BUG_ON(!timing);
+
+	if ((pio > 2 || ata_id_has_iordy(drive->id)) &&
+	    !(ata_id_is_cfa(drive->id) && pio > 4))
+		use_iordy = 1;
+
+	apply_timings(chipselect, pio, timing, use_iordy);
+}
+
+static const struct ide_tp_ops at91_ide_tp_ops = {
+	.exec_command	= ide_exec_command,
+	.read_status	= ide_read_status,
+	.read_altstatus	= ide_read_altstatus,
+	.set_irq	= ide_set_irq,
+
+	.tf_load	= at91_ide_tf_load,
+	.tf_read	= at91_ide_tf_read,
+
+	.input_data	= at91_ide_input_data,
+	.output_data	= at91_ide_output_data,
+};
+
+static const struct ide_port_ops at91_ide_port_ops = {
+	.set_pio_mode	= at91_ide_set_pio_mode,
+};
+
+static const struct ide_port_info at91_ide_port_info __initdata = {
+	.port_ops	= &at91_ide_port_ops,
+	.tp_ops		= &at91_ide_tp_ops,
+	.host_flags 	= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE |
+			  IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS,
+	.pio_mask 	= ATA_PIO5,
+};
+
+/*
+ * If interrupt is delivered through GPIO, IRQ are triggered on falling
+ * and rising edge of signal. Whereas IDE device request interrupt on high
+ * level (rising edge in our case). This mean we have fake interrupts, so
+ * we need to check interrupt pin and exit instantly from ISR when line
+ * is on low level.
+ */
+
+irqreturn_t at91_irq_handler(int irq, void *dev_id)
+{
+	int ntries = 8;
+	int pin_val1, pin_val2;
+
+	/* additional deglitch, line can be noisy in badly designed PCB */
+	do {
+		pin_val1 = at91_get_gpio_value(irq);
+		pin_val2 = at91_get_gpio_value(irq);
+	} while (pin_val1 != pin_val2 && --ntries > 0);
+
+	if (pin_val1 == 0 || ntries <= 0)
+		return IRQ_HANDLED;
+
+	return ide_intr(irq, dev_id);
+}
+
+static int __init at91_ide_probe(struct platform_device *pdev)
+{
+	int ret;
+	hw_regs_t hw;
+	hw_regs_t *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_host *host;
+	struct resource *res;
+	unsigned long tf_base = 0, ctl_base = 0;
+	struct at91_cf_data *board = pdev->dev.platform_data;
+
+	if (!board)
+		return -ENODEV;
+
+	if (board->det_pin && at91_get_gpio_value(board->det_pin) != 0) {
+		perr("no device detected\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		perr("can't get memory resource\n");
+		return -ENODEV;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, res->start + TASK_FILE,
+				     REGS_SIZE, "ide") ||
+	    !devm_request_mem_region(&pdev->dev, res->start + ALT_MODE,
+				     REGS_SIZE, "alt")) {
+		perr("memory resources in use\n");
+		return -EBUSY;
+	}
+
+	pdbg("chipselect %u irq %u res %08lx\n", board->chipselect,
+	     board->irq_pin, (unsigned long) res->start);
+
+	tf_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + TASK_FILE,
+					       REGS_SIZE);
+	ctl_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + ALT_MODE,
+						REGS_SIZE);
+	if (!tf_base || !ctl_base) {
+		perr("can't map memory regions\n");
+		return -EBUSY;
+	}
+
+	memset(&hw, 0, sizeof(hw));
+
+	if (board->flags & AT91_IDE_SWAP_A0_A2) {
+		/* workaround for stupid hardware bug */
+		hw.io_ports.data_addr	= tf_base + 0;
+		hw.io_ports.error_addr	= tf_base + 4;
+		hw.io_ports.nsect_addr	= tf_base + 2;
+		hw.io_ports.lbal_addr	= tf_base + 6;
+		hw.io_ports.lbam_addr	= tf_base + 1;
+		hw.io_ports.lbah_addr	= tf_base + 5;
+		hw.io_ports.device_addr = tf_base + 3;
+		hw.io_ports.command_addr = tf_base + 7;
+		hw.io_ports.ctl_addr	= ctl_base + 3;
+	} else
+		ide_std_init_ports(&hw, tf_base, ctl_base + 6);
+
+	hw.irq = board->irq_pin;
+	hw.chipset = ide_generic;
+	hw.dev = &pdev->dev;
+
+	host = ide_host_alloc(&at91_ide_port_info, hws);
+	if (!host) {
+		perr("failed to allocate ide host\n");
+		return -ENOMEM;
+	}
+
+	/* setup Static Memory Controller - PIO 0 as default */
+	apply_timings(board->chipselect, 0, ide_timing_find_mode(XFER_PIO_0), 0);
+
+	/* with GPIO interrupt we have to do quirks in handler */
+	if (board->irq_pin >= PIN_BASE)
+		host->irq_handler = at91_irq_handler;
+
+	host->ports[0]->select_data = board->chipselect;
+
+	ret = ide_host_register(host, &at91_ide_port_info, hws);
+	if (ret) {
+		perr("failed to register ide host\n");
+		goto err_free_host;
+	}
+	platform_set_drvdata(pdev, host);
+	return 0;
+
+err_free_host:
+	ide_host_free(host);
+	return ret;
+}
+
+static int __exit at91_ide_remove(struct platform_device *pdev)
+{
+	struct ide_host *host = platform_get_drvdata(pdev);
+
+	ide_host_remove(host);
+	return 0;
+}
+
+static struct platform_driver at91_ide_driver = {
+	.driver	= {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.remove	= __exit_p(at91_ide_remove),
+};
+
+static int __init at91_ide_init(void)
+{
+	return platform_driver_probe(&at91_ide_driver, at91_ide_probe);
+}
+
+static void __exit at91_ide_exit(void)
+{
+	platform_driver_unregister(&at91_ide_driver);
+}
+
+module_init(at91_ide_init);
+module_exit(at91_ide_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stanislaw Gruszka <stf_xl@wp.pl>");
+
diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c
index ecd1e62..923cbfe 100644
--- a/drivers/ide/atiixp.c
+++ b/drivers/ide/atiixp.c
@@ -142,7 +142,6 @@
 		.name		= DRV_NAME,
 		.enablebits	= {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
 		.port_ops	= &atiixp_port_ops,
-		.host_flags	= IDE_HFLAG_LEGACY_IRQS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
@@ -151,7 +150,7 @@
 		.name		= DRV_NAME,
 		.enablebits	= {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
 		.port_ops	= &atiixp_port_ops,
-		.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
+		.host_flags	= IDE_HFLAG_SINGLE,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c
index 79a2dfe..154ec2c 100644
--- a/drivers/ide/au1xxx-ide.c
+++ b/drivers/ide/au1xxx-ide.c
@@ -536,9 +536,8 @@
 #endif
 };
 
-static int au_ide_probe(struct device *dev)
+static int au_ide_probe(struct platform_device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
 	_auide_hwif *ahwif = &auide_hwif;
 	struct resource *res;
 	struct ide_host *host;
@@ -552,23 +551,23 @@
 #endif
 
 	memset(&auide_hwif, 0, sizeof(_auide_hwif));
-	ahwif->irq = platform_get_irq(pdev, 0);
+	ahwif->irq = platform_get_irq(dev, 0);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 
 	if (res == NULL) {
-		pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id);
+		pr_debug("%s %d: no base address\n", DRV_NAME, dev->id);
 		ret = -ENODEV;
 		goto out;
 	}
 	if (ahwif->irq < 0) {
-		pr_debug("%s %d: no IRQ\n", DRV_NAME, pdev->id);
+		pr_debug("%s %d: no IRQ\n", DRV_NAME, dev->id);
 		ret = -ENODEV;
 		goto out;
 	}
 
 	if (!request_mem_region(res->start, res->end - res->start + 1,
-				pdev->name)) {
+				dev->name)) {
 		pr_debug("%s: request_mem_region failed\n", DRV_NAME);
 		ret =  -EBUSY;
 		goto out;
@@ -583,7 +582,7 @@
 	memset(&hw, 0, sizeof(hw));
 	auide_setup_ports(&hw, ahwif);
 	hw.irq = ahwif->irq;
-	hw.dev = dev;
+	hw.dev = &dev->dev;
 	hw.chipset = ide_au1xxx;
 
 	ret = ide_host_add(&au1xxx_port_info, hws, &host);
@@ -592,7 +591,7 @@
 
 	auide_hwif.hwif = host->ports[0];
 
-	dev_set_drvdata(dev, host);
+	platform_set_drvdata(dev, host);
 
 	printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode );
 
@@ -600,38 +599,39 @@
 	return ret;
 }
 
-static int au_ide_remove(struct device *dev)
+static int au_ide_remove(struct platform_device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
 	struct resource *res;
-	struct ide_host *host = dev_get_drvdata(dev);
+	struct ide_host *host = platform_get_drvdata(dev);
 	_auide_hwif *ahwif = &auide_hwif;
 
 	ide_host_remove(host);
 
 	iounmap((void *)ahwif->regbase);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, res->end - res->start + 1);
 
 	return 0;
 }
 
-static struct device_driver au1200_ide_driver = {
-	.name		= "au1200-ide",
-	.bus		= &platform_bus_type,
+static struct platform_driver au1200_ide_driver = {
+	.driver = {
+		.name		= "au1200-ide",
+		.owner		= THIS_MODULE,
+	},
 	.probe 		= au_ide_probe,
 	.remove		= au_ide_remove,
 };
 
 static int __init au_ide_init(void)
 {
-	return driver_register(&au1200_ide_driver);
+	return platform_driver_register(&au1200_ide_driver);
 }
 
 static void __exit au_ide_exit(void)
 {
-	driver_unregister(&au1200_ide_driver);
+	platform_driver_unregister(&au1200_ide_driver);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 2f9688d..aeee036 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -333,7 +333,7 @@
 	return (dma_stat & 7) != 4;
 }
 
-static unsigned int init_chipset_cmd64x(struct pci_dev *dev)
+static int init_chipset_cmd64x(struct pci_dev *dev)
 {
 	u8 mrdmode = 0;
 
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c
index d003bec..58fb90e 100644
--- a/drivers/ide/cs5520.c
+++ b/drivers/ide/cs5520.c
@@ -133,7 +133,8 @@
 	 *	do all the device setup for us
 	 */
 
-	ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]);
+	ide_pci_setup_ports(dev, d, &hw[0], &hws[0]);
+	hw[0].irq = 14;
 
 	return ide_host_add(d, hws, NULL);
 }
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
index d8ede85..8e8b35a 100644
--- a/drivers/ide/cs5530.c
+++ b/drivers/ide/cs5530.c
@@ -135,7 +135,7 @@
  *	Initialize the cs5530 bridge for reliable IDE DMA operation.
  */
 
-static unsigned int init_chipset_cs5530(struct pci_dev *dev)
+static int init_chipset_cs5530(struct pci_dev *dev)
 {
 	struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
 
diff --git a/drivers/ide/delkin_cb.c b/drivers/ide/delkin_cb.c
index 8f1b2d9..bacb119 100644
--- a/drivers/ide/delkin_cb.c
+++ b/drivers/ide/delkin_cb.c
@@ -46,7 +46,7 @@
 	.quirkproc		= ide_undecoded_slave,
 };
 
-static unsigned int delkin_cb_init_chipset(struct pci_dev *dev)
+static int delkin_cb_init_chipset(struct pci_dev *dev)
 {
 	unsigned long base = pci_resource_start(dev, 0);
 	int i;
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 3eb9b5c..d3b3e82 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -995,7 +995,7 @@
 		pci_write_config_byte(dev, mcr_addr + 1, new_mcr);
 }
 
-static unsigned int init_chipset_hpt366(struct pci_dev *dev)
+static int init_chipset_hpt366(struct pci_dev *dev)
 {
 	unsigned long io_base	= pci_resource_start(dev, 4);
 	struct hpt_info *info	= hpt3xx_get_info(&dev->dev);
@@ -1237,7 +1237,7 @@
 	hpt3xx_disable_fast_irq(dev, 0x50);
 	hpt3xx_disable_fast_irq(dev, 0x54);
 
-	return dev->irq;
+	return 0;
 }
 
 static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index ec7d07f..5b704f1 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -20,9 +20,6 @@
 #include <acpi/acpi_bus.h>
 
 #define REGS_PER_GTF		7
-struct taskfile_array {
-	u8	tfa[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
-};
 
 struct GTM_buffer {
 	u32	PIO_speed0;
@@ -89,12 +86,8 @@
 	{ }	/* terminate list */
 };
 
-static int ide_acpi_blacklist(void)
+int ide_acpi_init(void)
 {
-	static int done;
-	if (done)
-		return 0;
-	done = 1;
 	dmi_check_system(ide_acpi_dmi_table);
 	return 0;
 }
@@ -202,40 +195,6 @@
 }
 
 /**
- * ide_acpi_drive_get_handle - Get ACPI object handle for a given drive
- * @drive: device to locate
- *
- * Retrieves the object handle of a given drive. According to the ACPI
- * spec the drive is a child of the hwif.
- *
- * Returns handle on success, 0 on error.
- */
-static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive)
-{
-	ide_hwif_t	*hwif = drive->hwif;
-	int		 port;
-	acpi_handle	 drive_handle;
-
-	if (!hwif->acpidata)
-		return NULL;
-
-	if (!hwif->acpidata->obj_handle)
-		return NULL;
-
-	port = hwif->channel ? drive->dn - 2: drive->dn;
-
-	DEBPRINT("ENTER: %s at channel#: %d port#: %d\n",
-		 drive->name, hwif->channel, port);
-
-
-	/* TBD: could also check ACPI object VALID bits */
-	drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port);
-	DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle);
-
-	return drive_handle;
-}
-
-/**
  * do_drive_get_GTF - get the drive bootup default taskfile settings
  * @drive: the drive for which the taskfile settings should be retrieved
  * @gtf_length: number of bytes of _GTF data returned at @gtf_address
@@ -257,47 +216,15 @@
 	acpi_status			status;
 	struct acpi_buffer		output;
 	union acpi_object 		*out_obj;
-	ide_hwif_t			*hwif = drive->hwif;
-	struct device			*dev = hwif->gendev.parent;
 	int				err = -ENODEV;
-	int				port;
 
 	*gtf_length = 0;
 	*gtf_address = 0UL;
 	*obj_loc = 0UL;
 
-	if (ide_noacpi)
-		return 0;
-
-	if (!dev) {
-		DEBPRINT("no PCI device for %s\n", hwif->name);
-		goto out;
-	}
-
-	if (!hwif->acpidata) {
-		DEBPRINT("no ACPI data for %s\n", hwif->name);
-		goto out;
-	}
-
-	port = hwif->channel ? drive->dn - 2: drive->dn;
-
-	DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
-		 hwif->name, dev_name(dev), port, hwif->channel);
-
-	if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) {
-		DEBPRINT("%s drive %d:%d not present\n",
-			 hwif->name, hwif->channel, port);
-		goto out;
-	}
-
-	/* Get this drive's _ADR info. if not already known. */
 	if (!drive->acpidata->obj_handle) {
-		drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
-		if (!drive->acpidata->obj_handle) {
-			DEBPRINT("No ACPI object found for %s\n",
-				 drive->name);
-			goto out;
-		}
+		DEBPRINT("No ACPI object found for %s\n", drive->name);
+		goto out;
 	}
 
 	/* Setting up output buffer */
@@ -355,43 +282,6 @@
 }
 
 /**
- * taskfile_load_raw - send taskfile registers to drive
- * @drive: drive to which output is sent
- * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
- *
- * Outputs IDE taskfile to the drive.
- */
-static int taskfile_load_raw(ide_drive_t *drive,
-			      const struct taskfile_array *gtf)
-{
-	ide_task_t args;
-	int err = 0;
-
-	DEBPRINT("(0x1f1-1f7): hex: "
-	       "%02x %02x %02x %02x %02x %02x %02x\n",
-	       gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
-	       gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
-
-	memset(&args, 0, sizeof(ide_task_t));
-
-	/* convert gtf to IDE Taskfile */
-	memcpy(&args.tf_array[7], &gtf->tfa, 7);
-	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-
-	if (!ide_acpigtf) {
-		DEBPRINT("_GTF execution disabled\n");
-		return err;
-	}
-
-	err = ide_no_data_taskfile(drive, &args);
-	if (err)
-		printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
-		       __func__, err);
-
-	return err;
-}
-
-/**
  * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
  * @drive: the drive to which the taskfile command should be sent
  * @gtf_length: total number of bytes of _GTF taskfiles
@@ -404,43 +294,41 @@
 				  unsigned int gtf_length,
 				  unsigned long gtf_address)
 {
-	int			rc = -ENODEV, err;
+	int			rc = 0, err;
 	int			gtf_count = gtf_length / REGS_PER_GTF;
 	int			ix;
-	struct taskfile_array	*gtf;
-
-	if (ide_noacpi)
-		return 0;
-
-	DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn);
-
-	if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
-		goto out;
-
-	if (!gtf_count)		/* shouldn't be here */
-		goto out;
 
 	DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n",
 		 gtf_length, gtf_length, gtf_count, gtf_address);
 
-	if (gtf_length % REGS_PER_GTF) {
-		printk(KERN_ERR "%s: unexpected GTF length (%d)\n",
-		       __func__, gtf_length);
-		goto out;
-	}
-
-	rc = 0;
+	/* send all taskfile registers (0x1f1-0x1f7) *in*that*order* */
 	for (ix = 0; ix < gtf_count; ix++) {
-		gtf = (struct taskfile_array *)
-			(gtf_address + ix * REGS_PER_GTF);
+		u8 *gtf = (u8 *)(gtf_address + ix * REGS_PER_GTF);
+		ide_task_t task;
 
-		/* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
-		err = taskfile_load_raw(drive, gtf);
-		if (err)
+		DEBPRINT("(0x1f1-1f7): "
+			 "hex: %02x %02x %02x %02x %02x %02x %02x\n",
+			 gtf[0], gtf[1], gtf[2],
+			 gtf[3], gtf[4], gtf[5], gtf[6]);
+
+		if (!ide_acpigtf) {
+			DEBPRINT("_GTF execution disabled\n");
+			continue;
+		}
+
+		/* convert GTF to taskfile */
+		memset(&task, 0, sizeof(ide_task_t));
+		memcpy(&task.tf_array[7], gtf, REGS_PER_GTF);
+		task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+		err = ide_no_data_taskfile(drive, &task);
+		if (err) {
+			printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
+					__func__, err);
 			rc = err;
+		}
 	}
 
-out:
 	return rc;
 }
 
@@ -647,26 +535,23 @@
 		DEBPRINT("no ACPI data for %s\n", hwif->name);
 		return;
 	}
+
 	/* channel first and then drives for power on and verse versa for power off */
 	if (on)
 		acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0);
 
-	ide_port_for_each_dev(i, drive, hwif) {
-		if (!drive->acpidata->obj_handle)
-			drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
-
-		if (drive->acpidata->obj_handle &&
-		    (drive->dev_flags & IDE_DFLAG_PRESENT)) {
+	ide_port_for_each_present_dev(i, drive, hwif) {
+		if (drive->acpidata->obj_handle)
 			acpi_bus_set_power(drive->acpidata->obj_handle,
-				on? ACPI_STATE_D0: ACPI_STATE_D3);
-		}
+					   on ? ACPI_STATE_D0 : ACPI_STATE_D3);
 	}
+
 	if (!on)
 		acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3);
 }
 
 /**
- * ide_acpi_init - initialize the ACPI link for an IDE interface
+ * ide_acpi_init_port - initialize the ACPI link for an IDE interface
  * @hwif: target IDE interface (channel)
  *
  * The ACPI spec is not quite clear when the drive identify buffer
@@ -676,10 +561,8 @@
  * So we get the information during startup; but this means that
  * any changes during run-time will be lost after resume.
  */
-void ide_acpi_init(ide_hwif_t *hwif)
+void ide_acpi_init_port(ide_hwif_t *hwif)
 {
-	ide_acpi_blacklist();
-
 	hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL);
 	if (!hwif->acpidata)
 		return;
@@ -708,15 +591,24 @@
 	hwif->devices[0]->acpidata = &hwif->acpidata->master;
 	hwif->devices[1]->acpidata = &hwif->acpidata->slave;
 
-	/*
-	 * Send IDENTIFY for each drive
-	 */
-	ide_port_for_each_dev(i, drive, hwif) {
-		memset(drive->acpidata, 0, sizeof(*drive->acpidata));
+	/* get _ADR info for each device */
+	ide_port_for_each_present_dev(i, drive, hwif) {
+		acpi_handle dev_handle;
 
-		if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
-			continue;
+		DEBPRINT("ENTER: %s at channel#: %d port#: %d\n",
+			 drive->name, hwif->channel, drive->dn & 1);
 
+		/* TBD: could also check ACPI object VALID bits */
+		dev_handle = acpi_get_child(hwif->acpidata->obj_handle,
+					    drive->dn & 1);
+
+		DEBPRINT("drive %s handle 0x%p\n", drive->name, dev_handle);
+
+		drive->acpidata->obj_handle = dev_handle;
+	}
+
+	/* send IDENTIFY for each device */
+	ide_port_for_each_present_dev(i, drive, hwif) {
 		err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff);
 		if (err)
 			DEBPRINT("identify device %s failed (%d)\n",
@@ -736,9 +628,7 @@
 	ide_acpi_get_timing(hwif);
 	ide_acpi_push_timing(hwif);
 
-	ide_port_for_each_dev(i, drive, hwif) {
-		if (drive->dev_flags & IDE_DFLAG_PRESENT)
-			/* Execute ACPI startup code */
-			ide_acpi_exec_tfs(drive);
+	ide_port_for_each_present_dev(i, drive, hwif) {
+		ide_acpi_exec_tfs(drive);
 	}
 }
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index e96c012..6adc5b4 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -140,10 +140,19 @@
 	rq->cmd_flags |= REQ_PREEMPT;
 	rq->buffer = (char *)pc;
 	rq->rq_disk = disk;
+
+	if (pc->req_xfer) {
+		rq->data = pc->buf;
+		rq->data_len = pc->req_xfer;
+	}
+
 	memcpy(rq->cmd, pc->c, 12);
 	if (drive->media == ide_tape)
 		rq->cmd[13] = REQ_IDETAPE_PC1;
-	ide_do_drive_cmd(drive, rq);
+
+	drive->hwif->rq = NULL;
+
+	elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
 }
 
 /*
@@ -159,6 +168,12 @@
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_SPECIAL;
 	rq->buffer = (char *)pc;
+
+	if (pc->req_xfer) {
+		rq->data = pc->buf;
+		rq->data_len = pc->req_xfer;
+	}
+
 	memcpy(rq->cmd, pc->c, 12);
 	if (drive->media == ide_tape)
 		rq->cmd[13] = REQ_IDETAPE_PC1;
@@ -285,6 +300,21 @@
 }
 EXPORT_SYMBOL_GPL(ide_cd_get_xferlen);
 
+void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
+{
+	ide_task_t task;
+
+	memset(&task, 0, sizeof(task));
+	task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
+			IDE_TFLAG_IN_NSECT;
+
+	drive->hwif->tp_ops->tf_read(drive, &task);
+
+	*bcount = (task.tf.lbah << 8) | task.tf.lbam;
+	*ireason = task.tf.nsect & 3;
+}
+EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
+
 /*
  * This is the usual interrupt handler which will be called during a packet
  * command.  We will transfer some of the data (as requested by the drive)
@@ -444,6 +474,25 @@
 	return ide_started;
 }
 
+static void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	ide_task_t task;
+	u8 dma = drive->dma;
+
+	memset(&task, 0, sizeof(task));
+	task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
+			IDE_TFLAG_OUT_FEATURE | tf_flags;
+	task.tf.feature = dma;		/* Use PIO/DMA */
+	task.tf.lbam    = bcount & 0xff;
+	task.tf.lbah    = (bcount >> 8) & 0xff;
+
+	ide_tf_dump(drive->name, &task.tf);
+	hwif->tp_ops->set_irq(hwif, 1);
+	SELECT_MASK(drive, 0);
+	hwif->tp_ops->tf_load(drive, &task);
+}
+
 static u8 ide_read_ireason(ide_drive_t *drive)
 {
 	ide_task_t task;
@@ -617,7 +666,7 @@
 						       : WAIT_TAPE_CMD;
 	}
 
-	ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma);
+	ide_pktcmd_tf_load(drive, tf_flags, bcount);
 
 	/* Issue the packet command */
 	if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index ddfbea4..2177cd1 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -242,7 +242,9 @@
 		ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n",
 			      failed_command->cmd[0]);
 
-	ide_do_drive_cmd(drive, rq);
+	drive->hwif->rq = NULL;
+
+	elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
 }
 
 static void cdrom_end_request(ide_drive_t *drive, int uptodate)
diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c
new file mode 100644
index 0000000..7c39534
--- /dev/null
+++ b/drivers/ide/ide-devsets.c
@@ -0,0 +1,190 @@
+
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+DEFINE_MUTEX(ide_setting_mtx);
+
+ide_devset_get(io_32bit, io_32bit);
+
+static int set_io_32bit(ide_drive_t *drive, int arg)
+{
+	if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT)
+		return -EPERM;
+
+	if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
+		return -EINVAL;
+
+	drive->io_32bit = arg;
+
+	return 0;
+}
+
+ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS);
+
+static int set_ksettings(ide_drive_t *drive, int arg)
+{
+	if (arg < 0 || arg > 1)
+		return -EINVAL;
+
+	if (arg)
+		drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS;
+	else
+		drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS;
+
+	return 0;
+}
+
+ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA);
+
+static int set_using_dma(ide_drive_t *drive, int arg)
+{
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	int err = -EPERM;
+
+	if (arg < 0 || arg > 1)
+		return -EINVAL;
+
+	if (ata_id_has_dma(drive->id) == 0)
+		goto out;
+
+	if (drive->hwif->dma_ops == NULL)
+		goto out;
+
+	err = 0;
+
+	if (arg) {
+		if (ide_set_dma(drive))
+			err = -EIO;
+	} else
+		ide_dma_off(drive);
+
+out:
+	return err;
+#else
+	if (arg < 0 || arg > 1)
+		return -EINVAL;
+
+	return -EPERM;
+#endif
+}
+
+/*
+ * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
+ */
+static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
+{
+	switch (req_pio) {
+	case 202:
+	case 201:
+	case 200:
+	case 102:
+	case 101:
+	case 100:
+		return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
+	case 9:
+	case 8:
+		return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
+	case 7:
+	case 6:
+		return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
+	default:
+		return 0;
+	}
+}
+
+static int set_pio_mode(ide_drive_t *drive, int arg)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_port_ops *port_ops = hwif->port_ops;
+
+	if (arg < 0 || arg > 255)
+		return -EINVAL;
+
+	if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
+	    (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+		return -ENOSYS;
+
+	if (set_pio_mode_abuse(drive->hwif, arg)) {
+		if (arg == 8 || arg == 9) {
+			unsigned long flags;
+
+			/* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
+			spin_lock_irqsave(&hwif->lock, flags);
+			port_ops->set_pio_mode(drive, arg);
+			spin_unlock_irqrestore(&hwif->lock, flags);
+		} else
+			port_ops->set_pio_mode(drive, arg);
+	} else {
+		int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
+
+		ide_set_pio(drive, arg);
+
+		if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
+			if (keep_dma)
+				ide_dma_on(drive);
+		}
+	}
+
+	return 0;
+}
+
+ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK);
+
+static int set_unmaskirq(ide_drive_t *drive, int arg)
+{
+	if (drive->dev_flags & IDE_DFLAG_NO_UNMASK)
+		return -EPERM;
+
+	if (arg < 0 || arg > 1)
+		return -EINVAL;
+
+	if (arg)
+		drive->dev_flags |= IDE_DFLAG_UNMASK;
+	else
+		drive->dev_flags &= ~IDE_DFLAG_UNMASK;
+
+	return 0;
+}
+
+ide_ext_devset_rw_sync(io_32bit, io_32bit);
+ide_ext_devset_rw_sync(keepsettings, ksettings);
+ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
+ide_ext_devset_rw_sync(using_dma, using_dma);
+__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
+
+int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
+		       int arg)
+{
+	struct request_queue *q = drive->queue;
+	struct request *rq;
+	int ret = 0;
+
+	if (!(setting->flags & DS_SYNC))
+		return setting->set(drive, arg);
+
+	rq = blk_get_request(q, READ, __GFP_WAIT);
+	rq->cmd_type = REQ_TYPE_SPECIAL;
+	rq->cmd_len = 5;
+	rq->cmd[0] = REQ_DEVSET_EXEC;
+	*(int *)&rq->cmd[1] = arg;
+	rq->special = setting->set;
+
+	if (blk_execute_rq(q, NULL, rq, 0))
+		ret = rq->errors;
+	blk_put_request(rq);
+
+	return ret;
+}
+
+ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq)
+{
+	int err, (*setfunc)(ide_drive_t *, int) = rq->special;
+
+	err = setfunc(drive, *(int *)&rq->cmd[1]);
+	if (err)
+		rq->errors = err;
+	else
+		err = 1;
+	ide_end_request(drive, err, 0);
+	return ide_stopped;
+}
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c
index 1146f42..1f86dcb 100644
--- a/drivers/ide/ide-disk_proc.c
+++ b/drivers/ide/ide-disk_proc.c
@@ -125,5 +125,5 @@
 	IDE_PROC_DEVSET(multcount,	0,    16),
 	IDE_PROC_DEVSET(nowerr,		0,     1),
 	IDE_PROC_DEVSET(wcache,		0,     1),
-	{ 0 },
+	{ NULL },
 };
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 72ebab0..a878f47 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -128,6 +128,7 @@
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct scatterlist *sg = hwif->sg_table;
+	int i;
 
 	ide_map_sg(drive, rq);
 
@@ -136,8 +137,13 @@
 	else
 		hwif->sg_dma_direction = DMA_TO_DEVICE;
 
-	return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
-			  hwif->sg_dma_direction);
+	i = dma_map_sg(hwif->dev, sg, hwif->sg_nents, hwif->sg_dma_direction);
+	if (i) {
+		hwif->orig_sg_nents = hwif->sg_nents;
+		hwif->sg_nents = i;
+	}
+
+	return i;
 }
 EXPORT_SYMBOL_GPL(ide_build_sglist);
 
@@ -156,7 +162,7 @@
 {
 	ide_hwif_t *hwif = drive->hwif;
 
-	dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
+	dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->orig_sg_nents,
 		     hwif->sg_dma_direction);
 }
 EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
@@ -464,6 +470,63 @@
 }
 EXPORT_SYMBOL_GPL(ide_dma_timeout);
 
+/*
+ * un-busy the port etc, and clear any pending DMA status. we want to
+ * retry the current request in pio mode instead of risking tossing it
+ * all away
+ */
+ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct request *rq;
+	ide_startstop_t ret = ide_stopped;
+
+	/*
+	 * end current dma transaction
+	 */
+
+	if (error < 0) {
+		printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
+		(void)hwif->dma_ops->dma_end(drive);
+		ret = ide_error(drive, "dma timeout error",
+				hwif->tp_ops->read_status(hwif));
+	} else {
+		printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
+		hwif->dma_ops->dma_timeout(drive);
+	}
+
+	/*
+	 * disable dma for now, but remember that we did so because of
+	 * a timeout -- we'll reenable after we finish this next request
+	 * (or rather the first chunk of it) in pio.
+	 */
+	drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
+	drive->retry_pio++;
+	ide_dma_off_quietly(drive);
+
+	/*
+	 * un-busy drive etc and make sure request is sane
+	 */
+
+	rq = hwif->rq;
+	if (!rq)
+		goto out;
+
+	hwif->rq = NULL;
+
+	rq->errors = 0;
+
+	if (!rq->bio)
+		goto out;
+
+	rq->sector = rq->bio->bi_sector;
+	rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
+	rq->hard_cur_sectors = rq->current_nr_sectors;
+	rq->buffer = bio_data(rq->bio);
+out:
+	return ret;
+}
+
 void ide_release_dma_engine(ide_hwif_t *hwif)
 {
 	if (hwif->dmatable_cpu) {
diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c
new file mode 100644
index 0000000..1231b5e
--- /dev/null
+++ b/drivers/ide/ide-eh.c
@@ -0,0 +1,428 @@
+
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+
+static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq,
+				     u8 stat, u8 err)
+{
+	ide_hwif_t *hwif = drive->hwif;
+
+	if ((stat & ATA_BUSY) ||
+	    ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
+		/* other bits are useless when BUSY */
+		rq->errors |= ERROR_RESET;
+	} else if (stat & ATA_ERR) {
+		/* err has different meaning on cdrom and tape */
+		if (err == ATA_ABORTED) {
+			if ((drive->dev_flags & IDE_DFLAG_LBA) &&
+			    /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
+			    hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
+				return ide_stopped;
+		} else if ((err & BAD_CRC) == BAD_CRC) {
+			/* UDMA crc error, just retry the operation */
+			drive->crc_count++;
+		} else if (err & (ATA_BBK | ATA_UNC)) {
+			/* retries won't help these */
+			rq->errors = ERROR_MAX;
+		} else if (err & ATA_TRK0NF) {
+			/* help it find track zero */
+			rq->errors |= ERROR_RECAL;
+		}
+	}
+
+	if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
+	    (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
+		int nsect = drive->mult_count ? drive->mult_count : 1;
+
+		ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE);
+	}
+
+	if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
+		ide_kill_rq(drive, rq);
+		return ide_stopped;
+	}
+
+	if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
+		rq->errors |= ERROR_RESET;
+
+	if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
+		++rq->errors;
+		return ide_do_reset(drive);
+	}
+
+	if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
+		drive->special.b.recalibrate = 1;
+
+	++rq->errors;
+
+	return ide_stopped;
+}
+
+static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq,
+				       u8 stat, u8 err)
+{
+	ide_hwif_t *hwif = drive->hwif;
+
+	if ((stat & ATA_BUSY) ||
+	    ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
+		/* other bits are useless when BUSY */
+		rq->errors |= ERROR_RESET;
+	} else {
+		/* add decoding error stuff */
+	}
+
+	if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
+		/* force an abort */
+		hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
+
+	if (rq->errors >= ERROR_MAX) {
+		ide_kill_rq(drive, rq);
+	} else {
+		if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
+			++rq->errors;
+			return ide_do_reset(drive);
+		}
+		++rq->errors;
+	}
+
+	return ide_stopped;
+}
+
+static ide_startstop_t __ide_error(ide_drive_t *drive, struct request *rq,
+				   u8 stat, u8 err)
+{
+	if (drive->media == ide_disk)
+		return ide_ata_error(drive, rq, stat, err);
+	return ide_atapi_error(drive, rq, stat, err);
+}
+
+/**
+ *	ide_error	-	handle an error on the IDE
+ *	@drive: drive the error occurred on
+ *	@msg: message to report
+ *	@stat: status bits
+ *
+ *	ide_error() takes action based on the error returned by the drive.
+ *	For normal I/O that may well include retries. We deal with
+ *	both new-style (taskfile) and old style command handling here.
+ *	In the case of taskfile command handling there is work left to
+ *	do
+ */
+
+ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat)
+{
+	struct request *rq;
+	u8 err;
+
+	err = ide_dump_status(drive, msg, stat);
+
+	rq = drive->hwif->rq;
+	if (rq == NULL)
+		return ide_stopped;
+
+	/* retry only "normal" I/O: */
+	if (!blk_fs_request(rq)) {
+		rq->errors = 1;
+		ide_end_drive_cmd(drive, stat, err);
+		return ide_stopped;
+	}
+
+	return __ide_error(drive, rq, stat, err);
+}
+EXPORT_SYMBOL_GPL(ide_error);
+
+static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
+{
+	struct request *rq = drive->hwif->rq;
+
+	if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
+		ide_end_request(drive, err ? err : 1, 0);
+}
+
+/* needed below */
+static ide_startstop_t do_reset1(ide_drive_t *, int);
+
+/*
+ * atapi_reset_pollfunc() gets invoked to poll the interface for completion
+ * every 50ms during an atapi drive reset operation.  If the drive has not yet
+ * responded, and we have not yet hit our maximum waiting time, then the timer
+ * is restarted for another 50ms.
+ */
+static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	u8 stat;
+
+	SELECT_DRIVE(drive);
+	udelay(10);
+	stat = hwif->tp_ops->read_status(hwif);
+
+	if (OK_STAT(stat, 0, ATA_BUSY))
+		printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name);
+	else {
+		if (time_before(jiffies, hwif->poll_timeout)) {
+			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20,
+					NULL);
+			/* continue polling */
+			return ide_started;
+		}
+		/* end of polling */
+		hwif->polling = 0;
+		printk(KERN_ERR "%s: ATAPI reset timed-out, status=0x%02x\n",
+			drive->name, stat);
+		/* do it the old fashioned way */
+		return do_reset1(drive, 1);
+	}
+	/* done polling */
+	hwif->polling = 0;
+	ide_complete_drive_reset(drive, 0);
+	return ide_stopped;
+}
+
+static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
+{
+	static const char *err_master_vals[] =
+		{ NULL, "passed", "formatter device error",
+		  "sector buffer error", "ECC circuitry error",
+		  "controlling MPU error" };
+
+	u8 err_master = err & 0x7f;
+
+	printk(KERN_ERR "%s: reset: master: ", hwif->name);
+	if (err_master && err_master < 6)
+		printk(KERN_CONT "%s", err_master_vals[err_master]);
+	else
+		printk(KERN_CONT "error (0x%02x?)", err);
+	if (err & 0x80)
+		printk(KERN_CONT "; slave: failed");
+	printk(KERN_CONT "\n");
+}
+
+/*
+ * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
+ * during an ide reset operation. If the drives have not yet responded,
+ * and we have not yet hit our maximum waiting time, then the timer is restarted
+ * for another 50ms.
+ */
+static ide_startstop_t reset_pollfunc(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_port_ops *port_ops = hwif->port_ops;
+	u8 tmp;
+	int err = 0;
+
+	if (port_ops && port_ops->reset_poll) {
+		err = port_ops->reset_poll(drive);
+		if (err) {
+			printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
+				hwif->name, drive->name);
+			goto out;
+		}
+	}
+
+	tmp = hwif->tp_ops->read_status(hwif);
+
+	if (!OK_STAT(tmp, 0, ATA_BUSY)) {
+		if (time_before(jiffies, hwif->poll_timeout)) {
+			ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
+			/* continue polling */
+			return ide_started;
+		}
+		printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n",
+			hwif->name, tmp);
+		drive->failures++;
+		err = -EIO;
+	} else  {
+		tmp = ide_read_error(drive);
+
+		if (tmp == 1) {
+			printk(KERN_INFO "%s: reset: success\n", hwif->name);
+			drive->failures = 0;
+		} else {
+			ide_reset_report_error(hwif, tmp);
+			drive->failures++;
+			err = -EIO;
+		}
+	}
+out:
+	hwif->polling = 0;	/* done polling */
+	ide_complete_drive_reset(drive, err);
+	return ide_stopped;
+}
+
+static void ide_disk_pre_reset(ide_drive_t *drive)
+{
+	int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1;
+
+	drive->special.all = 0;
+	drive->special.b.set_geometry = legacy;
+	drive->special.b.recalibrate  = legacy;
+
+	drive->mult_count = 0;
+	drive->dev_flags &= ~IDE_DFLAG_PARKED;
+
+	if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
+	    (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
+		drive->mult_req = 0;
+
+	if (drive->mult_req != drive->mult_count)
+		drive->special.b.set_multmode = 1;
+}
+
+static void pre_reset(ide_drive_t *drive)
+{
+	const struct ide_port_ops *port_ops = drive->hwif->port_ops;
+
+	if (drive->media == ide_disk)
+		ide_disk_pre_reset(drive);
+	else
+		drive->dev_flags |= IDE_DFLAG_POST_RESET;
+
+	if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
+		if (drive->crc_count)
+			ide_check_dma_crc(drive);
+		else
+			ide_dma_off(drive);
+	}
+
+	if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
+		if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
+			drive->dev_flags &= ~IDE_DFLAG_UNMASK;
+			drive->io_32bit = 0;
+		}
+		return;
+	}
+
+	if (port_ops && port_ops->pre_reset)
+		port_ops->pre_reset(drive);
+
+	if (drive->current_speed != 0xff)
+		drive->desired_speed = drive->current_speed;
+	drive->current_speed = 0xff;
+}
+
+/*
+ * do_reset1() attempts to recover a confused drive by resetting it.
+ * Unfortunately, resetting a disk drive actually resets all devices on
+ * the same interface, so it can really be thought of as resetting the
+ * interface rather than resetting the drive.
+ *
+ * ATAPI devices have their own reset mechanism which allows them to be
+ * individually reset without clobbering other devices on the same interface.
+ *
+ * Unfortunately, the IDE interface does not generate an interrupt to let
+ * us know when the reset operation has finished, so we must poll for this.
+ * Equally poor, though, is the fact that this may a very long time to complete,
+ * (up to 30 seconds worstcase).  So, instead of busy-waiting here for it,
+ * we set a timer to poll at 50ms intervals.
+ */
+static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+	const struct ide_port_ops *port_ops;
+	ide_drive_t *tdrive;
+	unsigned long flags, timeout;
+	int i;
+	DEFINE_WAIT(wait);
+
+	spin_lock_irqsave(&hwif->lock, flags);
+
+	/* We must not reset with running handlers */
+	BUG_ON(hwif->handler != NULL);
+
+	/* For an ATAPI device, first try an ATAPI SRST. */
+	if (drive->media != ide_disk && !do_not_try_atapi) {
+		pre_reset(drive);
+		SELECT_DRIVE(drive);
+		udelay(20);
+		tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
+		ndelay(400);
+		hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
+		hwif->polling = 1;
+		__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
+		spin_unlock_irqrestore(&hwif->lock, flags);
+		return ide_started;
+	}
+
+	/* We must not disturb devices in the IDE_DFLAG_PARKED state. */
+	do {
+		unsigned long now;
+
+		prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
+		timeout = jiffies;
+		ide_port_for_each_present_dev(i, tdrive, hwif) {
+			if ((tdrive->dev_flags & IDE_DFLAG_PARKED) &&
+			    time_after(tdrive->sleep, timeout))
+				timeout = tdrive->sleep;
+		}
+
+		now = jiffies;
+		if (time_before_eq(timeout, now))
+			break;
+
+		spin_unlock_irqrestore(&hwif->lock, flags);
+		timeout = schedule_timeout_uninterruptible(timeout - now);
+		spin_lock_irqsave(&hwif->lock, flags);
+	} while (timeout);
+	finish_wait(&ide_park_wq, &wait);
+
+	/*
+	 * First, reset any device state data we were maintaining
+	 * for any of the drives on this interface.
+	 */
+	ide_port_for_each_dev(i, tdrive, hwif)
+		pre_reset(tdrive);
+
+	if (io_ports->ctl_addr == 0) {
+		spin_unlock_irqrestore(&hwif->lock, flags);
+		ide_complete_drive_reset(drive, -ENXIO);
+		return ide_stopped;
+	}
+
+	/*
+	 * Note that we also set nIEN while resetting the device,
+	 * to mask unwanted interrupts from the interface during the reset.
+	 * However, due to the design of PC hardware, this will cause an
+	 * immediate interrupt due to the edge transition it produces.
+	 * This single interrupt gives us a "fast poll" for drives that
+	 * recover from reset very quickly, saving us the first 50ms wait time.
+	 *
+	 * TODO: add ->softreset method and stop abusing ->set_irq
+	 */
+	/* set SRST and nIEN */
+	tp_ops->set_irq(hwif, 4);
+	/* more than enough time */
+	udelay(10);
+	/* clear SRST, leave nIEN (unless device is on the quirk list) */
+	tp_ops->set_irq(hwif, drive->quirk_list == 2);
+	/* more than enough time */
+	udelay(10);
+	hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
+	hwif->polling = 1;
+	__ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
+
+	/*
+	 * Some weird controller like resetting themselves to a strange
+	 * state when the disks are reset this way. At least, the Winbond
+	 * 553 documentation says that
+	 */
+	port_ops = hwif->port_ops;
+	if (port_ops && port_ops->resetproc)
+		port_ops->resetproc(drive);
+
+	spin_unlock_irqrestore(&hwif->lock, flags);
+	return ide_started;
+}
+
+/*
+ * ide_do_reset() is the entry point to the drive/interface reset code.
+ */
+
+ide_startstop_t ide_do_reset(ide_drive_t *drive)
+{
+	return do_reset1(drive, 0);
+}
+EXPORT_SYMBOL(ide_do_reset);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 3eab1c6..317ec62 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -327,8 +327,10 @@
 		return ide_stopped;
 	}
 
-	ide_init_sg_cmd(drive, rq);
-	ide_map_sg(drive, rq);
+	if (blk_fs_request(rq) || pc->req_xfer) {
+		ide_init_sg_cmd(drive, rq);
+		ide_map_sg(drive, rq);
+	}
 
 	pc->sg = hwif->sg_table;
 	pc->sg_cnt = hwif->sg_nents;
diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c
index 3ec762c..fcd4d81 100644
--- a/drivers/ide/ide-floppy_proc.c
+++ b/drivers/ide/ide-floppy_proc.c
@@ -29,5 +29,5 @@
 	IDE_PROC_DEVSET(bios_head, 0,  255),
 	IDE_PROC_DEVSET(bios_sect, 0,   63),
 	IDE_PROC_DEVSET(ticks,	   0,  255),
-	{ 0 },
+	{ NULL },
 };
diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c
new file mode 100644
index 0000000..45b43dd
--- /dev/null
+++ b/drivers/ide/ide-io-std.c
@@ -0,0 +1,316 @@
+
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+/*
+ *	Conventional PIO operations for ATA devices
+ */
+
+static u8 ide_inb(unsigned long port)
+{
+	return (u8) inb(port);
+}
+
+static void ide_outb(u8 val, unsigned long port)
+{
+	outb(val, port);
+}
+
+/*
+ *	MMIO operations, typically used for SATA controllers
+ */
+
+static u8 ide_mm_inb(unsigned long port)
+{
+	return (u8) readb((void __iomem *) port);
+}
+
+static void ide_mm_outb(u8 value, unsigned long port)
+{
+	writeb(value, (void __iomem *) port);
+}
+
+void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+	else
+		outb(cmd, hwif->io_ports.command_addr);
+}
+EXPORT_SYMBOL_GPL(ide_exec_command);
+
+u8 ide_read_status(ide_hwif_t *hwif)
+{
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		return readb((void __iomem *)hwif->io_ports.status_addr);
+	else
+		return inb(hwif->io_ports.status_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_status);
+
+u8 ide_read_altstatus(ide_hwif_t *hwif)
+{
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		return readb((void __iomem *)hwif->io_ports.ctl_addr);
+	else
+		return inb(hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_altstatus);
+
+void ide_set_irq(ide_hwif_t *hwif, int on)
+{
+	u8 ctl = ATA_DEVCTL_OBS;
+
+	if (on == 4) { /* hack for SRST */
+		ctl |= 4;
+		on &= ~4;
+	}
+
+	ctl |= on ? 0 : 2;
+
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+	else
+		outb(ctl, hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_set_irq);
+
+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+	struct ide_taskfile *tf = &task->tf;
+	void (*tf_outb)(u8 addr, unsigned long port);
+	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+	u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+
+	if (mmio)
+		tf_outb = ide_mm_outb;
+	else
+		tf_outb = ide_outb;
+
+	if (task->tf_flags & IDE_TFLAG_FLAGGED)
+		HIHI = 0xFF;
+
+	if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+		u16 data = (tf->hob_data << 8) | tf->data;
+
+		if (mmio)
+			writew(data, (void __iomem *)io_ports->data_addr);
+		else
+			outw(data, io_ports->data_addr);
+	}
+
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+		tf_outb(tf->hob_feature, io_ports->feature_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+		tf_outb(tf->hob_nsect, io_ports->nsect_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+		tf_outb(tf->hob_lbal, io_ports->lbal_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+		tf_outb(tf->hob_lbam, io_ports->lbam_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+		tf_outb(tf->hob_lbah, io_ports->lbah_addr);
+
+	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+		tf_outb(tf->feature, io_ports->feature_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+		tf_outb(tf->nsect, io_ports->nsect_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+		tf_outb(tf->lbal, io_ports->lbal_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+		tf_outb(tf->lbam, io_ports->lbam_addr);
+	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+		tf_outb(tf->lbah, io_ports->lbah_addr);
+
+	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+		tf_outb((tf->device & HIHI) | drive->select,
+			 io_ports->device_addr);
+}
+EXPORT_SYMBOL_GPL(ide_tf_load);
+
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+	struct ide_taskfile *tf = &task->tf;
+	void (*tf_outb)(u8 addr, unsigned long port);
+	u8 (*tf_inb)(unsigned long port);
+	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+	if (mmio) {
+		tf_outb = ide_mm_outb;
+		tf_inb  = ide_mm_inb;
+	} else {
+		tf_outb = ide_outb;
+		tf_inb  = ide_inb;
+	}
+
+	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+		u16 data;
+
+		if (mmio)
+			data = readw((void __iomem *)io_ports->data_addr);
+		else
+			data = inw(io_ports->data_addr);
+
+		tf->data = data & 0xff;
+		tf->hob_data = (data >> 8) & 0xff;
+	}
+
+	/* be sure we're looking at the low order bits */
+	tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+		tf->feature = tf_inb(io_ports->feature_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+		tf->nsect  = tf_inb(io_ports->nsect_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+		tf->lbal   = tf_inb(io_ports->lbal_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+		tf->lbam   = tf_inb(io_ports->lbam_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+		tf->lbah   = tf_inb(io_ports->lbah_addr);
+	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+		tf->device = tf_inb(io_ports->device_addr);
+
+	if (task->tf_flags & IDE_TFLAG_LBA48) {
+		tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+			tf->hob_feature = tf_inb(io_ports->feature_addr);
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+			tf->hob_nsect   = tf_inb(io_ports->nsect_addr);
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+			tf->hob_lbal    = tf_inb(io_ports->lbal_addr);
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+			tf->hob_lbam    = tf_inb(io_ports->lbam_addr);
+		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+			tf->hob_lbah    = tf_inb(io_ports->lbah_addr);
+	}
+}
+EXPORT_SYMBOL_GPL(ide_tf_read);
+
+/*
+ * Some localbus EIDE interfaces require a special access sequence
+ * when using 32-bit I/O instructions to transfer data.  We call this
+ * the "vlb_sync" sequence, which consists of three successive reads
+ * of the sector count register location, with interrupts disabled
+ * to ensure that the reads all happen together.
+ */
+static void ata_vlb_sync(unsigned long port)
+{
+	(void)inb(port);
+	(void)inb(port);
+	(void)inb(port);
+}
+
+/*
+ * This is used for most PIO data transfers *from* the IDE interface
+ *
+ * These routines will round up any request for an odd number of bytes,
+ * so if an odd len is specified, be sure that there's at least one
+ * extra byte allocated for the buffer.
+ */
+void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
+		    unsigned int len)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+	unsigned long data_addr = io_ports->data_addr;
+	u8 io_32bit = drive->io_32bit;
+	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+	len++;
+
+	if (io_32bit) {
+		unsigned long uninitialized_var(flags);
+
+		if ((io_32bit & 2) && !mmio) {
+			local_irq_save(flags);
+			ata_vlb_sync(io_ports->nsect_addr);
+		}
+
+		if (mmio)
+			__ide_mm_insl((void __iomem *)data_addr, buf, len / 4);
+		else
+			insl(data_addr, buf, len / 4);
+
+		if ((io_32bit & 2) && !mmio)
+			local_irq_restore(flags);
+
+		if ((len & 3) >= 2) {
+			if (mmio)
+				__ide_mm_insw((void __iomem *)data_addr,
+						(u8 *)buf + (len & ~3), 1);
+			else
+				insw(data_addr, (u8 *)buf + (len & ~3), 1);
+		}
+	} else {
+		if (mmio)
+			__ide_mm_insw((void __iomem *)data_addr, buf, len / 2);
+		else
+			insw(data_addr, buf, len / 2);
+	}
+}
+EXPORT_SYMBOL_GPL(ide_input_data);
+
+/*
+ * This is used for most PIO data transfers *to* the IDE interface
+ */
+void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
+		     unsigned int len)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+	unsigned long data_addr = io_ports->data_addr;
+	u8 io_32bit = drive->io_32bit;
+	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+	len++;
+
+	if (io_32bit) {
+		unsigned long uninitialized_var(flags);
+
+		if ((io_32bit & 2) && !mmio) {
+			local_irq_save(flags);
+			ata_vlb_sync(io_ports->nsect_addr);
+		}
+
+		if (mmio)
+			__ide_mm_outsl((void __iomem *)data_addr, buf, len / 4);
+		else
+			outsl(data_addr, buf, len / 4);
+
+		if ((io_32bit & 2) && !mmio)
+			local_irq_restore(flags);
+
+		if ((len & 3) >= 2) {
+			if (mmio)
+				__ide_mm_outsw((void __iomem *)data_addr,
+						 (u8 *)buf + (len & ~3), 1);
+			else
+				outsw(data_addr, (u8 *)buf + (len & ~3), 1);
+		}
+	} else {
+		if (mmio)
+			__ide_mm_outsw((void __iomem *)data_addr, buf, len / 2);
+		else
+			outsw(data_addr, buf, len / 2);
+	}
+}
+EXPORT_SYMBOL_GPL(ide_output_data);
+
+const struct ide_tp_ops default_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= ide_read_status,
+	.read_altstatus		= ide_read_altstatus,
+
+	.set_irq		= ide_set_irq,
+
+	.tf_load		= ide_tf_load,
+	.tf_read		= ide_tf_read,
+
+	.input_data		= ide_input_data,
+	.output_data		= ide_output_data,
+};
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 9ee51ad..2e92497 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -196,7 +196,7 @@
 }
 EXPORT_SYMBOL(ide_end_drive_cmd);
 
-static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
+void ide_kill_rq(ide_drive_t *drive, struct request *rq)
 {
 	if (rq->rq_disk) {
 		struct ide_driver *drv;
@@ -207,133 +207,6 @@
 		ide_end_request(drive, 0, 0);
 }
 
-static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
-	ide_hwif_t *hwif = drive->hwif;
-
-	if ((stat & ATA_BUSY) ||
-	    ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
-		/* other bits are useless when BUSY */
-		rq->errors |= ERROR_RESET;
-	} else if (stat & ATA_ERR) {
-		/* err has different meaning on cdrom and tape */
-		if (err == ATA_ABORTED) {
-			if ((drive->dev_flags & IDE_DFLAG_LBA) &&
-			    /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
-			    hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
-				return ide_stopped;
-		} else if ((err & BAD_CRC) == BAD_CRC) {
-			/* UDMA crc error, just retry the operation */
-			drive->crc_count++;
-		} else if (err & (ATA_BBK | ATA_UNC)) {
-			/* retries won't help these */
-			rq->errors = ERROR_MAX;
-		} else if (err & ATA_TRK0NF) {
-			/* help it find track zero */
-			rq->errors |= ERROR_RECAL;
-		}
-	}
-
-	if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
-	    (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
-		int nsect = drive->mult_count ? drive->mult_count : 1;
-
-		ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE);
-	}
-
-	if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
-		ide_kill_rq(drive, rq);
-		return ide_stopped;
-	}
-
-	if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
-		rq->errors |= ERROR_RESET;
-
-	if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
-		++rq->errors;
-		return ide_do_reset(drive);
-	}
-
-	if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
-		drive->special.b.recalibrate = 1;
-
-	++rq->errors;
-
-	return ide_stopped;
-}
-
-static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
-	ide_hwif_t *hwif = drive->hwif;
-
-	if ((stat & ATA_BUSY) ||
-	    ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
-		/* other bits are useless when BUSY */
-		rq->errors |= ERROR_RESET;
-	} else {
-		/* add decoding error stuff */
-	}
-
-	if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
-		/* force an abort */
-		hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
-
-	if (rq->errors >= ERROR_MAX) {
-		ide_kill_rq(drive, rq);
-	} else {
-		if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
-			++rq->errors;
-			return ide_do_reset(drive);
-		}
-		++rq->errors;
-	}
-
-	return ide_stopped;
-}
-
-static ide_startstop_t
-__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
-	if (drive->media == ide_disk)
-		return ide_ata_error(drive, rq, stat, err);
-	return ide_atapi_error(drive, rq, stat, err);
-}
-
-/**
- *	ide_error	-	handle an error on the IDE
- *	@drive: drive the error occurred on
- *	@msg: message to report
- *	@stat: status bits
- *
- *	ide_error() takes action based on the error returned by the drive.
- *	For normal I/O that may well include retries. We deal with
- *	both new-style (taskfile) and old style command handling here.
- *	In the case of taskfile command handling there is work left to
- *	do
- */
- 
-ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
-{
-	struct request *rq;
-	u8 err;
-
-	err = ide_dump_status(drive, msg, stat);
-
-	rq = drive->hwif->rq;
-	if (rq == NULL)
-		return ide_stopped;
-
-	/* retry only "normal" I/O: */
-	if (!blk_fs_request(rq)) {
-		rq->errors = 1;
-		ide_end_drive_cmd(drive, stat, err);
-		return ide_stopped;
-	}
-
-	return __ide_error(drive, rq, stat, err);
-}
-EXPORT_SYMBOL_GPL(ide_error);
-
 static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
 {
 	tf->nsect   = drive->sect;
@@ -490,71 +363,16 @@
  	return ide_stopped;
 }
 
-int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
-		       int arg)
-{
-	struct request_queue *q = drive->queue;
-	struct request *rq;
-	int ret = 0;
-
-	if (!(setting->flags & DS_SYNC))
-		return setting->set(drive, arg);
-
-	rq = blk_get_request(q, READ, __GFP_WAIT);
-	rq->cmd_type = REQ_TYPE_SPECIAL;
-	rq->cmd_len = 5;
-	rq->cmd[0] = REQ_DEVSET_EXEC;
-	*(int *)&rq->cmd[1] = arg;
-	rq->special = setting->set;
-
-	if (blk_execute_rq(q, NULL, rq, 0))
-		ret = rq->errors;
-	blk_put_request(rq);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(ide_devset_execute);
-
 static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
 {
 	u8 cmd = rq->cmd[0];
 
-	if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) {
-		ide_task_t task;
-		struct ide_taskfile *tf = &task.tf;
-
-		memset(&task, 0, sizeof(task));
-		if (cmd == REQ_PARK_HEADS) {
-			drive->sleep = *(unsigned long *)rq->special;
-			drive->dev_flags |= IDE_DFLAG_SLEEPING;
-			tf->command = ATA_CMD_IDLEIMMEDIATE;
-			tf->feature = 0x44;
-			tf->lbal = 0x4c;
-			tf->lbam = 0x4e;
-			tf->lbah = 0x55;
-			task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
-		} else		/* cmd == REQ_UNPARK_HEADS */
-			tf->command = ATA_CMD_CHK_POWER;
-
-		task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-		task.rq = rq;
-		drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
-		return do_rw_taskfile(drive, &task);
-	}
-
 	switch (cmd) {
+	case REQ_PARK_HEADS:
+	case REQ_UNPARK_HEADS:
+		return ide_do_park_unpark(drive, rq);
 	case REQ_DEVSET_EXEC:
-	{
-		int err, (*setfunc)(ide_drive_t *, int) = rq->special;
-
-		err = setfunc(drive, *(int *)&rq->cmd[1]);
-		if (err)
-			rq->errors = err;
-		else
-			err = 1;
-		ide_end_request(drive, err, 0);
-		return ide_stopped;
-	}
+		return ide_do_devset(drive, rq);
 	case REQ_DRIVE_RESET:
 		return ide_do_reset(drive);
 	default:
@@ -820,63 +638,6 @@
 		blk_plug_device(q);
 }
 
-/*
- * un-busy the port etc, and clear any pending DMA status. we want to
- * retry the current request in pio mode instead of risking tossing it
- * all away
- */
-static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	struct request *rq;
-	ide_startstop_t ret = ide_stopped;
-
-	/*
-	 * end current dma transaction
-	 */
-
-	if (error < 0) {
-		printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
-		(void)hwif->dma_ops->dma_end(drive);
-		ret = ide_error(drive, "dma timeout error",
-				hwif->tp_ops->read_status(hwif));
-	} else {
-		printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
-		hwif->dma_ops->dma_timeout(drive);
-	}
-
-	/*
-	 * disable dma for now, but remember that we did so because of
-	 * a timeout -- we'll reenable after we finish this next request
-	 * (or rather the first chunk of it) in pio.
-	 */
-	drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
-	drive->retry_pio++;
-	ide_dma_off_quietly(drive);
-
-	/*
-	 * un-busy drive etc and make sure request is sane
-	 */
-
-	rq = hwif->rq;
-	if (!rq)
-		goto out;
-
-	hwif->rq = NULL;
-
-	rq->errors = 0;
-
-	if (!rq->bio)
-		goto out;
-
-	rq->sector = rq->bio->bi_sector;
-	rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
-	rq->hard_cur_sectors = rq->current_nr_sectors;
-	rq->buffer = bio_data(rq->bio);
-out:
-	return ret;
-}
-
 static void ide_plug_device(ide_drive_t *drive)
 {
 	struct request_queue *q = drive->queue;
@@ -888,6 +649,29 @@
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
+static int drive_is_ready(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	u8 stat = 0;
+
+	if (drive->waiting_for_dma)
+		return hwif->dma_ops->dma_test_irq(drive);
+
+	if (hwif->io_ports.ctl_addr &&
+	    (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0)
+		stat = hwif->tp_ops->read_altstatus(hwif);
+	else
+		/* Note: this may clear a pending IRQ!! */
+		stat = hwif->tp_ops->read_status(hwif);
+
+	if (stat & ATA_BUSY)
+		/* drive busy: definitely not interrupting */
+		return 0;
+
+	/* drive ready: *might* be interrupting */
+	return 1;
+}
+
 /**
  *	ide_timer_expiry	-	handle lack of an IDE interrupt
  *	@data: timer callback magic (hwif)
@@ -908,7 +692,7 @@
 	ide_drive_t	*uninitialized_var(drive);
 	ide_handler_t	*handler;
 	unsigned long	flags;
-	unsigned long	wait = -1;
+	int		wait = -1;
 	int		plug_device = 0;
 
 	spin_lock_irqsave(&hwif->lock, flags);
@@ -1162,54 +946,7 @@
 
 	return irq_ret;
 }
-
-/**
- *	ide_do_drive_cmd	-	issue IDE special command
- *	@drive: device to issue command
- *	@rq: request to issue
- *
- *	This function issues a special IDE device request
- *	onto the request queue.
- *
- *	the rq is queued at the head of the request queue, displacing
- *	the currently-being-processed request and this function
- *	returns immediately without waiting for the new rq to be
- *	completed.  This is VERY DANGEROUS, and is intended for
- *	careful use by the ATAPI tape/cdrom driver code.
- */
-
-void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq)
-{
-	struct request_queue *q = drive->queue;
-	unsigned long flags;
-
-	drive->hwif->rq = NULL;
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
-	spin_unlock_irqrestore(q->queue_lock, flags);
-}
-EXPORT_SYMBOL(ide_do_drive_cmd);
-
-void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	ide_task_t task;
-
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
-			IDE_TFLAG_OUT_FEATURE | tf_flags;
-	task.tf.feature = dma;		/* Use PIO/DMA */
-	task.tf.lbam    = bcount & 0xff;
-	task.tf.lbah    = (bcount >> 8) & 0xff;
-
-	ide_tf_dump(drive->name, &task.tf);
-	hwif->tp_ops->set_irq(hwif, 1);
-	SELECT_MASK(drive, 0);
-	hwif->tp_ops->tf_load(drive, &task);
-}
-
-EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
+EXPORT_SYMBOL_GPL(ide_intr);
 
 void ide_pad_transfer(ide_drive_t *drive, int write, int len)
 {
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 753b92e..317c5da 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -27,35 +27,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-/*
- *	Conventional PIO operations for ATA devices
- */
-
-static u8 ide_inb (unsigned long port)
-{
-	return (u8) inb(port);
-}
-
-static void ide_outb (u8 val, unsigned long port)
-{
-	outb(val, port);
-}
-
-/*
- *	MMIO operations, typically used for SATA controllers
- */
-
-static u8 ide_mm_inb (unsigned long port)
-{
-	return (u8) readb((void __iomem *) port);
-}
-
-static void ide_mm_outb (u8 value, unsigned long port)
-{
-	writeb(value, (void __iomem *) port);
-}
-
-void SELECT_DRIVE (ide_drive_t *drive)
+void SELECT_DRIVE(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	const struct ide_port_ops *port_ops = hwif->port_ops;
@@ -78,275 +50,6 @@
 		port_ops->maskproc(drive, mask);
 }
 
-void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
-{
-	if (hwif->host_flags & IDE_HFLAG_MMIO)
-		writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
-	else
-		outb(cmd, hwif->io_ports.command_addr);
-}
-EXPORT_SYMBOL_GPL(ide_exec_command);
-
-u8 ide_read_status(ide_hwif_t *hwif)
-{
-	if (hwif->host_flags & IDE_HFLAG_MMIO)
-		return readb((void __iomem *)hwif->io_ports.status_addr);
-	else
-		return inb(hwif->io_ports.status_addr);
-}
-EXPORT_SYMBOL_GPL(ide_read_status);
-
-u8 ide_read_altstatus(ide_hwif_t *hwif)
-{
-	if (hwif->host_flags & IDE_HFLAG_MMIO)
-		return readb((void __iomem *)hwif->io_ports.ctl_addr);
-	else
-		return inb(hwif->io_ports.ctl_addr);
-}
-EXPORT_SYMBOL_GPL(ide_read_altstatus);
-
-void ide_set_irq(ide_hwif_t *hwif, int on)
-{
-	u8 ctl = ATA_DEVCTL_OBS;
-
-	if (on == 4) { /* hack for SRST */
-		ctl |= 4;
-		on &= ~4;
-	}
-
-	ctl |= on ? 0 : 2;
-
-	if (hwif->host_flags & IDE_HFLAG_MMIO)
-		writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
-	else
-		outb(ctl, hwif->io_ports.ctl_addr);
-}
-EXPORT_SYMBOL_GPL(ide_set_irq);
-
-void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
-	void (*tf_outb)(u8 addr, unsigned long port);
-	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-	u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
-
-	if (mmio)
-		tf_outb = ide_mm_outb;
-	else
-		tf_outb = ide_outb;
-
-	if (task->tf_flags & IDE_TFLAG_FLAGGED)
-		HIHI = 0xFF;
-
-	if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
-		u16 data = (tf->hob_data << 8) | tf->data;
-
-		if (mmio)
-			writew(data, (void __iomem *)io_ports->data_addr);
-		else
-			outw(data, io_ports->data_addr);
-	}
-
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
-		tf_outb(tf->hob_feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
-		tf_outb(tf->hob_nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
-		tf_outb(tf->hob_lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
-		tf_outb(tf->hob_lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
-		tf_outb(tf->hob_lbah, io_ports->lbah_addr);
-
-	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
-		tf_outb(tf->feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
-		tf_outb(tf->nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
-		tf_outb(tf->lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
-		tf_outb(tf->lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
-		tf_outb(tf->lbah, io_ports->lbah_addr);
-
-	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-		tf_outb((tf->device & HIHI) | drive->select,
-			 io_ports->device_addr);
-}
-EXPORT_SYMBOL_GPL(ide_tf_load);
-
-void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
-	void (*tf_outb)(u8 addr, unsigned long port);
-	u8 (*tf_inb)(unsigned long port);
-	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-
-	if (mmio) {
-		tf_outb = ide_mm_outb;
-		tf_inb  = ide_mm_inb;
-	} else {
-		tf_outb = ide_outb;
-		tf_inb  = ide_inb;
-	}
-
-	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
-		u16 data;
-
-		if (mmio)
-			data = readw((void __iomem *)io_ports->data_addr);
-		else
-			data = inw(io_ports->data_addr);
-
-		tf->data = data & 0xff;
-		tf->hob_data = (data >> 8) & 0xff;
-	}
-
-	/* be sure we're looking at the low order bits */
-	tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
-
-	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
-		tf->feature = tf_inb(io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
-		tf->nsect  = tf_inb(io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
-		tf->lbal   = tf_inb(io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
-		tf->lbam   = tf_inb(io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
-		tf->lbah   = tf_inb(io_ports->lbah_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
-		tf->device = tf_inb(io_ports->device_addr);
-
-	if (task->tf_flags & IDE_TFLAG_LBA48) {
-		tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
-
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
-			tf->hob_feature = tf_inb(io_ports->feature_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
-			tf->hob_nsect   = tf_inb(io_ports->nsect_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
-			tf->hob_lbal    = tf_inb(io_ports->lbal_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
-			tf->hob_lbam    = tf_inb(io_ports->lbam_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
-			tf->hob_lbah    = tf_inb(io_ports->lbah_addr);
-	}
-}
-EXPORT_SYMBOL_GPL(ide_tf_read);
-
-/*
- * Some localbus EIDE interfaces require a special access sequence
- * when using 32-bit I/O instructions to transfer data.  We call this
- * the "vlb_sync" sequence, which consists of three successive reads
- * of the sector count register location, with interrupts disabled
- * to ensure that the reads all happen together.
- */
-static void ata_vlb_sync(unsigned long port)
-{
-	(void)inb(port);
-	(void)inb(port);
-	(void)inb(port);
-}
-
-/*
- * This is used for most PIO data transfers *from* the IDE interface
- *
- * These routines will round up any request for an odd number of bytes,
- * so if an odd len is specified, be sure that there's at least one
- * extra byte allocated for the buffer.
- */
-void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
-		    unsigned int len)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	struct ide_io_ports *io_ports = &hwif->io_ports;
-	unsigned long data_addr = io_ports->data_addr;
-	u8 io_32bit = drive->io_32bit;
-	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-
-	len++;
-
-	if (io_32bit) {
-		unsigned long uninitialized_var(flags);
-
-		if ((io_32bit & 2) && !mmio) {
-			local_irq_save(flags);
-			ata_vlb_sync(io_ports->nsect_addr);
-		}
-
-		if (mmio)
-			__ide_mm_insl((void __iomem *)data_addr, buf, len / 4);
-		else
-			insl(data_addr, buf, len / 4);
-
-		if ((io_32bit & 2) && !mmio)
-			local_irq_restore(flags);
-
-		if ((len & 3) >= 2) {
-			if (mmio)
-				__ide_mm_insw((void __iomem *)data_addr,
-						(u8 *)buf + (len & ~3), 1);
-			else
-				insw(data_addr, (u8 *)buf + (len & ~3), 1);
-		}
-	} else {
-		if (mmio)
-			__ide_mm_insw((void __iomem *)data_addr, buf, len / 2);
-		else
-			insw(data_addr, buf, len / 2);
-	}
-}
-EXPORT_SYMBOL_GPL(ide_input_data);
-
-/*
- * This is used for most PIO data transfers *to* the IDE interface
- */
-void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
-		     unsigned int len)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	struct ide_io_ports *io_ports = &hwif->io_ports;
-	unsigned long data_addr = io_ports->data_addr;
-	u8 io_32bit = drive->io_32bit;
-	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-
-	if (io_32bit) {
-		unsigned long uninitialized_var(flags);
-
-		if ((io_32bit & 2) && !mmio) {
-			local_irq_save(flags);
-			ata_vlb_sync(io_ports->nsect_addr);
-		}
-
-		if (mmio)
-			__ide_mm_outsl((void __iomem *)data_addr, buf, len / 4);
-		else
-			outsl(data_addr, buf, len / 4);
-
-		if ((io_32bit & 2) && !mmio)
-			local_irq_restore(flags);
-
-		if ((len & 3) >= 2) {
-			if (mmio)
-				__ide_mm_outsw((void __iomem *)data_addr,
-						 (u8 *)buf + (len & ~3), 1);
-			else
-				outsw(data_addr, (u8 *)buf + (len & ~3), 1);
-		}
-	} else {
-		if (mmio)
-			__ide_mm_outsw((void __iomem *)data_addr, buf, len / 2);
-		else
-			outsw(data_addr, buf, len / 2);
-	}
-}
-EXPORT_SYMBOL_GPL(ide_output_data);
-
 u8 ide_read_error(ide_drive_t *drive)
 {
 	ide_task_t task;
@@ -360,35 +63,6 @@
 }
 EXPORT_SYMBOL_GPL(ide_read_error);
 
-void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
-{
-	ide_task_t task;
-
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
-			IDE_TFLAG_IN_NSECT;
-
-	drive->hwif->tp_ops->tf_read(drive, &task);
-
-	*bcount = (task.tf.lbah << 8) | task.tf.lbam;
-	*ireason = task.tf.nsect & 3;
-}
-EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
-
-const struct ide_tp_ops default_tp_ops = {
-	.exec_command		= ide_exec_command,
-	.read_status		= ide_read_status,
-	.read_altstatus		= ide_read_altstatus,
-
-	.set_irq		= ide_set_irq,
-
-	.tf_load		= ide_tf_load,
-	.tf_read		= ide_tf_read,
-
-	.input_data		= ide_input_data,
-	.output_data		= ide_output_data,
-};
-
 void ide_fix_driveid(u16 *id)
 {
 #ifndef __LITTLE_ENDIAN
@@ -410,7 +84,7 @@
  * returned by the ATA_CMD_ID_ATA[PI] commands.
  */
 
-void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
+void ide_fixstring(u8 *s, const int bytecount, const int byteswap)
 {
 	u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */
 
@@ -433,44 +107,9 @@
 	while (p != end)
 		*p++ = '\0';
 }
-
 EXPORT_SYMBOL(ide_fixstring);
 
 /*
- * Needed for PCI irq sharing
- */
-int drive_is_ready (ide_drive_t *drive)
-{
-	ide_hwif_t *hwif	= drive->hwif;
-	u8 stat			= 0;
-
-	if (drive->waiting_for_dma)
-		return hwif->dma_ops->dma_test_irq(drive);
-
-	/*
-	 * We do a passive status test under shared PCI interrupts on
-	 * cards that truly share the ATA side interrupt, but may also share
-	 * an interrupt with another pci card/device.  We make no assumptions
-	 * about possible isa-pnp and pci-pnp issues yet.
-	 */
-	if (hwif->io_ports.ctl_addr &&
-	    (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0)
-		stat = hwif->tp_ops->read_altstatus(hwif);
-	else
-		/* Note: this may clear a pending IRQ!! */
-		stat = hwif->tp_ops->read_status(hwif);
-
-	if (stat & ATA_BUSY)
-		/* drive busy:  definitely not interrupting */
-		return 0;
-
-	/* drive ready: *might* be interrupting */
-	return 1;
-}
-
-EXPORT_SYMBOL(drive_is_ready);
-
-/*
  * This routine busy-waits for the drive status to be not "busy".
  * It then checks the status for all of the "good" bits and none
  * of the "bad" bits, and if all is okay it returns 0.  All other
@@ -481,7 +120,8 @@
  * setting a timer to wake up at half second intervals thereafter,
  * until timeout is achieved, before timing out.
  */
-static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
+static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad,
+			   unsigned long timeout, u8 *rstat)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
@@ -539,7 +179,8 @@
  * The caller should return the updated value of "startstop" in this case,
  * "startstop" is unchanged when the function returns 0.
  */
-int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout)
+int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good,
+		  u8 bad, unsigned long timeout)
 {
 	int err;
 	u8 stat;
@@ -559,7 +200,6 @@
 
 	return err;
 }
-
 EXPORT_SYMBOL(ide_wait_stat);
 
 /**
@@ -580,7 +220,6 @@
 			return 1;
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(ide_in_drive_list);
 
 /*
@@ -605,7 +244,7 @@
  *  All hosts that use the 80c ribbon must use!
  *  The name is derived from upper byte of word 93 and the 80c ribbon.
  */
-u8 eighty_ninty_three (ide_drive_t *drive)
+u8 eighty_ninty_three(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	u16 *id = drive->id;
@@ -650,47 +289,19 @@
 
 int ide_driveid_update(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
-	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	u16 *id;
-	unsigned long flags;
-	u8 stat;
+	int rc;
 
-	/*
-	 * Re-read drive->id for possible DMA mode
-	 * change (copied from ide-probe.c)
-	 */
+	id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
+	if (id == NULL)
+		return 0;
 
 	SELECT_MASK(drive, 1);
-	tp_ops->set_irq(hwif, 0);
-	msleep(50);
-	tp_ops->exec_command(hwif, ATA_CMD_ID_ATA);
-
-	if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) {
-		SELECT_MASK(drive, 0);
-		return 0;
-	}
-
-	msleep(50);	/* wait for IRQ and ATA_DRQ */
-	stat = tp_ops->read_status(hwif);
-
-	if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) {
-		SELECT_MASK(drive, 0);
-		printk("%s: CHECK for good STATUS\n", drive->name);
-		return 0;
-	}
-	local_irq_save(flags);
+	rc = ide_dev_read_id(drive, ATA_CMD_ID_ATA, id);
 	SELECT_MASK(drive, 0);
-	id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
-	if (!id) {
-		local_irq_restore(flags);
-		return 0;
-	}
-	tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
-	(void)tp_ops->read_status(hwif);	/* clear drive IRQ */
-	local_irq_enable();
-	local_irq_restore(flags);
-	ide_fix_driveid(id);
+
+	if (rc)
+		goto out_err;
 
 	drive->id[ATA_ID_UDMA_MODES]  = id[ATA_ID_UDMA_MODES];
 	drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES];
@@ -703,6 +314,12 @@
 		ide_dma_off(drive);
 
 	return 1;
+out_err:
+	SELECT_MASK(drive, 0);
+	if (rc == 2)
+		printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__);
+	kfree(id);
+	return 0;
 }
 
 int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
@@ -729,18 +346,15 @@
 	 * but for some reason these don't work at
 	 * this point (lost interrupt).
 	 */
-        /*
-         * Select the drive, and issue the SETFEATURES command
-         */
-	disable_irq_nosync(hwif->irq);
-	
+
 	/*
 	 *	FIXME: we race against the running IRQ here if
 	 *	this is called from non IRQ context. If we use
 	 *	disable_irq() we hang on the error path. Work
 	 *	is needed.
 	 */
-	 
+	disable_irq_nosync(hwif->irq);
+
 	udelay(1);
 	SELECT_DRIVE(drive);
 	SELECT_MASK(drive, 1);
@@ -810,8 +424,8 @@
  *
  * See also ide_execute_command
  */
-static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
-		      unsigned int timeout, ide_expiry_t *expiry)
+void __ide_set_handler(ide_drive_t *drive, ide_handler_t *handler,
+		       unsigned int timeout, ide_expiry_t *expiry)
 {
 	ide_hwif_t *hwif = drive->hwif;
 
@@ -833,9 +447,8 @@
 	__ide_set_handler(drive, handler, timeout, expiry);
 	spin_unlock_irqrestore(&hwif->lock, flags);
 }
-
 EXPORT_SYMBOL(ide_set_handler);
- 
+
 /**
  *	ide_execute_command	-	execute an IDE command
  *	@drive: IDE drive to issue the command against
@@ -845,7 +458,7 @@
  *	@expiry:  handler to run on timeout
  *
  *	Helper function to issue an IDE command. This handles the
- *	atomicity requirements, command timing and ensures that the 
+ *	atomicity requirements, command timing and ensures that the
  *	handler and IRQ setup do not race. All IDE command kick off
  *	should go via this function or do equivalent locking.
  */
@@ -882,301 +495,6 @@
 }
 EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
 
-static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
-{
-	struct request *rq = drive->hwif->rq;
-
-	if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
-		ide_end_request(drive, err ? err : 1, 0);
-}
-
-/* needed below */
-static ide_startstop_t do_reset1 (ide_drive_t *, int);
-
-/*
- * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms
- * during an atapi drive reset operation. If the drive has not yet responded,
- * and we have not yet hit our maximum waiting time, then the timer is restarted
- * for another 50ms.
- */
-static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	u8 stat;
-
-	SELECT_DRIVE(drive);
-	udelay (10);
-	stat = hwif->tp_ops->read_status(hwif);
-
-	if (OK_STAT(stat, 0, ATA_BUSY))
-		printk("%s: ATAPI reset complete\n", drive->name);
-	else {
-		if (time_before(jiffies, hwif->poll_timeout)) {
-			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
-			/* continue polling */
-			return ide_started;
-		}
-		/* end of polling */
-		hwif->polling = 0;
-		printk("%s: ATAPI reset timed-out, status=0x%02x\n",
-				drive->name, stat);
-		/* do it the old fashioned way */
-		return do_reset1(drive, 1);
-	}
-	/* done polling */
-	hwif->polling = 0;
-	ide_complete_drive_reset(drive, 0);
-	return ide_stopped;
-}
-
-static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
-{
-	static const char *err_master_vals[] =
-		{ NULL, "passed", "formatter device error",
-		  "sector buffer error", "ECC circuitry error",
-		  "controlling MPU error" };
-
-	u8 err_master = err & 0x7f;
-
-	printk(KERN_ERR "%s: reset: master: ", hwif->name);
-	if (err_master && err_master < 6)
-		printk(KERN_CONT "%s", err_master_vals[err_master]);
-	else
-		printk(KERN_CONT "error (0x%02x?)", err);
-	if (err & 0x80)
-		printk(KERN_CONT "; slave: failed");
-	printk(KERN_CONT "\n");
-}
-
-/*
- * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
- * during an ide reset operation. If the drives have not yet responded,
- * and we have not yet hit our maximum waiting time, then the timer is restarted
- * for another 50ms.
- */
-static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	const struct ide_port_ops *port_ops = hwif->port_ops;
-	u8 tmp;
-	int err = 0;
-
-	if (port_ops && port_ops->reset_poll) {
-		err = port_ops->reset_poll(drive);
-		if (err) {
-			printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
-				hwif->name, drive->name);
-			goto out;
-		}
-	}
-
-	tmp = hwif->tp_ops->read_status(hwif);
-
-	if (!OK_STAT(tmp, 0, ATA_BUSY)) {
-		if (time_before(jiffies, hwif->poll_timeout)) {
-			ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
-			/* continue polling */
-			return ide_started;
-		}
-		printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
-		drive->failures++;
-		err = -EIO;
-	} else  {
-		tmp = ide_read_error(drive);
-
-		if (tmp == 1) {
-			printk(KERN_INFO "%s: reset: success\n", hwif->name);
-			drive->failures = 0;
-		} else {
-			ide_reset_report_error(hwif, tmp);
-			drive->failures++;
-			err = -EIO;
-		}
-	}
-out:
-	hwif->polling = 0;	/* done polling */
-	ide_complete_drive_reset(drive, err);
-	return ide_stopped;
-}
-
-static void ide_disk_pre_reset(ide_drive_t *drive)
-{
-	int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1;
-
-	drive->special.all = 0;
-	drive->special.b.set_geometry = legacy;
-	drive->special.b.recalibrate  = legacy;
-
-	drive->mult_count = 0;
-	drive->dev_flags &= ~IDE_DFLAG_PARKED;
-
-	if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
-	    (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
-		drive->mult_req = 0;
-
-	if (drive->mult_req != drive->mult_count)
-		drive->special.b.set_multmode = 1;
-}
-
-static void pre_reset(ide_drive_t *drive)
-{
-	const struct ide_port_ops *port_ops = drive->hwif->port_ops;
-
-	if (drive->media == ide_disk)
-		ide_disk_pre_reset(drive);
-	else
-		drive->dev_flags |= IDE_DFLAG_POST_RESET;
-
-	if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
-		if (drive->crc_count)
-			ide_check_dma_crc(drive);
-		else
-			ide_dma_off(drive);
-	}
-
-	if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
-		if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
-			drive->dev_flags &= ~IDE_DFLAG_UNMASK;
-			drive->io_32bit = 0;
-		}
-		return;
-	}
-
-	if (port_ops && port_ops->pre_reset)
-		port_ops->pre_reset(drive);
-
-	if (drive->current_speed != 0xff)
-		drive->desired_speed = drive->current_speed;
-	drive->current_speed = 0xff;
-}
-
-/*
- * do_reset1() attempts to recover a confused drive by resetting it.
- * Unfortunately, resetting a disk drive actually resets all devices on
- * the same interface, so it can really be thought of as resetting the
- * interface rather than resetting the drive.
- *
- * ATAPI devices have their own reset mechanism which allows them to be
- * individually reset without clobbering other devices on the same interface.
- *
- * Unfortunately, the IDE interface does not generate an interrupt to let
- * us know when the reset operation has finished, so we must poll for this.
- * Equally poor, though, is the fact that this may a very long time to complete,
- * (up to 30 seconds worstcase).  So, instead of busy-waiting here for it,
- * we set a timer to poll at 50ms intervals.
- */
-static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	struct ide_io_ports *io_ports = &hwif->io_ports;
-	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
-	const struct ide_port_ops *port_ops;
-	ide_drive_t *tdrive;
-	unsigned long flags, timeout;
-	int i;
-	DEFINE_WAIT(wait);
-
-	spin_lock_irqsave(&hwif->lock, flags);
-
-	/* We must not reset with running handlers */
-	BUG_ON(hwif->handler != NULL);
-
-	/* For an ATAPI device, first try an ATAPI SRST. */
-	if (drive->media != ide_disk && !do_not_try_atapi) {
-		pre_reset(drive);
-		SELECT_DRIVE(drive);
-		udelay (20);
-		tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
-		ndelay(400);
-		hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
-		hwif->polling = 1;
-		__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
-		spin_unlock_irqrestore(&hwif->lock, flags);
-		return ide_started;
-	}
-
-	/* We must not disturb devices in the IDE_DFLAG_PARKED state. */
-	do {
-		unsigned long now;
-
-		prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
-		timeout = jiffies;
-		ide_port_for_each_dev(i, tdrive, hwif) {
-			if (tdrive->dev_flags & IDE_DFLAG_PRESENT &&
-			    tdrive->dev_flags & IDE_DFLAG_PARKED &&
-			    time_after(tdrive->sleep, timeout))
-				timeout = tdrive->sleep;
-		}
-
-		now = jiffies;
-		if (time_before_eq(timeout, now))
-			break;
-
-		spin_unlock_irqrestore(&hwif->lock, flags);
-		timeout = schedule_timeout_uninterruptible(timeout - now);
-		spin_lock_irqsave(&hwif->lock, flags);
-	} while (timeout);
-	finish_wait(&ide_park_wq, &wait);
-
-	/*
-	 * First, reset any device state data we were maintaining
-	 * for any of the drives on this interface.
-	 */
-	ide_port_for_each_dev(i, tdrive, hwif)
-		pre_reset(tdrive);
-
-	if (io_ports->ctl_addr == 0) {
-		spin_unlock_irqrestore(&hwif->lock, flags);
-		ide_complete_drive_reset(drive, -ENXIO);
-		return ide_stopped;
-	}
-
-	/*
-	 * Note that we also set nIEN while resetting the device,
-	 * to mask unwanted interrupts from the interface during the reset.
-	 * However, due to the design of PC hardware, this will cause an
-	 * immediate interrupt due to the edge transition it produces.
-	 * This single interrupt gives us a "fast poll" for drives that
-	 * recover from reset very quickly, saving us the first 50ms wait time.
-	 *
-	 * TODO: add ->softreset method and stop abusing ->set_irq
-	 */
-	/* set SRST and nIEN */
-	tp_ops->set_irq(hwif, 4);
-	/* more than enough time */
-	udelay(10);
-	/* clear SRST, leave nIEN (unless device is on the quirk list) */
-	tp_ops->set_irq(hwif, drive->quirk_list == 2);
-	/* more than enough time */
-	udelay(10);
-	hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
-	hwif->polling = 1;
-	__ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
-
-	/*
-	 * Some weird controller like resetting themselves to a strange
-	 * state when the disks are reset this way. At least, the Winbond
-	 * 553 documentation says that
-	 */
-	port_ops = hwif->port_ops;
-	if (port_ops && port_ops->resetproc)
-		port_ops->resetproc(drive);
-
-	spin_unlock_irqrestore(&hwif->lock, flags);
-	return ide_started;
-}
-
-/*
- * ide_do_reset() is the entry point to the drive/interface reset code.
- */
-
-ide_startstop_t ide_do_reset (ide_drive_t *drive)
-{
-	return do_reset1(drive, 0);
-}
-
-EXPORT_SYMBOL(ide_do_reset);
-
 /*
  * ide_wait_not_busy() waits for the currently selected device on the hwif
  * to report a non-busy status, see comments in ide_probe_port().
@@ -1185,7 +503,7 @@
 {
 	u8 stat = 0;
 
-	while(timeout--) {
+	while (timeout--) {
 		/*
 		 * Turn this into a schedule() sleep once I'm sure
 		 * about locking issues (2.5 work ?).
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 09526a0..f6c683d 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -5,163 +5,6 @@
 #include <linux/ide.h>
 #include <linux/bitops.h>
 
-static const char *udma_str[] =
-	 { "UDMA/16", "UDMA/25",  "UDMA/33",  "UDMA/44",
-	   "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
-static const char *mwdma_str[] =
-	{ "MWDMA0", "MWDMA1", "MWDMA2" };
-static const char *swdma_str[] =
-	{ "SWDMA0", "SWDMA1", "SWDMA2" };
-static const char *pio_str[] =
-	{ "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
-
-/**
- *	ide_xfer_verbose	-	return IDE mode names
- *	@mode: transfer mode
- *
- *	Returns a constant string giving the name of the mode
- *	requested.
- */
-
-const char *ide_xfer_verbose(u8 mode)
-{
-	const char *s;
-	u8 i = mode & 0xf;
-
-	if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
-		s = udma_str[i];
-	else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
-		s = mwdma_str[i];
-	else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
-		s = swdma_str[i];
-	else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
-		s = pio_str[i & 0x7];
-	else if (mode == XFER_PIO_SLOW)
-		s = "PIO SLOW";
-	else
-		s = "XFER ERROR";
-
-	return s;
-}
-EXPORT_SYMBOL(ide_xfer_verbose);
-
-/**
- *	ide_rate_filter		-	filter transfer mode
- *	@drive: IDE device
- *	@speed: desired speed
- *
- *	Given the available transfer modes this function returns
- *	the best available speed at or below the speed requested.
- *
- *	TODO: check device PIO capabilities
- */
-
-static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	u8 mode = ide_find_dma_mode(drive, speed);
-
-	if (mode == 0) {
-		if (hwif->pio_mask)
-			mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0;
-		else
-			mode = XFER_PIO_4;
-	}
-
-/*	printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */
-
-	return min(speed, mode);
-}
-
-/**
- *	ide_get_best_pio_mode	-	get PIO mode from drive
- *	@drive: drive to consider
- *	@mode_wanted: preferred mode
- *	@max_mode: highest allowed mode
- *
- *	This routine returns the recommended PIO settings for a given drive,
- *	based on the drive->id information and the ide_pio_blacklist[].
- *
- *	Drive PIO mode is auto-selected if 255 is passed as mode_wanted.
- *	This is used by most chipset support modules when "auto-tuning".
- */
-
-u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
-{
-	u16 *id = drive->id;
-	int pio_mode = -1, overridden = 0;
-
-	if (mode_wanted != 255)
-		return min_t(u8, mode_wanted, max_mode);
-
-	if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
-		pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
-
-	if (pio_mode != -1) {
-		printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
-	} else {
-		pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
-		if (pio_mode > 2) {	/* 2 is maximum allowed tPIO value */
-			pio_mode = 2;
-			overridden = 1;
-		}
-
-		if (id[ATA_ID_FIELD_VALID] & 2) {	      /* ATA2? */
-			if (ata_id_has_iordy(id)) {
-				if (id[ATA_ID_PIO_MODES] & 7) {
-					overridden = 0;
-					if (id[ATA_ID_PIO_MODES] & 4)
-						pio_mode = 5;
-					else if (id[ATA_ID_PIO_MODES] & 2)
-						pio_mode = 4;
-					else
-						pio_mode = 3;
-				}
-			}
-		}
-
-		if (overridden)
-			printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
-					 drive->name);
-	}
-
-	if (pio_mode > max_mode)
-		pio_mode = max_mode;
-
-	return pio_mode;
-}
-EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
-
-/* req_pio == "255" for auto-tune */
-void ide_set_pio(ide_drive_t *drive, u8 req_pio)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	const struct ide_port_ops *port_ops = hwif->port_ops;
-	u8 host_pio, pio;
-
-	if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
-	    (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
-		return;
-
-	BUG_ON(hwif->pio_mask == 0x00);
-
-	host_pio = fls(hwif->pio_mask) - 1;
-
-	pio = ide_get_best_pio_mode(drive, req_pio, host_pio);
-
-	/*
-	 * TODO:
-	 * - report device max PIO mode
-	 * - check req_pio != 255 against device max PIO mode
-	 */
-	printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n",
-			  drive->name, host_pio, req_pio,
-			  req_pio == 255 ? "(auto-tune)" : "", pio);
-
-	(void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
-}
-EXPORT_SYMBOL_GPL(ide_set_pio);
-
 /**
  *	ide_toggle_bounce	-	handle bounce buffering
  *	@drive: drive to update
@@ -188,89 +31,6 @@
 		blk_queue_bounce_limit(drive->queue, addr);
 }
 
-int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	const struct ide_port_ops *port_ops = hwif->port_ops;
-
-	if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
-		return 0;
-
-	if (port_ops == NULL || port_ops->set_pio_mode == NULL)
-		return -1;
-
-	/*
-	 * TODO: temporary hack for some legacy host drivers that didn't
-	 * set transfer mode on the device in ->set_pio_mode method...
-	 */
-	if (port_ops->set_dma_mode == NULL) {
-		port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
-		return 0;
-	}
-
-	if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
-		if (ide_config_drive_speed(drive, mode))
-			return -1;
-		port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
-		return 0;
-	} else {
-		port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
-		return ide_config_drive_speed(drive, mode);
-	}
-}
-
-int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	const struct ide_port_ops *port_ops = hwif->port_ops;
-
-	if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
-		return 0;
-
-	if (port_ops == NULL || port_ops->set_dma_mode == NULL)
-		return -1;
-
-	if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
-		if (ide_config_drive_speed(drive, mode))
-			return -1;
-		port_ops->set_dma_mode(drive, mode);
-		return 0;
-	} else {
-		port_ops->set_dma_mode(drive, mode);
-		return ide_config_drive_speed(drive, mode);
-	}
-}
-EXPORT_SYMBOL_GPL(ide_set_dma_mode);
-
-/**
- *	ide_set_xfer_rate	-	set transfer rate
- *	@drive: drive to set
- *	@rate: speed to attempt to set
- *
- *	General helper for setting the speed of an IDE device. This
- *	function knows about user enforced limits from the configuration
- *	which ->set_pio_mode/->set_dma_mode does not.
- */
-
-int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	const struct ide_port_ops *port_ops = hwif->port_ops;
-
-	if (port_ops == NULL || port_ops->set_dma_mode == NULL ||
-	    (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
-		return -1;
-
-	rate = ide_rate_filter(drive, rate);
-
-	BUG_ON(rate < XFER_PIO_0);
-
-	if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
-		return ide_set_pio_mode(drive, rate);
-
-	return ide_set_dma_mode(drive, rate);
-}
-
 static void ide_dump_opcode(ide_drive_t *drive)
 {
 	struct request *rq = drive->hwif->rq;
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index c875a95..f30e521 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -1,5 +1,6 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
+#include <linux/hdreg.h>
 #include <linux/jiffies.h>
 #include <linux/blkdev.h>
 
@@ -60,6 +61,30 @@
 	return;
 }
 
+ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq)
+{
+	ide_task_t task;
+	struct ide_taskfile *tf = &task.tf;
+
+	memset(&task, 0, sizeof(task));
+	if (rq->cmd[0] == REQ_PARK_HEADS) {
+		drive->sleep = *(unsigned long *)rq->special;
+		drive->dev_flags |= IDE_DFLAG_SLEEPING;
+		tf->command = ATA_CMD_IDLEIMMEDIATE;
+		tf->feature = 0x44;
+		tf->lbal = 0x4c;
+		tf->lbam = 0x4e;
+		tf->lbah = 0x55;
+		task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
+	} else		/* cmd == REQ_UNPARK_HEADS */
+		tf->command = ATA_CMD_CHK_POWER;
+
+	task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+	task.rq = rq;
+	drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
+	return do_rw_taskfile(drive, &task);
+}
+
 ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
diff --git a/drivers/ide/ide-pci-generic.c b/drivers/ide/ide-pci-generic.c
index bddae2b..61111fd 100644
--- a/drivers/ide/ide-pci-generic.c
+++ b/drivers/ide/ide-pci-generic.c
@@ -33,8 +33,6 @@
 module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
 MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
 
-#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS)
-
 #define DECLARE_GENERIC_PCI_DEV(extra_flags) \
 	{ \
 		.name		= DRV_NAME, \
@@ -61,7 +59,7 @@
 	/*  2: SAMURAI / HT6565 / HINT_IDE */
 	DECLARE_GENERIC_PCI_DEV(0),
 	/*  3: UM8673F / UM8886A / UM8886BF */
-	DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC),
+	DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_DMA),
 	/*  4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */
 	DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA),
 
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index ce0818a..9740670 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -181,16 +181,16 @@
  *	do_identify	-	identify a drive
  *	@drive: drive to identify 
  *	@cmd: command used
+ *	@id: buffer for IDENTIFY data
  *
  *	Called when we have issued a drive identify command to
  *	read and parse the results. This function is run with
  *	interrupts disabled. 
  */
 
-static void do_identify(ide_drive_t *drive, u8 cmd)
+static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	u16 *id = drive->id;
 	char *m = (char *)&id[ATA_ID_PROD];
 	unsigned long flags;
 	int bswap = 1;
@@ -233,16 +233,6 @@
 	drive->dev_flags |= IDE_DFLAG_PRESENT;
 	drive->dev_flags &= ~IDE_DFLAG_DEAD;
 
-	/*
-	 * Check for an ATAPI device
-	 */
-	if (cmd == ATA_CMD_ID_ATAPI)
-		ide_classify_atapi_dev(drive);
-	else
-	/*
-	 * Not an ATAPI device: looks like a "regular" hard disk
-	 */
-		ide_classify_ata_dev(drive);
 	return;
 err_misc:
 	kfree(id);
@@ -250,21 +240,19 @@
 }
 
 /**
- *	actual_try_to_identify	-	send ata/atapi identify
+ *	ide_dev_read_id	-	send ATA/ATAPI IDENTIFY command
  *	@drive: drive to identify
  *	@cmd: command to use
+ *	@id: buffer for IDENTIFY data
  *
- *	try_to_identify() sends an ATA(PI) IDENTIFY request to a drive
- *	and waits for a response.  It also monitors irqs while this is
- *	happening, in hope of automatically determining which one is
- *	being used by the interface.
+ *	Sends an ATA(PI) IDENTIFY request to a drive and waits for a response.
  *
  *	Returns:	0  device was identified
  *			1  device timed-out (no response to identify request)
  *			2  device aborted the command (refused to identify itself)
  */
 
-static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -273,6 +261,13 @@
 	unsigned long timeout;
 	u8 s = 0, a = 0;
 
+	/*
+	 * Disable device IRQ.  Otherwise we'll get spurious interrupts
+	 * during the identify phase that the IRQ handler isn't expecting.
+	 */
+	if (io_ports->ctl_addr)
+		tp_ops->set_irq(hwif, 0);
+
 	/* take a deep breath */
 	msleep(50);
 
@@ -317,7 +312,7 @@
 
 	if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
 		/* drive returned ID */
-		do_identify(drive, cmd);
+		do_identify(drive, cmd, id);
 		/* drive responded with ID */
 		rc = 0;
 		/* clear drive IRQ */
@@ -329,63 +324,6 @@
 	return rc;
 }
 
-/**
- *	try_to_identify	-	try to identify a drive
- *	@drive: drive to probe
- *	@cmd: command to use
- *
- *	Issue the identify command and then do IRQ probing to
- *	complete the identification when needed by finding the
- *	IRQ the drive is attached to
- */
- 
-static int try_to_identify (ide_drive_t *drive, u8 cmd)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
-	int retval;
-	int autoprobe = 0;
-	unsigned long cookie = 0;
-
-	/*
-	 * Disable device irq unless we need to
-	 * probe for it. Otherwise we'll get spurious
-	 * interrupts during the identify-phase that
-	 * the irq handler isn't expecting.
-	 */
-	if (hwif->io_ports.ctl_addr) {
-		if (!hwif->irq) {
-			autoprobe = 1;
-			cookie = probe_irq_on();
-		}
-		tp_ops->set_irq(hwif, autoprobe);
-	}
-
-	retval = actual_try_to_identify(drive, cmd);
-
-	if (autoprobe) {
-		int irq;
-
-		tp_ops->set_irq(hwif, 0);
-		/* clear drive IRQ */
-		(void)tp_ops->read_status(hwif);
-		udelay(5);
-		irq = probe_irq_off(cookie);
-		if (!hwif->irq) {
-			if (irq > 0) {
-				hwif->irq = irq;
-			} else {
-				/* Mmmm.. multiple IRQs..
-				 * don't know which was ours
-				 */
-				printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n",
-					drive->name, cookie);
-			}
-		}
-	}
-	return retval;
-}
-
 int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus)
 {
 	u8 stat;
@@ -440,6 +378,7 @@
 {
 	ide_hwif_t *hwif = drive->hwif;
 	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+	u16 *id = drive->id;
 	int rc;
 	u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
 
@@ -475,11 +414,10 @@
 
 	if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
 	    present || cmd == ATA_CMD_ID_ATAPI) {
-		/* send cmd and wait */
-		if ((rc = try_to_identify(drive, cmd))) {
+		rc = ide_dev_read_id(drive, cmd, id);
+		if (rc)
 			/* failed: try again */
-			rc = try_to_identify(drive,cmd);
-		}
+			rc = ide_dev_read_id(drive, cmd, id);
 
 		stat = tp_ops->read_status(hwif);
 
@@ -494,7 +432,7 @@
 			msleep(50);
 			tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
 			(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
-			rc = try_to_identify(drive, cmd);
+			rc = ide_dev_read_id(drive, cmd, id);
 		}
 
 		/* ensure drive IRQ is clear */
@@ -517,37 +455,6 @@
 	return rc;
 }
 
-/*
- *
- */
-static void enable_nest (ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
-	u8 stat;
-
-	printk(KERN_INFO "%s: enabling %s -- ",
-		hwif->name, (char *)&drive->id[ATA_ID_PROD]);
-
-	SELECT_DRIVE(drive);
-	msleep(50);
-	tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST);
-
-	if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) {
-		printk(KERN_CONT "failed (timeout)\n");
-		return;
-	}
-
-	msleep(50);
-
-	stat = tp_ops->read_status(hwif);
-
-	if (!OK_STAT(stat, 0, BAD_STAT))
-		printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
-	else
-		printk(KERN_CONT "success\n");
-}
-
 /**
  *	probe_for_drives	-	upper level drive probe
  *	@drive: drive to probe for
@@ -563,6 +470,8 @@
 static u8 probe_for_drive(ide_drive_t *drive)
 {
 	char *m;
+	int rc;
+	u8 cmd;
 
 	/*
 	 *	In order to keep things simple we have an id
@@ -586,21 +495,19 @@
 
 	/* skip probing? */
 	if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) {
-retry:
 		/* if !(success||timed-out) */
-		if (do_probe(drive, ATA_CMD_ID_ATA) >= 2)
+		cmd = ATA_CMD_ID_ATA;
+		rc = do_probe(drive, cmd);
+		if (rc >= 2) {
 			/* look for ATAPI device */
-			(void)do_probe(drive, ATA_CMD_ID_ATAPI);
+			cmd = ATA_CMD_ID_ATAPI;
+			rc = do_probe(drive, cmd);
+		}
 
 		if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
 			/* drive not found */
 			return 0;
 
-		if (strstr(m, "E X A B Y T E N E S T")) {
-			enable_nest(drive);
-			goto retry;
-		}
-
 		/* identification failed? */
 		if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
 			if (drive->media == ide_disk) {
@@ -614,8 +521,12 @@
 				printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
 				drive->dev_flags &= ~IDE_DFLAG_PRESENT;
 			}
+		} else {
+			if (cmd == ATA_CMD_ID_ATAPI)
+				ide_classify_atapi_dev(drive);
+			else
+				ide_classify_ata_dev(drive);
 		}
-		/* drive was found */
 	}
 
 	if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
@@ -779,7 +690,6 @@
 static int ide_probe_port(ide_hwif_t *hwif)
 {
 	ide_drive_t *drive;
-	unsigned long flags;
 	unsigned int irqd;
 	int i, rc = -ENODEV;
 
@@ -797,9 +707,6 @@
 	if (irqd)
 		disable_irq(hwif->irq);
 
-	local_save_flags(flags);
-	local_irq_enable_in_hardirq();
-
 	if (ide_port_wait_ready(hwif) == -EBUSY)
 		printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
 
@@ -813,8 +720,6 @@
 			rc = 0;
 	}
 
-	local_irq_restore(flags);
-
 	/*
 	 * Use cached IRQ number. It might be (and is...) changed by probe
 	 * code above
@@ -831,29 +736,18 @@
 	ide_drive_t *drive;
 	int i;
 
-	ide_port_for_each_dev(i, drive, hwif) {
-		if (drive->dev_flags & IDE_DFLAG_PRESENT) {
-			if (port_ops && port_ops->quirkproc)
-				port_ops->quirkproc(drive);
-		}
+	ide_port_for_each_present_dev(i, drive, hwif) {
+		if (port_ops && port_ops->quirkproc)
+			port_ops->quirkproc(drive);
 	}
 
-	ide_port_for_each_dev(i, drive, hwif) {
-		if (drive->dev_flags & IDE_DFLAG_PRESENT) {
-			ide_set_max_pio(drive);
+	ide_port_for_each_present_dev(i, drive, hwif) {
+		ide_set_max_pio(drive);
 
-			drive->dev_flags |= IDE_DFLAG_NICE1;
+		drive->dev_flags |= IDE_DFLAG_NICE1;
 
-			if (hwif->dma_ops)
-				ide_set_dma(drive);
-		}
-	}
-
-	ide_port_for_each_dev(i, drive, hwif) {
-		if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
-			drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
-		else
-			drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
+		if (hwif->dma_ops)
+			ide_set_dma(drive);
 	}
 }
 
@@ -924,10 +818,7 @@
 	int i, j = 0;
 
 	mutex_lock(&ide_cfg_mtx);
-	ide_port_for_each_dev(i, drive, hwif) {
-		if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
-			continue;
-
+	ide_port_for_each_present_dev(i, drive, hwif) {
 		if (ide_init_queue(drive)) {
 			printk(KERN_ERR "ide: failed to init %s\n",
 					drive->name);
@@ -950,14 +841,12 @@
 static int init_irq (ide_hwif_t *hwif)
 {
 	struct ide_io_ports *io_ports = &hwif->io_ports;
+	irq_handler_t irq_handler;
 	int sa = 0;
 
-	mutex_lock(&ide_cfg_mtx);
-	spin_lock_init(&hwif->lock);
-
-	init_timer(&hwif->timer);
-	hwif->timer.function = &ide_timer_expiry;
-	hwif->timer.data = (unsigned long)hwif;
+	irq_handler = hwif->host->irq_handler;
+	if (irq_handler == NULL)
+		irq_handler = ide_intr;
 
 #if defined(__mc68000__)
 	sa = IRQF_SHARED;
@@ -969,7 +858,7 @@
 	if (io_ports->ctl_addr)
 		hwif->tp_ops->set_irq(hwif, 1);
 
-	if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif))
+	if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif))
 		goto out_up;
 
 	if (!hwif->rqsize) {
@@ -992,10 +881,8 @@
 		printk(KERN_CONT " (serialized)");
 	printk(KERN_CONT "\n");
 
-	mutex_unlock(&ide_cfg_mtx);
 	return 0;
 out_up:
-	mutex_unlock(&ide_cfg_mtx);
 	return 1;
 }
 
@@ -1094,14 +981,9 @@
 
 static int hwif_init(ide_hwif_t *hwif)
 {
-	int old_irq;
-
 	if (!hwif->irq) {
-		hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
-		if (!hwif->irq) {
-			printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name);
-			return 0;
-		}
+		printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name);
+		return 0;
 	}
 
 	if (register_blkdev(hwif->major, hwif->name))
@@ -1119,29 +1001,12 @@
 
 	sg_init_table(hwif->sg_table, hwif->sg_max_nents);
 	
-	if (init_irq(hwif) == 0)
-		goto done;
-
-	old_irq = hwif->irq;
-	/*
-	 *	It failed to initialise. Find the default IRQ for 
-	 *	this port and try that.
-	 */
-	hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
-	if (!hwif->irq) {
-		printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n",
-			hwif->name, old_irq);
-		goto out;
-	}
 	if (init_irq(hwif)) {
-		printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n",
-			hwif->name, old_irq, hwif->irq);
+		printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n",
+			hwif->name, hwif->irq);
 		goto out;
 	}
-	printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n",
-		hwif->name, hwif->irq);
 
-done:
 	blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
 			    THIS_MODULE, ata_probe, ata_lock, hwif);
 	return 1;
@@ -1156,13 +1021,10 @@
 	ide_drive_t *drive;
 	unsigned int i;
 
-	ide_port_for_each_dev(i, drive, hwif) {
+	ide_port_for_each_present_dev(i, drive, hwif) {
 		struct device *dev = &drive->gendev;
 		int ret;
 
-		if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
-			continue;
-
 		dev_set_name(dev, "%u.%u", hwif->index, i);
 		dev->parent = &hwif->gendev;
 		dev->bus = &ide_bus_type;
@@ -1187,6 +1049,8 @@
 
 		if (hwif->host_flags & IDE_HFLAG_IO_32BIT)
 			drive->io_32bit = 1;
+		if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
+			drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
 		if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS)
 			drive->dev_flags |= IDE_DFLAG_UNMASK;
 		if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
@@ -1208,10 +1072,6 @@
 	if (d->init_iops)
 		d->init_iops(hwif);
 
-	if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
-	    (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
-		hwif->irq = port ? 15 : 14;
-
 	/* ->host_flags may be set by ->init_iops (or even earlier...) */
 	hwif->host_flags |= d->host_flags;
 	hwif->pio_mask = d->pio_mask;
@@ -1312,6 +1172,12 @@
 	hwif->name[2]	= 'e';
 	hwif->name[3]	= '0' + index;
 
+	spin_lock_init(&hwif->lock);
+
+	init_timer(&hwif->timer);
+	hwif->timer.function = &ide_timer_expiry;
+	hwif->timer.data = (unsigned long)hwif;
+
 	init_completion(&hwif->gendev_rel_comp);
 
 	hwif->tp_ops = &default_tp_ops;
@@ -1562,7 +1428,7 @@
 
 		j++;
 
-		ide_acpi_init(hwif);
+		ide_acpi_init_port(hwif);
 
 		if (hwif->present)
 			ide_acpi_port_init_devices(hwif);
@@ -1619,11 +1485,9 @@
 	ide_drive_t *drive;
 	int i;
 
-	ide_port_for_each_dev(i, drive, hwif) {
-		if (drive->dev_flags & IDE_DFLAG_PRESENT) {
-			device_unregister(&drive->gendev);
-			wait_for_completion(&drive->gendev_rel_comp);
-		}
+	ide_port_for_each_present_dev(i, drive, hwif) {
+		device_unregister(&drive->gendev);
+		wait_for_completion(&drive->gendev_rel_comp);
 	}
 }
 
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 1d8978b..417cde5 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -231,7 +231,7 @@
 	IDE_PROC_DEVSET(pio_mode, 0, 255),
 	IDE_PROC_DEVSET(unmaskirq, 0, 1),
 	IDE_PROC_DEVSET(using_dma, 0, 1),
-	{ 0 },
+	{ NULL },
 };
 
 static void proc_ide_settings_warn(void)
@@ -600,7 +600,7 @@
 	int i;
 
 	ide_port_for_each_dev(i, drive, hwif) {
-		if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc)
+		if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
 			continue;
 
 		drive->proc = proc_mkdir(drive->name, parent);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index bb450a7..4e6181c 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2166,7 +2166,7 @@
 	__IDE_PROC_DEVSET(speed,	0, 0xffff, NULL, NULL),
 	__IDE_PROC_DEVSET(tdsc,		IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
 					mulf_tdsc, divf_tdsc),
-	{ 0 },
+	{ NULL },
 };
 #endif
 
diff --git a/drivers/ide/ide-xfer-mode.c b/drivers/ide/ide-xfer-mode.c
new file mode 100644
index 0000000..6910f6a
--- /dev/null
+++ b/drivers/ide/ide-xfer-mode.c
@@ -0,0 +1,246 @@
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/ide.h>
+#include <linux/bitops.h>
+
+static const char *udma_str[] =
+	 { "UDMA/16", "UDMA/25",  "UDMA/33",  "UDMA/44",
+	   "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
+static const char *mwdma_str[] =
+	{ "MWDMA0", "MWDMA1", "MWDMA2" };
+static const char *swdma_str[] =
+	{ "SWDMA0", "SWDMA1", "SWDMA2" };
+static const char *pio_str[] =
+	{ "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
+
+/**
+ *	ide_xfer_verbose	-	return IDE mode names
+ *	@mode: transfer mode
+ *
+ *	Returns a constant string giving the name of the mode
+ *	requested.
+ */
+
+const char *ide_xfer_verbose(u8 mode)
+{
+	const char *s;
+	u8 i = mode & 0xf;
+
+	if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
+		s = udma_str[i];
+	else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
+		s = mwdma_str[i];
+	else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
+		s = swdma_str[i];
+	else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
+		s = pio_str[i & 0x7];
+	else if (mode == XFER_PIO_SLOW)
+		s = "PIO SLOW";
+	else
+		s = "XFER ERROR";
+
+	return s;
+}
+EXPORT_SYMBOL(ide_xfer_verbose);
+
+/**
+ *	ide_get_best_pio_mode	-	get PIO mode from drive
+ *	@drive: drive to consider
+ *	@mode_wanted: preferred mode
+ *	@max_mode: highest allowed mode
+ *
+ *	This routine returns the recommended PIO settings for a given drive,
+ *	based on the drive->id information and the ide_pio_blacklist[].
+ *
+ *	Drive PIO mode is auto-selected if 255 is passed as mode_wanted.
+ *	This is used by most chipset support modules when "auto-tuning".
+ */
+
+u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
+{
+	u16 *id = drive->id;
+	int pio_mode = -1, overridden = 0;
+
+	if (mode_wanted != 255)
+		return min_t(u8, mode_wanted, max_mode);
+
+	if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
+		pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
+
+	if (pio_mode != -1) {
+		printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
+	} else {
+		pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
+		if (pio_mode > 2) {	/* 2 is maximum allowed tPIO value */
+			pio_mode = 2;
+			overridden = 1;
+		}
+
+		if (id[ATA_ID_FIELD_VALID] & 2) {	      /* ATA2? */
+			if (ata_id_has_iordy(id)) {
+				if (id[ATA_ID_PIO_MODES] & 7) {
+					overridden = 0;
+					if (id[ATA_ID_PIO_MODES] & 4)
+						pio_mode = 5;
+					else if (id[ATA_ID_PIO_MODES] & 2)
+						pio_mode = 4;
+					else
+						pio_mode = 3;
+				}
+			}
+		}
+
+		if (overridden)
+			printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
+					 drive->name);
+	}
+
+	if (pio_mode > max_mode)
+		pio_mode = max_mode;
+
+	return pio_mode;
+}
+EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
+
+int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_port_ops *port_ops = hwif->port_ops;
+
+	if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+		return 0;
+
+	if (port_ops == NULL || port_ops->set_pio_mode == NULL)
+		return -1;
+
+	/*
+	 * TODO: temporary hack for some legacy host drivers that didn't
+	 * set transfer mode on the device in ->set_pio_mode method...
+	 */
+	if (port_ops->set_dma_mode == NULL) {
+		port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+		return 0;
+	}
+
+	if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
+		if (ide_config_drive_speed(drive, mode))
+			return -1;
+		port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+		return 0;
+	} else {
+		port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+		return ide_config_drive_speed(drive, mode);
+	}
+}
+
+int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_port_ops *port_ops = hwif->port_ops;
+
+	if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+		return 0;
+
+	if (port_ops == NULL || port_ops->set_dma_mode == NULL)
+		return -1;
+
+	if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
+		if (ide_config_drive_speed(drive, mode))
+			return -1;
+		port_ops->set_dma_mode(drive, mode);
+		return 0;
+	} else {
+		port_ops->set_dma_mode(drive, mode);
+		return ide_config_drive_speed(drive, mode);
+	}
+}
+EXPORT_SYMBOL_GPL(ide_set_dma_mode);
+
+/* req_pio == "255" for auto-tune */
+void ide_set_pio(ide_drive_t *drive, u8 req_pio)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_port_ops *port_ops = hwif->port_ops;
+	u8 host_pio, pio;
+
+	if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
+	    (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+		return;
+
+	BUG_ON(hwif->pio_mask == 0x00);
+
+	host_pio = fls(hwif->pio_mask) - 1;
+
+	pio = ide_get_best_pio_mode(drive, req_pio, host_pio);
+
+	/*
+	 * TODO:
+	 * - report device max PIO mode
+	 * - check req_pio != 255 against device max PIO mode
+	 */
+	printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n",
+			  drive->name, host_pio, req_pio,
+			  req_pio == 255 ? "(auto-tune)" : "", pio);
+
+	(void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
+}
+EXPORT_SYMBOL_GPL(ide_set_pio);
+
+/**
+ *	ide_rate_filter		-	filter transfer mode
+ *	@drive: IDE device
+ *	@speed: desired speed
+ *
+ *	Given the available transfer modes this function returns
+ *	the best available speed at or below the speed requested.
+ *
+ *	TODO: check device PIO capabilities
+ */
+
+static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	u8 mode = ide_find_dma_mode(drive, speed);
+
+	if (mode == 0) {
+		if (hwif->pio_mask)
+			mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0;
+		else
+			mode = XFER_PIO_4;
+	}
+
+/*	printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */
+
+	return min(speed, mode);
+}
+
+/**
+ *	ide_set_xfer_rate	-	set transfer rate
+ *	@drive: drive to set
+ *	@rate: speed to attempt to set
+ *
+ *	General helper for setting the speed of an IDE device. This
+ *	function knows about user enforced limits from the configuration
+ *	which ->set_pio_mode/->set_dma_mode does not.
+ */
+
+int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_port_ops *port_ops = hwif->port_ops;
+
+	if (port_ops == NULL || port_ops->set_dma_mode == NULL ||
+	    (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+		return -1;
+
+	rate = ide_rate_filter(drive, rate);
+
+	BUG_ON(rate < XFER_PIO_0);
+
+	if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
+		return ide_set_pio_mode(drive, rate);
+
+	return ide_set_dma_mode(drive, rate);
+}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 0920e3b..92c9b90 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -62,160 +62,6 @@
 
 struct class *ide_port_class;
 
-/*
- *	Locks for IDE setting functionality
- */
-
-DEFINE_MUTEX(ide_setting_mtx);
-
-ide_devset_get(io_32bit, io_32bit);
-
-static int set_io_32bit(ide_drive_t *drive, int arg)
-{
-	if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT)
-		return -EPERM;
-
-	if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
-		return -EINVAL;
-
-	drive->io_32bit = arg;
-
-	return 0;
-}
-
-ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS);
-
-static int set_ksettings(ide_drive_t *drive, int arg)
-{
-	if (arg < 0 || arg > 1)
-		return -EINVAL;
-
-	if (arg)
-		drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS;
-	else
-		drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS;
-
-	return 0;
-}
-
-ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA);
-
-static int set_using_dma(ide_drive_t *drive, int arg)
-{
-#ifdef CONFIG_BLK_DEV_IDEDMA
-	int err = -EPERM;
-
-	if (arg < 0 || arg > 1)
-		return -EINVAL;
-
-	if (ata_id_has_dma(drive->id) == 0)
-		goto out;
-
-	if (drive->hwif->dma_ops == NULL)
-		goto out;
-
-	err = 0;
-
-	if (arg) {
-		if (ide_set_dma(drive))
-			err = -EIO;
-	} else
-		ide_dma_off(drive);
-
-out:
-	return err;
-#else
-	if (arg < 0 || arg > 1)
-		return -EINVAL;
-
-	return -EPERM;
-#endif
-}
-
-/*
- * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
- */
-static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
-{
-	switch (req_pio) {
-	case 202:
-	case 201:
-	case 200:
-	case 102:
-	case 101:
-	case 100:
-		return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
-	case 9:
-	case 8:
-		return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
-	case 7:
-	case 6:
-		return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
-	default:
-		return 0;
-	}
-}
-
-static int set_pio_mode(ide_drive_t *drive, int arg)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	const struct ide_port_ops *port_ops = hwif->port_ops;
-
-	if (arg < 0 || arg > 255)
-		return -EINVAL;
-
-	if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
-	    (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
-		return -ENOSYS;
-
-	if (set_pio_mode_abuse(drive->hwif, arg)) {
-		if (arg == 8 || arg == 9) {
-			unsigned long flags;
-
-			/* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
-			spin_lock_irqsave(&hwif->lock, flags);
-			port_ops->set_pio_mode(drive, arg);
-			spin_unlock_irqrestore(&hwif->lock, flags);
-		} else
-			port_ops->set_pio_mode(drive, arg);
-	} else {
-		int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
-
-		ide_set_pio(drive, arg);
-
-		if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
-			if (keep_dma)
-				ide_dma_on(drive);
-		}
-	}
-
-	return 0;
-}
-
-ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK);
-
-static int set_unmaskirq(ide_drive_t *drive, int arg)
-{
-	if (drive->dev_flags & IDE_DFLAG_NO_UNMASK)
-		return -EPERM;
-
-	if (arg < 0 || arg > 1)
-		return -EINVAL;
-
-	if (arg)
-		drive->dev_flags |= IDE_DFLAG_UNMASK;
-	else
-		drive->dev_flags &= ~IDE_DFLAG_UNMASK;
-
-	return 0;
-}
-
-ide_ext_devset_rw_sync(io_32bit, io_32bit);
-ide_ext_devset_rw_sync(keepsettings, ksettings);
-ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
-ide_ext_devset_rw_sync(using_dma, using_dma);
-__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
-
 /**
  * ide_device_get	-	get an additional reference to a ide_drive_t
  * @drive:	device to get a reference to
@@ -527,6 +373,8 @@
 		goto out_port_class;
 	}
 
+	ide_acpi_init();
+
 	proc_ide_create();
 
 	return 0;
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
index 13b8153..6b9fc95 100644
--- a/drivers/ide/it821x.c
+++ b/drivers/ide/it821x.c
@@ -603,7 +603,7 @@
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
 }
 
-static unsigned int init_chipset_it821x(struct pci_dev *dev)
+static int init_chipset_it821x(struct pci_dev *dev)
 {
 	u8 conf;
 	static char *mode[2] = { "pass through", "smart" };
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c
index 83643ed..ea48a3e 100644
--- a/drivers/ide/ns87415.c
+++ b/drivers/ide/ns87415.c
@@ -286,9 +286,7 @@
 	}
 
 	if (!using_inta)
-		hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
-	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-		hwif->irq = hwif->mate->irq;	/* share IRQ with mate */
+		hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
 
 	if (!hwif->dma_base)
 		return;
diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c
index f21290c..b68906c 100644
--- a/drivers/ide/pdc202xx_new.c
+++ b/drivers/ide/pdc202xx_new.c
@@ -325,7 +325,7 @@
 }
 #endif /* CONFIG_PPC_PMAC */
 
-static unsigned int init_chipset_pdcnew(struct pci_dev *dev)
+static int init_chipset_pdcnew(struct pci_dev *dev)
 {
 	const char *name = DRV_NAME;
 	unsigned long dma_base = pci_resource_start(dev, 4);
@@ -444,7 +444,7 @@
 #endif
 
  out:
-	return dev->irq;
+	return 0;
 }
 
 static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c
index 9719332..cba66eb 100644
--- a/drivers/ide/pdc202xx_old.c
+++ b/drivers/ide/pdc202xx_old.c
@@ -264,7 +264,7 @@
 	ide_dma_timeout(drive);
 }
 
-static unsigned int init_chipset_pdc202xx(struct pci_dev *dev)
+static int init_chipset_pdc202xx(struct pci_dev *dev)
 {
 	unsigned long dmabase = pci_resource_start(dev, 4);
 	u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
@@ -290,7 +290,7 @@
 		printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN");
 	}
 out:
-	return dev->irq;
+	return 0;
 }
 
 static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index f1e2e4e..2aa6999 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -204,7 +204,7 @@
  *	out to be nice and simple.
  */
 
-static unsigned int init_chipset_ich(struct pci_dev *dev)
+static int init_chipset_ich(struct pci_dev *dev)
 {
 	u32 extra = 0;
 
@@ -318,19 +318,12 @@
 	.cable_detect		= piix_cable_detect,
 };
 
-#ifndef CONFIG_IA64
- #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
-#else
- #define IDE_HFLAGS_PIIX 0
-#endif
-
 #define DECLARE_PIIX_DEV(udma) \
 	{						\
 		.name		= DRV_NAME,		\
 		.init_hwif	= init_hwif_piix,	\
 		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
 		.port_ops	= &piix_port_ops,	\
-		.host_flags	= IDE_HFLAGS_PIIX,	\
 		.pio_mask	= ATA_PIO4,		\
 		.swdma_mask	= ATA_SWDMA2_ONLY,	\
 		.mwdma_mask	= ATA_MWDMA12_ONLY,	\
@@ -344,7 +337,6 @@
 		.init_hwif	= init_hwif_piix, \
 		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
 		.port_ops	= &ich_port_ops, \
-		.host_flags	= IDE_HFLAGS_PIIX, \
 		.pio_mask	= ATA_PIO4, \
 		.swdma_mask	= ATA_SWDMA2_ONLY, \
 		.mwdma_mask	= ATA_MWDMA12_ONLY, \
@@ -360,8 +352,7 @@
 		 */
 		.name		= DRV_NAME,
 		.enablebits	= {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}},
-		.host_flags	= IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA |
-				  IDE_HFLAGS_PIIX,
+		.host_flags	= IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA,
 		.pio_mask	= ATA_PIO4,
 		/* This is a painful system best to let it self tune for now */
 	},
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
index 382102b..b6554ef 100644
--- a/drivers/ide/serverworks.c
+++ b/drivers/ide/serverworks.c
@@ -175,7 +175,7 @@
 	pci_write_config_byte(dev, 0x54, ultra_enable);
 }
 
-static unsigned int init_chipset_svwks(struct pci_dev *dev)
+static int init_chipset_svwks(struct pci_dev *dev)
 {
 	unsigned int reg;
 	u8 btr;
@@ -270,7 +270,7 @@
 		pci_write_config_byte(dev, 0x5A, btr);
 	}
 
-	return dev->irq;
+	return 0;
 }
 
 static u8 ata66_svwks_svwks(ide_hwif_t *hwif)
@@ -353,14 +353,11 @@
 	.cable_detect		= svwks_cable_detect,
 };
 
-#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS
-
 static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
 	{	/* 0: OSB4 */
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_svwks,
 		.port_ops	= &osb4_port_ops,
-		.host_flags	= IDE_HFLAGS_SVWKS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= 0x00, /* UDMA is problematic on OSB4 */
@@ -369,7 +366,6 @@
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_svwks,
 		.port_ops	= &svwks_port_ops,
-		.host_flags	= IDE_HFLAGS_SVWKS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
@@ -378,7 +374,6 @@
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_svwks,
 		.port_ops	= &svwks_port_ops,
-		.host_flags	= IDE_HFLAGS_SVWKS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
@@ -387,7 +382,7 @@
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_svwks,
 		.port_ops	= &svwks_port_ops,
-		.host_flags	= IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+		.host_flags	= IDE_HFLAG_SINGLE,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
@@ -396,7 +391,7 @@
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_svwks,
 		.port_ops	= &svwks_port_ops,
-		.host_flags	= IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+		.host_flags	= IDE_HFLAG_SINGLE,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index e85d1ed..24bc884 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -305,7 +305,6 @@
  *	@dev: PCI device holding interface
  *	@d: IDE port info
  *	@port: port number
- *	@irq: PCI IRQ
  *	@hw: hw_regs_t instance corresponding to this port
  *
  *	Perform the initial set up for the hardware interface structure. This
@@ -316,7 +315,7 @@
  */
 
 static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
-			    unsigned int port, int irq, hw_regs_t *hw)
+			    unsigned int port, hw_regs_t *hw)
 {
 	unsigned long ctl = 0, base = 0;
 
@@ -344,7 +343,6 @@
 	}
 
 	memset(hw, 0, sizeof(*hw));
-	hw->irq = irq;
 	hw->dev = &dev->dev;
 	hw->chipset = d->chipset ? d->chipset : ide_pci;
 	ide_std_init_ports(hw, base, ctl | 2);
@@ -448,7 +446,6 @@
  *	ide_pci_setup_ports	-	configure ports/devices on PCI IDE
  *	@dev: PCI device
  *	@d: IDE port info
- *	@pciirq: IRQ line
  *	@hw: hw_regs_t instances corresponding to this PCI IDE device
  *	@hws: hw_regs_t pointers table to update
  *
@@ -462,7 +459,7 @@
  */
 
 void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
-			 int pciirq, hw_regs_t *hw, hw_regs_t **hws)
+			 hw_regs_t *hw, hw_regs_t **hws)
 {
 	int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
 	u8 tmp;
@@ -481,7 +478,7 @@
 			continue;	/* port not enabled */
 		}
 
-		if (ide_hw_configure(dev, d, port, pciirq, hw + port))
+		if (ide_hw_configure(dev, d, port, hw + port))
 			continue;
 
 		*(hws + port) = hw + port;
@@ -524,7 +521,7 @@
 		if (noisy)
 			printk(KERN_INFO "%s %s: not 100%% native mode: will "
 				"probe irqs later\n", d->name, pci_name(dev));
-		pciirq = ret;
+		pciirq = 0;
 	} else if (!pciirq && noisy) {
 		printk(KERN_WARNING "%s %s: bad irq (%d): will probe later\n",
 			d->name, pci_name(dev), pciirq);
@@ -549,7 +546,7 @@
 	if (ret < 0)
 		goto out;
 
-	ide_pci_setup_ports(dev, d, 0, &hw[0], &hws[0]);
+	ide_pci_setup_ports(dev, d, &hw[0], &hws[0]);
 
 	host = ide_host_alloc(d, hws);
 	if (host == NULL) {
@@ -568,7 +565,11 @@
 		goto out;
 
 	/* fixup IRQ */
-	hw[1].irq = hw[0].irq = ret;
+	if (ide_pci_is_in_compatibility_mode(dev)) {
+		hw[0].irq = pci_get_legacy_ide_irq(dev, 0);
+		hw[1].irq = pci_get_legacy_ide_irq(dev, 1);
+	} else
+		hw[1].irq = hw[0].irq = ret;
 
 	ret = ide_host_register(host, d, hws);
 	if (ret)
@@ -591,7 +592,7 @@
 		if (ret < 0)
 			goto out;
 
-		ide_pci_setup_ports(pdev[i], d, 0, &hw[i*2], &hws[i*2]);
+		ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]);
 	}
 
 	host = ide_host_alloc(d, hws);
@@ -619,7 +620,11 @@
 			goto out;
 
 		/* fixup IRQ */
-		hw[i*2 + 1].irq = hw[i*2].irq = ret;
+		if (ide_pci_is_in_compatibility_mode(pdev[i])) {
+			hw[i*2].irq = pci_get_legacy_ide_irq(pdev[i], 0);
+			hw[i*2 + 1].irq = pci_get_legacy_ide_irq(pdev[i], 1);
+		} else
+			hw[i*2 + 1].irq = hw[i*2].irq = ret;
 	}
 
 	ret = ide_host_register(host, d, hws);
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c
index cb2b352..1811ae9 100644
--- a/drivers/ide/siimage.c
+++ b/drivers/ide/siimage.c
@@ -464,7 +464,7 @@
  *	to 133 MHz clocking if the system isn't already set up to do it.
  */
 
-static unsigned int init_chipset_siimage(struct pci_dev *dev)
+static int init_chipset_siimage(struct pci_dev *dev)
 {
 	struct ide_host *host = pci_get_drvdata(dev);
 	void __iomem *ioaddr = host->host_priv;
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index 9ec1a4a..afca22b 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -447,7 +447,7 @@
 	return chipset_family;
 }
 
-static unsigned int init_chipset_sis5513(struct pci_dev *dev)
+static int init_chipset_sis5513(struct pci_dev *dev)
 {
 	/* Make general config ops here
 	   1/ tell IDE channels to operate in Compatibility mode only
@@ -563,7 +563,7 @@
 	.name		= DRV_NAME,
 	.init_chipset	= init_chipset_sis5513,
 	.enablebits	= { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
-	.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
+	.host_flags	= IDE_HFLAG_NO_AUTODMA,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 };
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
index 6297956..dba213c 100644
--- a/drivers/ide/sl82c105.c
+++ b/drivers/ide/sl82c105.c
@@ -271,7 +271,7 @@
  * channel 0 here at least, but channel 1 has to be enabled by
  * firmware or arch code. We still set both to 16 bits mode.
  */
-static unsigned int init_chipset_sl82c105(struct pci_dev *dev)
+static int init_chipset_sl82c105(struct pci_dev *dev)
 {
 	u32 val;
 
@@ -281,7 +281,7 @@
 	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
 	pci_write_config_dword(dev, 0x40, val);
 
-	return dev->irq;
+	return 0;
 }
 
 static const struct ide_port_ops sl82c105_port_ops = {
diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c
index 40b4b94..f55d7d6 100644
--- a/drivers/ide/slc90e66.c
+++ b/drivers/ide/slc90e66.c
@@ -136,7 +136,6 @@
 	.name		= DRV_NAME,
 	.enablebits	= { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
 	.port_ops	= &slc90e66_port_ops,
-	.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/trm290.c b/drivers/ide/trm290.c
index b6a1285..1c09e54 100644
--- a/drivers/ide/trm290.c
+++ b/drivers/ide/trm290.c
@@ -277,9 +277,6 @@
 	if (reg & 0x10)
 		/* legacy mode */
 		hwif->irq = hwif->channel ? 15 : 14;
-	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-		/* sharing IRQ with mate */
-		hwif->irq = hwif->mate->irq;
 
 #if 1
 	{
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index 6092fe3..3ff7231 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -267,7 +267,7 @@
  *	and initialize its drive independent registers.
  */
 
-static unsigned int init_chipset_via82cxxx(struct pci_dev *dev)
+static int init_chipset_via82cxxx(struct pci_dev *dev)
 {
 	struct ide_host *host = pci_get_drvdata(dev);
 	struct via82cxxx_dev *vdev = host->host_priv;
@@ -443,16 +443,6 @@
 	if ((via_config->flags & VIA_NO_UNMASK) == 0)
 		d.host_flags |= IDE_HFLAG_UNMASK_IRQS;
 
-#ifdef CONFIG_PPC_CHRP
-	if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos)
-		d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS;
-#endif
-
-#ifdef CONFIG_AMIGAONE
-	if (machine_is(amigaone))
-		d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS;
-#endif
-
 	d.udma_mask = via_config->udma_mask;
 
 	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index a01b448..4a65b96 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -2490,12 +2490,14 @@
 	int ret = 0;
 	struct nes_vnic *nesvnic;
 	struct nes_device *nesdev;
+	struct nes_ib_device *nesibdev;
 
 	nesvnic = to_nesvnic(nesqp->ibqp.device);
 	if (!nesvnic)
 		return -EINVAL;
 
 	nesdev = nesvnic->nesdev;
+	nesibdev = nesvnic->nesibdev;
 
 	nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
 			atomic_read(&nesvnic->netdev->refcnt));
@@ -2507,6 +2509,8 @@
 	} else {
 		/* Need to free the Last Streaming Mode Message */
 		if (nesqp->ietf_frame) {
+			if (nesqp->lsmm_mr)
+				nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr);
 			pci_free_consistent(nesdev->pcidev,
 					nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
 					nesqp->ietf_frame, nesqp->ietf_frame_pbase);
@@ -2543,6 +2547,12 @@
 	u32 crc_value;
 	int ret;
 	int passive_state;
+	struct nes_ib_device *nesibdev;
+	struct ib_mr *ibmr = NULL;
+	struct ib_phys_buf ibphysbuf;
+	struct nes_pd *nespd;
+
+
 
 	ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
 	if (!ibqp)
@@ -2601,6 +2611,26 @@
 	if (cm_id->remote_addr.sin_addr.s_addr !=
 			cm_id->local_addr.sin_addr.s_addr) {
 		u64temp = (unsigned long)nesqp;
+		nesibdev = nesvnic->nesibdev;
+		nespd = nesqp->nespd;
+		ibphysbuf.addr = nesqp->ietf_frame_pbase;
+		ibphysbuf.size = conn_param->private_data_len +
+					sizeof(struct ietf_mpa_frame);
+		ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd,
+						&ibphysbuf, 1,
+						IB_ACCESS_LOCAL_WRITE,
+						(u64 *)&nesqp->ietf_frame);
+		if (!ibmr) {
+			nes_debug(NES_DBG_CM, "Unable to register memory region"
+					"for lSMM for cm_node = %p \n",
+					cm_node);
+			return -ENOMEM;
+		}
+
+		ibmr->pd = &nespd->ibpd;
+		ibmr->device = nespd->ibpd.device;
+		nesqp->lsmm_mr = ibmr;
+
 		u64temp |= NES_SW_CONTEXT_ALIGN>>1;
 		set_wqe_64bit_value(wqe->wqe_words,
 			NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
@@ -2611,14 +2641,13 @@
 		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] =
 			cpu_to_le32(conn_param->private_data_len +
 			sizeof(struct ietf_mpa_frame));
-		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] =
-			cpu_to_le32((u32)nesqp->ietf_frame_pbase);
-		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] =
-			cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32));
+		set_wqe_64bit_value(wqe->wqe_words,
+					NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
+					(u64)nesqp->ietf_frame);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] =
 			cpu_to_le32(conn_param->private_data_len +
 			sizeof(struct ietf_mpa_frame));
-		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey;
 
 		nesqp->nesqp_context->ird_ord_sizes |=
 			cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 4fdb7245..d93a656 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1360,8 +1360,10 @@
 					NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT);
 			nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.sq_encoded_size <<
 					NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT);
+			if (!udata) {
 				nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_PRIV_EN);
 				nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_FAST_REGISTER_EN);
+			}
 			nesqp->nesqp_context->cqs = cpu_to_le32(nesqp->nesscq->hw_cq.cq_number +
 					((u32)nesqp->nesrcq->hw_cq.cq_number << 16));
 			u64temp = (u64)nesqp->hwqp.sq_pbase;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index 6c6b4da..ae0ca9b 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -134,6 +134,7 @@
 	struct ietf_mpa_frame *ietf_frame;
 	dma_addr_t            ietf_frame_pbase;
 	wait_queue_head_t     state_waitq;
+	struct ib_mr          *lsmm_mr;
 	unsigned long         socket;
 	struct nes_hw_qp      hwqp;
 	struct work_struct    work;
diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
index e50047b..77cfde5 100644
--- a/drivers/input/joystick/maplecontrol.c
+++ b/drivers/input/joystick/maplecontrol.c
@@ -3,7 +3,7 @@
  *	Based on drivers/usb/iforce.c
  *
  *	Copyright Yaegashi Takeshi, 2001
- *	Adrian McMenamin, 2008
+ *	Adrian McMenamin, 2008 - 2009
  */
 
 #include <linux/kernel.h>
@@ -29,7 +29,7 @@
 	struct maple_device *mapledev = mq->dev;
 	struct dc_pad *pad = maple_get_drvdata(mapledev);
 	struct input_dev *dev = pad->dev;
-	unsigned char *res = mq->recvbuf;
+	unsigned char *res = mq->recvbuf->buf;
 
 	buttons = ~le16_to_cpup((__le16 *)(res + 8));
 
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
index 22f17a5..5aa2361 100644
--- a/drivers/input/keyboard/maple_keyb.c
+++ b/drivers/input/keyboard/maple_keyb.c
@@ -1,8 +1,8 @@
 /*
  * SEGA Dreamcast keyboard driver
  * Based on drivers/usb/usbkbd.c
- * Copyright YAEGASHI Takeshi, 2001
- * Porting to 2.6 Copyright Adrian McMenamin, 2007, 2008
+ * Copyright (c) YAEGASHI Takeshi, 2001
+ * Porting to 2.6 Copyright (c) Adrian McMenamin, 2007 - 2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@
 
 #define NR_SCANCODES 256
 
-MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin");
+MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk");
 MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
 MODULE_LICENSE("GPL");
 
@@ -115,7 +115,7 @@
 				input_event(dev, EV_MSC, MSC_SCAN, code);
 				input_report_key(dev, keycode, 0);
 			} else
-				printk(KERN_DEBUG "maple_keyb: "
+				dev_dbg(&dev->dev,
 					"Unknown key (scancode %#x) released.",
 					code);
 		}
@@ -127,7 +127,7 @@
 				input_event(dev, EV_MSC, MSC_SCAN, code);
 				input_report_key(dev, keycode, 1);
 			} else
-				printk(KERN_DEBUG "maple_keyb: "
+				dev_dbg(&dev->dev,
 					"Unknown key (scancode %#x) pressed.",
 					code);
 		}
@@ -140,7 +140,7 @@
 {
 	struct maple_device *mapledev = mq->dev;
 	struct dc_kbd *kbd = maple_get_drvdata(mapledev);
-	unsigned long *buf = mq->recvbuf;
+	unsigned long *buf = (unsigned long *)(mq->recvbuf->buf);
 
 	/*
 	 * We should always get the lock because the only
@@ -159,22 +159,27 @@
 
 static int probe_maple_kbd(struct device *dev)
 {
-	struct maple_device *mdev = to_maple_dev(dev);
-	struct maple_driver *mdrv = to_maple_driver(dev->driver);
+	struct maple_device *mdev;
+	struct maple_driver *mdrv;
 	int i, error;
 	struct dc_kbd *kbd;
 	struct input_dev *idev;
 
-	if (!(mdev->function & MAPLE_FUNC_KEYBOARD))
-		return -EINVAL;
+	mdev = to_maple_dev(dev);
+	mdrv = to_maple_driver(dev->driver);
 
 	kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
-	idev = input_allocate_device();
-	if (!kbd || !idev) {
+	if (!kbd) {
 		error = -ENOMEM;
 		goto fail;
 	}
 
+	idev = input_allocate_device();
+	if (!idev) {
+		error = -ENOMEM;
+		goto fail_idev_alloc;
+	}
+
 	kbd->dev = idev;
 	memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode));
 
@@ -195,7 +200,7 @@
 
 	error = input_register_device(idev);
 	if (error)
-		goto fail;
+		goto fail_register;
 
 	/* Maple polling is locked to VBLANK - which may be just 50/s */
 	maple_getcond_callback(mdev, dc_kbd_callback, HZ/50,
@@ -207,10 +212,12 @@
 
 	return error;
 
-fail:
-	input_free_device(idev);
-	kfree(kbd);
+fail_register:
 	maple_set_drvdata(mdev, NULL);
+	input_free_device(idev);
+fail_idev_alloc:
+	kfree(kbd);
+fail:
 	return error;
 }
 
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
index 5c8a1bc..e1480fb 100644
--- a/drivers/input/keyboard/sh_keysc.c
+++ b/drivers/input/keyboard/sh_keysc.c
@@ -219,6 +219,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);
+
+	device_init_wakeup(&pdev->dev, 1);
 	return 0;
  err5:
 	free_irq(irq, pdev);
@@ -253,17 +255,33 @@
 	return 0;
 }
 
+static int sh_keysc_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
+	unsigned short value;
 
-#define sh_keysc_suspend NULL
-#define sh_keysc_resume NULL
+	value = ioread16(priv->iomem_base + KYCR1_OFFS);
+
+	if (device_may_wakeup(dev))
+		value |= 0x80;
+	else
+		value &= ~0x80;
+
+	iowrite16(value, priv->iomem_base + KYCR1_OFFS);
+	return 0;
+}
+
+static struct dev_pm_ops sh_keysc_dev_pm_ops = {
+	.suspend = sh_keysc_suspend,
+};
 
 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",
+		.pm	= &sh_keysc_dev_pm_ops,
 	}
 };
 
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index ac245e7..3071a52 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -389,8 +389,7 @@
 
 static void gigaset_device_release(struct device *dev)
 {
-	struct platform_device *pdev =
-		container_of(dev, struct platform_device, dev);
+	struct platform_device *pdev = to_platform_device(dev);
 
 	/* adapted from platform_device_release() in drivers/base/platform.c */
 	//FIXME is this actually necessary?
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index b4d44e5..8132533 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -212,6 +212,9 @@
 	hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0);
 }
 
+/* An extern declaration inside a C file is bad form.  Don't do it. */
+extern void lguest_setup_irq(unsigned int irq);
+
 /* This routine finds the first virtqueue described in the configuration of
  * this device and sets it up.
  *
@@ -266,6 +269,9 @@
 		goto unmap;
 	}
 
+	/* Make sure the interrupt is allocated. */
+	lguest_setup_irq(lvq->config.irq);
+
 	/* Tell the interrupt for this virtqueue to go to the virtio_ring
 	 * interrupt handler. */
 	/* FIXME: We used to have a flag for the Host to tell us we could use
diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c
index ef2dbfe..ada5ebb 100644
--- a/drivers/mca/mca-bus.c
+++ b/drivers/mca/mca-bus.c
@@ -110,7 +110,7 @@
 
 	mca_dev->dev.parent = &mca_bus->dev;
 	mca_dev->dev.bus = &mca_bus_type;
-	sprintf (mca_dev->dev.bus_id, "%02d:%02X", bus, mca_dev->slot);
+	dev_set_name(&mca_dev->dev, "%02d:%02X", bus, mca_dev->slot);
 	mca_dev->dma_mask = mca_bus->default_dma_mask;
 	mca_dev->dev.dma_mask = &mca_dev->dma_mask;
 	mca_dev->dev.coherent_dma_mask = mca_dev->dma_mask;
@@ -151,7 +151,7 @@
 	if (!mca_bus)
 		return NULL;
 
-	sprintf(mca_bus->dev.bus_id,"mca%d",bus);
+	dev_set_name(&mca_bus->dev, "mca%d", bus);
 	sprintf(mca_bus->name,"Host %s MCA Bridge", bus ? "Secondary" : "Primary");
 	if (device_register(&mca_bus->dev)) {
 		kfree(mca_bus);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 35bda49..bfefd07 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -60,6 +60,7 @@
 };
 
 struct dm_crypt_request {
+	struct convert_context *ctx;
 	struct scatterlist sg_in;
 	struct scatterlist sg_out;
 };
@@ -335,6 +336,18 @@
 	init_completion(&ctx->restart);
 }
 
+static struct dm_crypt_request *dmreq_of_req(struct crypt_config *cc,
+					     struct ablkcipher_request *req)
+{
+	return (struct dm_crypt_request *)((char *)req + cc->dmreq_start);
+}
+
+static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc,
+					       struct dm_crypt_request *dmreq)
+{
+	return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start);
+}
+
 static int crypt_convert_block(struct crypt_config *cc,
 			       struct convert_context *ctx,
 			       struct ablkcipher_request *req)
@@ -345,10 +358,11 @@
 	u8 *iv;
 	int r = 0;
 
-	dmreq = (struct dm_crypt_request *)((char *)req + cc->dmreq_start);
+	dmreq = dmreq_of_req(cc, req);
 	iv = (u8 *)ALIGN((unsigned long)(dmreq + 1),
 			 crypto_ablkcipher_alignmask(cc->tfm) + 1);
 
+	dmreq->ctx = ctx;
 	sg_init_table(&dmreq->sg_in, 1);
 	sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT,
 		    bv_in->bv_offset + ctx->offset_in);
@@ -395,8 +409,9 @@
 		cc->req = mempool_alloc(cc->req_pool, GFP_NOIO);
 	ablkcipher_request_set_tfm(cc->req, cc->tfm);
 	ablkcipher_request_set_callback(cc->req, CRYPTO_TFM_REQ_MAY_BACKLOG |
-					     CRYPTO_TFM_REQ_MAY_SLEEP,
-					     kcryptd_async_done, ctx);
+					CRYPTO_TFM_REQ_MAY_SLEEP,
+					kcryptd_async_done,
+					dmreq_of_req(cc, cc->req));
 }
 
 /*
@@ -553,19 +568,22 @@
 static void crypt_dec_pending(struct dm_crypt_io *io)
 {
 	struct crypt_config *cc = io->target->private;
+	struct bio *base_bio = io->base_bio;
+	struct dm_crypt_io *base_io = io->base_io;
+	int error = io->error;
 
 	if (!atomic_dec_and_test(&io->pending))
 		return;
 
-	if (likely(!io->base_io))
-		bio_endio(io->base_bio, io->error);
-	else {
-		if (io->error && !io->base_io->error)
-			io->base_io->error = io->error;
-		crypt_dec_pending(io->base_io);
-	}
-
 	mempool_free(io, cc->io_pool);
+
+	if (likely(!base_io))
+		bio_endio(base_bio, error);
+	else {
+		if (error && !base_io->error)
+			base_io->error = error;
+		crypt_dec_pending(base_io);
+	}
 }
 
 /*
@@ -821,7 +839,8 @@
 static void kcryptd_async_done(struct crypto_async_request *async_req,
 			       int error)
 {
-	struct convert_context *ctx = async_req->data;
+	struct dm_crypt_request *dmreq = async_req->data;
+	struct convert_context *ctx = dmreq->ctx;
 	struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx);
 	struct crypt_config *cc = io->target->private;
 
@@ -830,7 +849,7 @@
 		return;
 	}
 
-	mempool_free(ablkcipher_request_cast(async_req), cc->req_pool);
+	mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
 
 	if (!atomic_dec_and_test(&ctx->pending))
 		return;
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index f14813b..36e2b5e 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -292,6 +292,8 @@
 					     (PAGE_SIZE >> SECTOR_SHIFT));
 		num_bvecs = 1 + min_t(int, bio_get_nr_vecs(where->bdev),
 				      num_bvecs);
+		if (unlikely(num_bvecs > BIO_MAX_PAGES))
+			num_bvecs = BIO_MAX_PAGES;
 		bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios);
 		bio->bi_sector = where->sector + (where->count - remaining);
 		bio->bi_bdev = where->bdev;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 54d0588..f010965 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -704,7 +704,8 @@
 	char *new_name = (char *) param + param->data_start;
 
 	if (new_name < param->data ||
-	    invalid_str(new_name, (void *) param + param_size)) {
+	    invalid_str(new_name, (void *) param + param_size) ||
+	    strlen(new_name) > DM_NAME_LEN - 1) {
 		DMWARN("Invalid new logical volume name supplied.");
 		return -EINVAL;
 	}
@@ -1063,7 +1064,7 @@
 
 	r = populate_table(t, param, param_size);
 	if (r) {
-		dm_table_put(t);
+		dm_table_destroy(t);
 		goto out;
 	}
 
@@ -1071,7 +1072,7 @@
 	hc = dm_get_mdptr(md);
 	if (!hc || hc->md != md) {
 		DMWARN("device has been removed from the dev hash table.");
-		dm_table_put(t);
+		dm_table_destroy(t);
 		up_write(&_hash_lock);
 		r = -ENXIO;
 		goto out;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 51ba1db..8d40f27 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -525,9 +525,12 @@
 static void dec_pending(struct dm_io *io, int error)
 {
 	unsigned long flags;
+	int io_error;
+	struct bio *bio;
+	struct mapped_device *md = io->md;
 
 	/* Push-back supersedes any I/O errors */
-	if (error && !(io->error > 0 && __noflush_suspending(io->md)))
+	if (error && !(io->error > 0 && __noflush_suspending(md)))
 		io->error = error;
 
 	if (atomic_dec_and_test(&io->io_count)) {
@@ -537,24 +540,27 @@
 			 * This must be handled before the sleeper on
 			 * suspend queue merges the pushback list.
 			 */
-			spin_lock_irqsave(&io->md->pushback_lock, flags);
-			if (__noflush_suspending(io->md))
-				bio_list_add(&io->md->pushback, io->bio);
+			spin_lock_irqsave(&md->pushback_lock, flags);
+			if (__noflush_suspending(md))
+				bio_list_add(&md->pushback, io->bio);
 			else
 				/* noflush suspend was interrupted. */
 				io->error = -EIO;
-			spin_unlock_irqrestore(&io->md->pushback_lock, flags);
+			spin_unlock_irqrestore(&md->pushback_lock, flags);
 		}
 
 		end_io_acct(io);
 
-		if (io->error != DM_ENDIO_REQUEUE) {
-			trace_block_bio_complete(io->md->queue, io->bio);
+		io_error = io->error;
+		bio = io->bio;
 
-			bio_endio(io->bio, io->error);
+		free_io(md, io);
+
+		if (io_error != DM_ENDIO_REQUEUE) {
+			trace_block_bio_complete(md->queue, bio);
+
+			bio_endio(bio, io_error);
 		}
-
-		free_io(io->md, io);
 	}
 }
 
@@ -562,6 +568,7 @@
 {
 	int r = 0;
 	struct dm_target_io *tio = bio->bi_private;
+	struct dm_io *io = tio->io;
 	struct mapped_device *md = tio->io->md;
 	dm_endio_fn endio = tio->ti->type->end_io;
 
@@ -585,15 +592,14 @@
 		}
 	}
 
-	dec_pending(tio->io, error);
-
 	/*
 	 * Store md for cleanup instead of tio which is about to get freed.
 	 */
 	bio->bi_private = md->bs;
 
-	bio_put(bio);
 	free_tio(md, tio);
+	bio_put(bio);
+	dec_pending(io, error);
 }
 
 static sector_t max_io_len(struct mapped_device *md,
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 03b4cd0..a307f87 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -214,12 +214,7 @@
 	return mddev;
 }
 
-static void mddev_delayed_delete(struct work_struct *ws)
-{
-	mddev_t *mddev = container_of(ws, mddev_t, del_work);
-	kobject_del(&mddev->kobj);
-	kobject_put(&mddev->kobj);
-}
+static void mddev_delayed_delete(struct work_struct *ws);
 
 static void mddev_put(mddev_t *mddev)
 {
@@ -3542,6 +3537,21 @@
 
 int mdp_major = 0;
 
+static void mddev_delayed_delete(struct work_struct *ws)
+{
+	mddev_t *mddev = container_of(ws, mddev_t, del_work);
+
+	if (mddev->private == &md_redundancy_group) {
+		sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
+		if (mddev->sysfs_action)
+			sysfs_put(mddev->sysfs_action);
+		mddev->sysfs_action = NULL;
+		mddev->private = NULL;
+	}
+	kobject_del(&mddev->kobj);
+	kobject_put(&mddev->kobj);
+}
+
 static int md_alloc(dev_t dev, char *name)
 {
 	static DEFINE_MUTEX(disks_mutex);
@@ -4033,13 +4043,9 @@
 			mddev->queue->merge_bvec_fn = NULL;
 			mddev->queue->unplug_fn = NULL;
 			mddev->queue->backing_dev_info.congested_fn = NULL;
-			if (mddev->pers->sync_request) {
-				sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
-				if (mddev->sysfs_action)
-					sysfs_put(mddev->sysfs_action);
-				mddev->sysfs_action = NULL;
-			}
 			module_put(mddev->pers->owner);
+			if (mddev->pers->sync_request)
+				mddev->private = &md_redundancy_group;
 			mddev->pers = NULL;
 			/* tell userspace to handle 'inactive' */
 			sysfs_notify_dirent(mddev->sysfs_state);
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 29e8f15..fec1d77 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1683,7 +1683,7 @@
 
 static int dst_get_tuning_algo(struct dvb_frontend *fe)
 {
-	return dst_algo;
+	return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW;
 }
 
 static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 8434077..8dcb3fb 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -1290,9 +1290,6 @@
 		dprintk("%s() Finalised property cache\n", __func__);
 		dtv_property_cache_submit(fe);
 
-		/* Request the search algorithm to search */
-		fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
-
 		r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND,
 			&fepriv->parameters);
 		break;
@@ -1717,6 +1714,10 @@
 			fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
 
 		fepriv->state = FESTATE_RETUNE;
+
+		/* Request the search algorithm to search */
+		fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
 		dvb_frontend_wakeup(fe);
 		dvb_frontend_add_event(fe, 0);
 		fepriv->status = 0;
diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c
index a67d177..2da55ec 100644
--- a/drivers/media/dvb/frontends/stb0899_algo.c
+++ b/drivers/media/dvb/frontends/stb0899_algo.c
@@ -156,7 +156,7 @@
 	}
 
 	if (range > 0)
-		internal->sub_range = MIN(internal->srch_range, range);
+		internal->sub_range = min(internal->srch_range, range);
 	else
 		internal->sub_range = 0;
 
@@ -185,7 +185,7 @@
 	timing = stb0899_read_reg(state, STB0899_RTF);
 
 	if (lock >= 42) {
-		if ((lock > 48) && (ABS(timing) >= 110)) {
+		if ((lock > 48) && (abs(timing) >= 110)) {
 			internal->status = ANALOGCARRIER;
 			dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !");
 		} else {
@@ -222,7 +222,7 @@
 		index++;
 		derot_freq += index * internal->direction * derot_step;	/* next derot zig zag position	*/
 
-		if (ABS(derot_freq) > derot_limit)
+		if (abs(derot_freq) > derot_limit)
 			next_loop--;
 
 		if (next_loop) {
@@ -298,7 +298,7 @@
 			last_derot_freq = derot_freq;
 			derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */
 
-			if(ABS(derot_freq) > derot_limit)
+			if(abs(derot_freq) > derot_limit)
 				next_loop--;
 
 			if (next_loop) {
@@ -400,7 +400,7 @@
 		if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) {
 
 			derot_freq += index * internal->direction * derot_step;	/* next zig zag derotator position */
-			if (ABS(derot_freq) > derot_limit)
+			if (abs(derot_freq) > derot_limit)
 				next_loop--;
 
 			if (next_loop) {
@@ -467,7 +467,7 @@
 
 	if (internal->sub_dir > 0) {
 		old_sub_range = internal->sub_range;
-		internal->sub_range = MIN((internal->srch_range / 2) -
+		internal->sub_range = min((internal->srch_range / 2) -
 					  (internal->tuner_offst + internal->sub_range / 2),
 					   internal->sub_range);
 
@@ -771,7 +771,7 @@
 	int i;
 
 	i = 0;
-	while ((1 << i) <= ABS(number))
+	while ((1 << i) <= abs(number))
 		i++;
 
 	if (number == 0)
diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c
index 10613ac..a04c782 100644
--- a/drivers/media/dvb/frontends/stb0899_drv.c
+++ b/drivers/media/dvb/frontends/stb0899_drv.c
@@ -794,7 +794,7 @@
 	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
 	old_state = reg;
 	/* set to burst mode	*/
-	STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x02);
+	STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x03);
 	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01);
 	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
 	switch (burst) {
diff --git a/drivers/media/dvb/frontends/stb0899_priv.h b/drivers/media/dvb/frontends/stb0899_priv.h
index 24619e3..82395b9 100644
--- a/drivers/media/dvb/frontends/stb0899_priv.h
+++ b/drivers/media/dvb/frontends/stb0899_priv.h
@@ -59,10 +59,6 @@
 #define MAKEWORD32(a, b, c, d)			(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
 #define MAKEWORD16(a, b)			(((a) << 8) | (b))
 
-#define MIN(x, y)				((x) <= (y) ? (x) : (y))
-#define MAX(x, y)				((x) >= (y) ? (x) : (y))
-#define ABS(x)					((x) >= 0 ? (x) : -(x))
-
 #define LSB(x)					((x & 0xff))
 #define MSB(y)					((y >> 8) & 0xff)
 
@@ -168,10 +164,10 @@
 	u32			freq;			/* Demod internal Frequency		*/
 	u32			srate;			/* Demod internal Symbol rate		*/
 	enum stb0899_fec	fecrate;		/* Demod internal FEC rate		*/
-	u32			srch_range;		/* Demod internal Search Range		*/
-	u32			sub_range;		/* Demod current sub range (Hz)		*/
-	u32			tuner_step;		/* Tuner step (Hz)			*/
-	u32			tuner_offst;		/* Relative offset to carrier (Hz)	*/
+	s32			srch_range;		/* Demod internal Search Range		*/
+	s32			sub_range;		/* Demod current sub range (Hz)		*/
+	s32			tuner_step;		/* Tuner step (Hz)			*/
+	s32			tuner_offst;		/* Relative offset to carrier (Hz)	*/
 	u32			tuner_bw;		/* Current bandwidth of the tuner (Hz)	*/
 
 	s32			mclk;			/* Masterclock Divider factor (binary)	*/
diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c
index ff39275..1ed5a7d 100644
--- a/drivers/media/dvb/frontends/stb6100.c
+++ b/drivers/media/dvb/frontends/stb6100.c
@@ -427,11 +427,11 @@
 	status->refclock	= 27000000;	/* Hz	*/
 	status->iqsense		= 1;
 	status->bandwidth	= 36000;	/* kHz	*/
-	state->bandwidth	= status->bandwidth * 1000;	/* MHz	*/
+	state->bandwidth	= status->bandwidth * 1000;	/* Hz	*/
 	state->reference	= status->refclock / 1000;	/* kHz	*/
 
 	/* Set default bandwidth.	*/
-	return stb6100_set_bandwidth(fe, status->bandwidth);
+	return stb6100_set_bandwidth(fe, state->bandwidth);
 }
 
 static int stb6100_get_state(struct dvb_frontend *fe,
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
index 170720b..b150ed3 100644
--- a/drivers/media/dvb/frontends/zl10353.c
+++ b/drivers/media/dvb/frontends/zl10353.c
@@ -590,7 +590,7 @@
 	struct zl10353_state *state = fe->demodulator_priv;
 	u8 val = 0x0a;
 
-	if (state->config.no_tuner) {
+	if (state->config.disable_i2c_gate_ctrl) {
 		/* No tuner attached to the internal I2C bus */
 		/* If set enable I2C bridge, the main I2C bus stopped hardly */
 		return 0;
diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
index fdbb88f..2287bac 100644
--- a/drivers/media/dvb/frontends/zl10353.h
+++ b/drivers/media/dvb/frontends/zl10353.h
@@ -38,6 +38,9 @@
 
 	/* set if parallel ts output is required */
 	int parallel_ts;
+
+	/* set if i2c_gate_ctrl disable is required */
+	u8 disable_i2c_gate_ctrl:1;
 };
 
 #if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE))
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 4d35308..3936238 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -298,7 +298,8 @@
 
 	strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver));
 	strlcpy(v->card, dev->name, sizeof(v->card));
-	snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev->dev.bus_id);
+	snprintf(v->bus_info, sizeof(v->bus_info),
+		 "I2C:%s", dev_name(&dev->dev));
 	v->version = RADIO_VERSION;
 	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 66c755c..ce98d95 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -803,9 +803,10 @@
 		return (-ENOENT);
 	}
 
-	card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t));
-	if (!card)
-		return (-ENOMEM);
+	err = snd_card_create(index[devno], id[devno], THIS_MODULE,
+			      sizeof(snd_cx88_card_t), &card);
+	if (err < 0)
+		return err;
 
 	card->private_free = snd_cx88_dev_free;
 
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index 2ac738f..f132e31 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -448,9 +448,10 @@
 	printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
 			 "Rechberger\n");
 
-	card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0,
+			      &card);
+	if (err < 0)
+		return err;
 
 	spin_lock_init(&adev->slock);
 	err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index e564a61..48892b5 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -102,7 +102,11 @@
 	}
 
 	/* Test some registers, but we don't know their exact meaning yet */
-	if (m5602_read_sensor(sd, 0x00, prod_id, sizeof(prod_id)))
+	if (m5602_read_sensor(sd, 0x00, prod_id, 2))
+		return -ENODEV;
+	if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
+		return -ENODEV;
+	if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
 		return -ENODEV;
 
 	if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index c750d3d..8b0b64a 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -990,10 +990,10 @@
 	if (!enable[devnum])
 		return -ENODEV;
 
-	card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t));
-
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[devnum], id[devnum], THIS_MODULE,
+			      sizeof(snd_card_saa7134_t), &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "SAA7134");
 
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 0776ecf..b5370b3 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -860,6 +860,7 @@
 	.demod_address = 0x1e>>1,
 	.no_tuner      = 1,
 	.parallel_ts   = 1,
+	.disable_i2c_gate_ctrl = 1,
 };
 
 /* ==================================================================
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 5aeccb3..076ed5b 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -54,7 +54,7 @@
 /* ---------------------------------------------------------------------- */
 /* our structs                                                            */
 
-#define MAXREGS 64
+#define MAXREGS 256
 
 struct CHIPSTATE;
 typedef int  (*getvalue)(int);
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index cf9d4c7..8a4b74f 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -34,7 +34,7 @@
 	spin_lock_init(&v4l2_dev->lock);
 	v4l2_dev->dev = dev;
 	snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
-			dev->driver->name, dev->bus_id);
+			dev->driver->name, dev_name(dev));
 	dev_set_drvdata(dev, v4l2_dev);
 	return 0;
 }
diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig
index 4ea5fa7..8666e19 100644
--- a/drivers/media/video/zoran/Kconfig
+++ b/drivers/media/video/zoran/Kconfig
@@ -68,6 +68,7 @@
 	tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
 	depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1
 	select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+	select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
 	help
 	  Support for the AverMedia 6 Eyes video surveillance card.
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index 6063dc2..57271cb 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -214,7 +214,7 @@
 
 int mcp_host_register(struct mcp *mcp)
 {
-	strcpy(mcp->attached_device.bus_id, "mcp0");
+	dev_set_name(&mcp->attached_device, "mcp0");
 	return device_register(&mcp->attached_device);
 }
 EXPORT_SYMBOL(mcp_host_register);
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 6860c92..fea9085 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -492,7 +492,7 @@
 
 	ucb->dev.class = &ucb1x00_class;
 	ucb->dev.parent = &mcp->attached_device;
-	strlcpy(ucb->dev.bus_id, "ucb1x00", sizeof(ucb->dev.bus_id));
+	dev_set_name(&ucb->dev, "ucb1x00");
 
 	spin_lock_init(&ucb->lock);
 	spin_lock_init(&ucb->io_lock);
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index 84d5ea1..b457a05 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -1383,6 +1383,11 @@
 			wm8350->power.rev_g_coeff = 1;
 			break;
 
+		case 1:
+			dev_info(wm8350->dev, "WM8351 Rev B\n");
+			wm8350->power.rev_g_coeff = 1;
+			break;
+
 		default:
 			dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV\n");
 			ret = -ENODEV;
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 9c50e6f..34ce270 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -248,12 +248,15 @@
 
 	sg_init_one(&sg, data_buf, len);
 
-	/*
-	 * The spec states that CSR and CID accesses have a timeout
-	 * of 64 clock cycles.
-	 */
-	data.timeout_ns = 0;
-	data.timeout_clks = 64;
+	if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) {
+		/*
+		 * The spec states that CSR and CID accesses have a timeout
+		 * of 64 clock cycles.
+		 */
+		data.timeout_ns = 0;
+		data.timeout_clks = 64;
+	} else
+		mmc_set_data_timeout(&data, card);
 
 	mmc_wait_for_req(host, &mrq);
 
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 2b1196e..e94e920 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -1603,7 +1603,7 @@
 
 	tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)host);
 
-	ret = request_irq(irq, atmci_interrupt, 0, pdev->dev.bus_id, host);
+	ret = request_irq(irq, atmci_interrupt, 0, dev_name(&pdev->dev), host);
 	if (ret)
 		goto err_request_irq;
 
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index fb2921f..0c44d56 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -103,7 +103,7 @@
 		if (!gpio_is_valid(oms->gpios[i]))
 			continue;
 
-		ret = gpio_request(oms->gpios[i], dev->bus_id);
+		ret = gpio_request(oms->gpios[i], dev_name(dev));
 		if (ret < 0) {
 			oms->gpios[i] = -EINVAL;
 			continue;
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index f4a67c6..2db166b 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -793,8 +793,7 @@
 			      host->mem->start + host->sdidata);
 
 	if (!setup_ok) {
-		s3c2410_dma_config(host->dma, 4,
-			(S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI));
+		s3c2410_dma_config(host->dma, 4, 0);
 		s3c2410_dma_set_buffdone_fn(host->dma,
 					    s3cmci_dma_done_callback);
 		s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index bc33200..6fde0a2 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -120,13 +120,6 @@
 	  doesn't have access to, memory beyond the mem=xxx limit, nvram,
 	  memory on the video card, etc...
 
-config MTD_PS3VRAM
-	tristate "PS3 video RAM"
-	depends on FB_PS3
-	help
-	  This driver allows you to use excess PS3 video RAM as volatile
-	  storage or system swap.
-
 config MTD_LART
 	tristate "28F160xx flash driver for LART"
 	depends on SA1100_LART
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index e51521d..0993d5c 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,4 +16,3 @@
 obj-$(CONFIG_MTD_BLOCK2MTD)	+= block2mtd.o
 obj-$(CONFIG_MTD_DATAFLASH)	+= mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
-obj-$(CONFIG_MTD_PS3VRAM)	+= ps3vram.o
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index d44f741..6d9f810 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -821,7 +821,8 @@
 					if (!(info->flags & IS_POW2PS))
 						return info;
 				}
-			}
+			} else
+				return info;
 		}
 	}
 
diff --git a/drivers/mtd/devices/ps3vram.c b/drivers/mtd/devices/ps3vram.c
deleted file mode 100644
index d21e9be..0000000
--- a/drivers/mtd/devices/ps3vram.c
+++ /dev/null
@@ -1,768 +0,0 @@
-/**
- * ps3vram - Use extra PS3 video ram as MTD block device.
- *
- * Copyright (c) 2007-2008 Jim Paris <jim@jtan.com>
- * Added support RSX DMA Vivien Chappelier <vivien.chappelier@free.fr>
- */
-
-#include <linux/io.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-#include <linux/gfp.h>
-#include <linux/delay.h>
-#include <linux/mtd/mtd.h>
-
-#include <asm/lv1call.h>
-#include <asm/ps3.h>
-
-#define DEVICE_NAME		"ps3vram"
-
-#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */
-#define XDR_IOIF 0x0c000000
-
-#define FIFO_BASE XDR_IOIF
-#define FIFO_SIZE (64 * 1024)
-
-#define DMA_PAGE_SIZE (4 * 1024)
-
-#define CACHE_PAGE_SIZE (256 * 1024)
-#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE)
-
-#define CACHE_OFFSET CACHE_PAGE_SIZE
-#define FIFO_OFFSET 0
-
-#define CTRL_PUT 0x10
-#define CTRL_GET 0x11
-#define CTRL_TOP 0x15
-
-#define UPLOAD_SUBCH	1
-#define DOWNLOAD_SUBCH	2
-
-#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN	0x0000030c
-#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY	0x00000104
-
-#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601
-
-struct mtd_info ps3vram_mtd;
-
-#define CACHE_PAGE_PRESENT 1
-#define CACHE_PAGE_DIRTY   2
-
-struct ps3vram_tag {
-	unsigned int address;
-	unsigned int flags;
-};
-
-struct ps3vram_cache {
-	unsigned int page_count;
-	unsigned int page_size;
-	struct ps3vram_tag *tags;
-};
-
-struct ps3vram_priv {
-	u64 memory_handle;
-	u64 context_handle;
-	u32 *ctrl;
-	u32 *reports;
-	u8 __iomem *ddr_base;
-	u8 *xdr_buf;
-
-	u32 *fifo_base;
-	u32 *fifo_ptr;
-
-	struct device *dev;
-	struct ps3vram_cache cache;
-
-	/* Used to serialize cache/DMA operations */
-	struct mutex lock;
-};
-
-#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */
-#define DMA_NOTIFIER_OFFSET_BASE 0x1000     /* first DMA notifier offset */
-#define DMA_NOTIFIER_SIZE        0x40
-#define NOTIFIER 7	/* notifier used for completion report */
-
-/* A trailing '-' means to subtract off ps3fb_videomemory.size */
-char *size = "256M-";
-module_param(size, charp, 0);
-MODULE_PARM_DESC(size, "memory size");
-
-static u32 *ps3vram_get_notifier(u32 *reports, int notifier)
-{
-	return (void *) reports +
-		DMA_NOTIFIER_OFFSET_BASE +
-		DMA_NOTIFIER_SIZE * notifier;
-}
-
-static void ps3vram_notifier_reset(struct mtd_info *mtd)
-{
-	int i;
-
-	struct ps3vram_priv *priv = mtd->priv;
-	u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
-	for (i = 0; i < 4; i++)
-		notify[i] = 0xffffffff;
-}
-
-static int ps3vram_notifier_wait(struct mtd_info *mtd, unsigned int timeout_ms)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
-	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
-
-	do {
-		if (!notify[3])
-			return 0;
-		msleep(1);
-	} while (time_before(jiffies, timeout));
-
-	return -ETIMEDOUT;
-}
-
-static void ps3vram_init_ring(struct mtd_info *mtd)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-
-	priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
-	priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET;
-}
-
-static int ps3vram_wait_ring(struct mtd_info *mtd, unsigned int timeout_ms)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
-
-	do {
-		if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET])
-			return 0;
-		msleep(1);
-	} while (time_before(jiffies, timeout));
-
-	dev_dbg(priv->dev, "%s:%d: FIFO timeout (%08x/%08x/%08x)\n", __func__,
-		__LINE__, priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET],
-		priv->ctrl[CTRL_TOP]);
-
-	return -ETIMEDOUT;
-}
-
-static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data)
-{
-	*(priv->fifo_ptr)++ = data;
-}
-
-static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan,
-				      u32 tag, u32 size)
-{
-	ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag);
-}
-
-static void ps3vram_rewind_ring(struct mtd_info *mtd)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	u64 status;
-
-	ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET));
-
-	priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
-
-	/* asking the HV for a blit will kick the fifo */
-	status = lv1_gpu_context_attribute(priv->context_handle,
-					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
-					   0, 0, 0, 0);
-	if (status)
-		dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n",
-			__func__, __LINE__);
-
-	priv->fifo_ptr = priv->fifo_base;
-}
-
-static void ps3vram_fire_ring(struct mtd_info *mtd)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	u64 status;
-
-	mutex_lock(&ps3_gpu_mutex);
-
-	priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET +
-		(priv->fifo_ptr - priv->fifo_base) * sizeof(u32);
-
-	/* asking the HV for a blit will kick the fifo */
-	status = lv1_gpu_context_attribute(priv->context_handle,
-					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
-					   0, 0, 0, 0);
-	if (status)
-		dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n",
-			__func__, __LINE__);
-
-	if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) >
-		FIFO_SIZE - 1024) {
-		dev_dbg(priv->dev, "%s:%d: fifo full, rewinding\n", __func__,
-			__LINE__);
-		ps3vram_wait_ring(mtd, 200);
-		ps3vram_rewind_ring(mtd);
-	}
-
-	mutex_unlock(&ps3_gpu_mutex);
-}
-
-static void ps3vram_bind(struct mtd_info *mtd)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-
-	ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1);
-	ps3vram_out_ring(priv, 0x31337303);
-	ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3);
-	ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER);
-	ps3vram_out_ring(priv, 0xfeed0001);	/* DMA system RAM instance */
-	ps3vram_out_ring(priv, 0xfeed0000);     /* DMA video RAM instance */
-
-	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1);
-	ps3vram_out_ring(priv, 0x3137c0de);
-	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3);
-	ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER);
-	ps3vram_out_ring(priv, 0xfeed0000);	/* DMA video RAM instance */
-	ps3vram_out_ring(priv, 0xfeed0001);	/* DMA system RAM instance */
-
-	ps3vram_fire_ring(mtd);
-}
-
-static int ps3vram_upload(struct mtd_info *mtd, unsigned int src_offset,
-			  unsigned int dst_offset, int len, int count)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-
-	ps3vram_begin_ring(priv, UPLOAD_SUBCH,
-			   NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-	ps3vram_out_ring(priv, XDR_IOIF + src_offset);
-	ps3vram_out_ring(priv, dst_offset);
-	ps3vram_out_ring(priv, len);
-	ps3vram_out_ring(priv, len);
-	ps3vram_out_ring(priv, len);
-	ps3vram_out_ring(priv, count);
-	ps3vram_out_ring(priv, (1 << 8) | 1);
-	ps3vram_out_ring(priv, 0);
-
-	ps3vram_notifier_reset(mtd);
-	ps3vram_begin_ring(priv, UPLOAD_SUBCH,
-			   NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
-	ps3vram_out_ring(priv, 0);
-	ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1);
-	ps3vram_out_ring(priv, 0);
-	ps3vram_fire_ring(mtd);
-	if (ps3vram_notifier_wait(mtd, 200) < 0) {
-		dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__,
-			__LINE__);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int ps3vram_download(struct mtd_info *mtd, unsigned int src_offset,
-			    unsigned int dst_offset, int len, int count)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-
-	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH,
-			   NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-	ps3vram_out_ring(priv, src_offset);
-	ps3vram_out_ring(priv, XDR_IOIF + dst_offset);
-	ps3vram_out_ring(priv, len);
-	ps3vram_out_ring(priv, len);
-	ps3vram_out_ring(priv, len);
-	ps3vram_out_ring(priv, count);
-	ps3vram_out_ring(priv, (1 << 8) | 1);
-	ps3vram_out_ring(priv, 0);
-
-	ps3vram_notifier_reset(mtd);
-	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH,
-			   NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
-	ps3vram_out_ring(priv, 0);
-	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1);
-	ps3vram_out_ring(priv, 0);
-	ps3vram_fire_ring(mtd);
-	if (ps3vram_notifier_wait(mtd, 200) < 0) {
-		dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__,
-			__LINE__);
-		return -1;
-	}
-
-	return 0;
-}
-
-static void ps3vram_cache_evict(struct mtd_info *mtd, int entry)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	struct ps3vram_cache *cache = &priv->cache;
-
-	if (cache->tags[entry].flags & CACHE_PAGE_DIRTY) {
-		dev_dbg(priv->dev, "%s:%d: flushing %d : 0x%08x\n", __func__,
-			__LINE__, entry, cache->tags[entry].address);
-		if (ps3vram_upload(mtd,
-				   CACHE_OFFSET + entry * cache->page_size,
-				   cache->tags[entry].address,
-				   DMA_PAGE_SIZE,
-				   cache->page_size / DMA_PAGE_SIZE) < 0) {
-			dev_dbg(priv->dev, "%s:%d: failed to upload from "
-				"0x%x to 0x%x size 0x%x\n", __func__, __LINE__,
-				entry * cache->page_size,
-				cache->tags[entry].address, cache->page_size);
-		}
-		cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY;
-	}
-}
-
-static void ps3vram_cache_load(struct mtd_info *mtd, int entry,
-			       unsigned int address)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	struct ps3vram_cache *cache = &priv->cache;
-
-	dev_dbg(priv->dev, "%s:%d: fetching %d : 0x%08x\n", __func__, __LINE__,
-		entry, address);
-	if (ps3vram_download(mtd,
-			     address,
-			     CACHE_OFFSET + entry * cache->page_size,
-			     DMA_PAGE_SIZE,
-			     cache->page_size / DMA_PAGE_SIZE) < 0) {
-		dev_err(priv->dev, "%s:%d: failed to download from "
-			"0x%x to 0x%x size 0x%x\n", __func__, __LINE__, address,
-			entry * cache->page_size, cache->page_size);
-	}
-
-	cache->tags[entry].address = address;
-	cache->tags[entry].flags |= CACHE_PAGE_PRESENT;
-}
-
-
-static void ps3vram_cache_flush(struct mtd_info *mtd)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	struct ps3vram_cache *cache = &priv->cache;
-	int i;
-
-	dev_dbg(priv->dev, "%s:%d: FLUSH\n", __func__, __LINE__);
-	for (i = 0; i < cache->page_count; i++) {
-		ps3vram_cache_evict(mtd, i);
-		cache->tags[i].flags = 0;
-	}
-}
-
-static unsigned int ps3vram_cache_match(struct mtd_info *mtd, loff_t address)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	struct ps3vram_cache *cache = &priv->cache;
-	unsigned int base;
-	unsigned int offset;
-	int i;
-	static int counter;
-
-	offset = (unsigned int) (address & (cache->page_size - 1));
-	base = (unsigned int) (address - offset);
-
-	/* fully associative check */
-	for (i = 0; i < cache->page_count; i++) {
-		if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) &&
-		    cache->tags[i].address == base) {
-			dev_dbg(priv->dev, "%s:%d: found entry %d : 0x%08x\n",
-				__func__, __LINE__, i, cache->tags[i].address);
-			return i;
-		}
-	}
-
-	/* choose a random entry */
-	i = (jiffies + (counter++)) % cache->page_count;
-	dev_dbg(priv->dev, "%s:%d: using entry %d\n", __func__, __LINE__, i);
-
-	ps3vram_cache_evict(mtd, i);
-	ps3vram_cache_load(mtd, i, base);
-
-	return i;
-}
-
-static int ps3vram_cache_init(struct mtd_info *mtd)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-
-	priv->cache.page_count = CACHE_PAGE_COUNT;
-	priv->cache.page_size = CACHE_PAGE_SIZE;
-	priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) *
-				   CACHE_PAGE_COUNT, GFP_KERNEL);
-	if (priv->cache.tags == NULL) {
-		dev_err(priv->dev, "%s:%d: could not allocate cache tags\n",
-			__func__, __LINE__);
-		return -ENOMEM;
-	}
-
-	dev_info(priv->dev, "created ram cache: %d entries, %d KiB each\n",
-		CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024);
-
-	return 0;
-}
-
-static void ps3vram_cache_cleanup(struct mtd_info *mtd)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-
-	ps3vram_cache_flush(mtd);
-	kfree(priv->cache.tags);
-}
-
-static int ps3vram_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-
-	if (instr->addr + instr->len > mtd->size)
-		return -EINVAL;
-
-	mutex_lock(&priv->lock);
-
-	ps3vram_cache_flush(mtd);
-
-	/* Set bytes to 0xFF */
-	memset_io(priv->ddr_base + instr->addr, 0xFF, instr->len);
-
-	mutex_unlock(&priv->lock);
-
-	instr->state = MTD_ERASE_DONE;
-	mtd_erase_callback(instr);
-
-	return 0;
-}
-
-static int ps3vram_read(struct mtd_info *mtd, loff_t from, size_t len,
-			size_t *retlen, u_char *buf)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	unsigned int cached, count;
-
-	dev_dbg(priv->dev, "%s:%d: from=0x%08x len=0x%zx\n", __func__, __LINE__,
-		(unsigned int)from, len);
-
-	if (from >= mtd->size)
-		return -EINVAL;
-
-	if (len > mtd->size - from)
-		len = mtd->size - from;
-
-	/* Copy from vram to buf */
-	count = len;
-	while (count) {
-		unsigned int offset, avail;
-		unsigned int entry;
-
-		offset = (unsigned int) (from & (priv->cache.page_size - 1));
-		avail  = priv->cache.page_size - offset;
-
-		mutex_lock(&priv->lock);
-
-		entry = ps3vram_cache_match(mtd, from);
-		cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
-
-		dev_dbg(priv->dev, "%s:%d: from=%08x cached=%08x offset=%08x "
-			"avail=%08x count=%08x\n", __func__, __LINE__,
-			(unsigned int)from, cached, offset, avail, count);
-
-		if (avail > count)
-			avail = count;
-		memcpy(buf, priv->xdr_buf + cached, avail);
-
-		mutex_unlock(&priv->lock);
-
-		buf += avail;
-		count -= avail;
-		from += avail;
-	}
-
-	*retlen = len;
-	return 0;
-}
-
-static int ps3vram_write(struct mtd_info *mtd, loff_t to, size_t len,
-			 size_t *retlen, const u_char *buf)
-{
-	struct ps3vram_priv *priv = mtd->priv;
-	unsigned int cached, count;
-
-	if (to >= mtd->size)
-		return -EINVAL;
-
-	if (len > mtd->size - to)
-		len = mtd->size - to;
-
-	/* Copy from buf to vram */
-	count = len;
-	while (count) {
-		unsigned int offset, avail;
-		unsigned int entry;
-
-		offset = (unsigned int) (to & (priv->cache.page_size - 1));
-		avail  = priv->cache.page_size - offset;
-
-		mutex_lock(&priv->lock);
-
-		entry = ps3vram_cache_match(mtd, to);
-		cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
-
-		dev_dbg(priv->dev, "%s:%d: to=%08x cached=%08x offset=%08x "
-			"avail=%08x count=%08x\n", __func__, __LINE__,
-			(unsigned int)to, cached, offset, avail, count);
-
-		if (avail > count)
-			avail = count;
-		memcpy(priv->xdr_buf + cached, buf, avail);
-
-		priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY;
-
-		mutex_unlock(&priv->lock);
-
-		buf += avail;
-		count -= avail;
-		to += avail;
-	}
-
-	*retlen = len;
-	return 0;
-}
-
-static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
-{
-	struct ps3vram_priv *priv;
-	int status;
-	u64 ddr_lpar;
-	u64 ctrl_lpar;
-	u64 info_lpar;
-	u64 reports_lpar;
-	u64 ddr_size;
-	u64 reports_size;
-	int ret = -ENOMEM;
-	char *rest;
-
-	ret = -EIO;
-	ps3vram_mtd.priv = kzalloc(sizeof(struct ps3vram_priv), GFP_KERNEL);
-	if (!ps3vram_mtd.priv)
-		goto out;
-	priv = ps3vram_mtd.priv;
-
-	mutex_init(&priv->lock);
-	priv->dev = &dev->core;
-
-	/* Allocate XDR buffer (1MiB aligned) */
-	priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL,
-		get_order(XDR_BUF_SIZE));
-	if (priv->xdr_buf == NULL) {
-		dev_dbg(&dev->core, "%s:%d: could not allocate XDR buffer\n",
-			__func__, __LINE__);
-		ret = -ENOMEM;
-		goto out_free_priv;
-	}
-
-	/* Put FIFO at begginning of XDR buffer */
-	priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET);
-	priv->fifo_ptr = priv->fifo_base;
-
-	/* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */
-	if (ps3_open_hv_device(dev)) {
-		dev_err(&dev->core, "%s:%d: ps3_open_hv_device failed\n",
-			__func__, __LINE__);
-		ret = -EAGAIN;
-		goto out_close_gpu;
-	}
-
-	/* Request memory */
-	status = -1;
-	ddr_size = memparse(size, &rest);
-	if (*rest == '-')
-		ddr_size -= ps3fb_videomemory.size;
-	ddr_size = ALIGN(ddr_size, 1024*1024);
-	if (ddr_size <= 0) {
-		dev_err(&dev->core, "%s:%d: specified size is too small\n",
-			__func__, __LINE__);
-		ret = -EINVAL;
-		goto out_close_gpu;
-	}
-
-	while (ddr_size > 0) {
-		status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0,
-						 &priv->memory_handle,
-						 &ddr_lpar);
-		if (!status)
-			break;
-		ddr_size -= 1024*1024;
-	}
-	if (status || ddr_size <= 0) {
-		dev_err(&dev->core, "%s:%d: lv1_gpu_memory_allocate failed\n",
-			__func__, __LINE__);
-		ret = -ENOMEM;
-		goto out_free_xdr_buf;
-	}
-
-	/* Request context */
-	status = lv1_gpu_context_allocate(priv->memory_handle,
-					  0,
-					  &priv->context_handle,
-					  &ctrl_lpar,
-					  &info_lpar,
-					  &reports_lpar,
-					  &reports_size);
-	if (status) {
-		dev_err(&dev->core, "%s:%d: lv1_gpu_context_allocate failed\n",
-			__func__, __LINE__);
-		ret = -ENOMEM;
-		goto out_free_memory;
-	}
-
-	/* Map XDR buffer to RSX */
-	status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF,
-				       ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)),
-				       XDR_BUF_SIZE, 0);
-	if (status) {
-		dev_err(&dev->core, "%s:%d: lv1_gpu_context_iomap failed\n",
-			__func__, __LINE__);
-		ret = -ENOMEM;
-		goto out_free_context;
-	}
-
-	priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE);
-
-	if (!priv->ddr_base) {
-		dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__,
-			__LINE__);
-		ret = -ENOMEM;
-		goto out_free_context;
-	}
-
-	priv->ctrl = ioremap(ctrl_lpar, 64 * 1024);
-	if (!priv->ctrl) {
-		dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__,
-			__LINE__);
-		ret = -ENOMEM;
-		goto out_unmap_vram;
-	}
-
-	priv->reports = ioremap(reports_lpar, reports_size);
-	if (!priv->reports) {
-		dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__,
-			__LINE__);
-		ret = -ENOMEM;
-		goto out_unmap_ctrl;
-	}
-
-	mutex_lock(&ps3_gpu_mutex);
-	ps3vram_init_ring(&ps3vram_mtd);
-	mutex_unlock(&ps3_gpu_mutex);
-
-	ps3vram_mtd.name = "ps3vram";
-	ps3vram_mtd.size = ddr_size;
-	ps3vram_mtd.flags = MTD_CAP_RAM;
-	ps3vram_mtd.erase = ps3vram_erase;
-	ps3vram_mtd.point = NULL;
-	ps3vram_mtd.unpoint = NULL;
-	ps3vram_mtd.read = ps3vram_read;
-	ps3vram_mtd.write = ps3vram_write;
-	ps3vram_mtd.owner = THIS_MODULE;
-	ps3vram_mtd.type = MTD_RAM;
-	ps3vram_mtd.erasesize = CACHE_PAGE_SIZE;
-	ps3vram_mtd.writesize = 1;
-
-	ps3vram_bind(&ps3vram_mtd);
-
-	mutex_lock(&ps3_gpu_mutex);
-	ret = ps3vram_wait_ring(&ps3vram_mtd, 100);
-	mutex_unlock(&ps3_gpu_mutex);
-	if (ret < 0) {
-		dev_err(&dev->core, "%s:%d: failed to initialize channels\n",
-			__func__, __LINE__);
-		ret = -ETIMEDOUT;
-		goto out_unmap_reports;
-	}
-
-	ps3vram_cache_init(&ps3vram_mtd);
-
-	if (add_mtd_device(&ps3vram_mtd)) {
-		dev_err(&dev->core, "%s:%d: add_mtd_device failed\n",
-			__func__, __LINE__);
-		ret = -EAGAIN;
-		goto out_cache_cleanup;
-	}
-
-	dev_info(&dev->core, "reserved %u MiB of gpu memory\n",
-		(unsigned int)(ddr_size / 1024 / 1024));
-
-	return 0;
-
-out_cache_cleanup:
-	ps3vram_cache_cleanup(&ps3vram_mtd);
-out_unmap_reports:
-	iounmap(priv->reports);
-out_unmap_ctrl:
-	iounmap(priv->ctrl);
-out_unmap_vram:
-	iounmap(priv->ddr_base);
-out_free_context:
-	lv1_gpu_context_free(priv->context_handle);
-out_free_memory:
-	lv1_gpu_memory_free(priv->memory_handle);
-out_close_gpu:
-	ps3_close_hv_device(dev);
-out_free_xdr_buf:
-	free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
-out_free_priv:
-	kfree(ps3vram_mtd.priv);
-	ps3vram_mtd.priv = NULL;
-out:
-	return ret;
-}
-
-static int ps3vram_shutdown(struct ps3_system_bus_device *dev)
-{
-	struct ps3vram_priv *priv;
-
-	priv = ps3vram_mtd.priv;
-
-	del_mtd_device(&ps3vram_mtd);
-	ps3vram_cache_cleanup(&ps3vram_mtd);
-	iounmap(priv->reports);
-	iounmap(priv->ctrl);
-	iounmap(priv->ddr_base);
-	lv1_gpu_context_free(priv->context_handle);
-	lv1_gpu_memory_free(priv->memory_handle);
-	ps3_close_hv_device(dev);
-	free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
-	kfree(priv);
-	return 0;
-}
-
-static struct ps3_system_bus_driver ps3vram_driver = {
-	.match_id	= PS3_MATCH_ID_GPU,
-	.match_sub_id	= PS3_MATCH_SUB_ID_GPU_RAMDISK,
-	.core.name	= DEVICE_NAME,
-	.core.owner	= THIS_MODULE,
-	.probe		= ps3vram_probe,
-	.remove		= ps3vram_shutdown,
-	.shutdown	= ps3vram_shutdown,
-};
-
-static int __init ps3vram_init(void)
-{
-	return ps3_system_bus_driver_register(&ps3vram_driver);
-}
-
-static void __exit ps3vram_exit(void)
-{
-	ps3_system_bus_driver_unregister(&ps3vram_driver);
-}
-
-module_init(ps3vram_init);
-module_exit(ps3vram_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jim Paris <jim@jtan.com>");
-MODULE_DESCRIPTION("MTD driver for PS3 video RAM");
-MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK);
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 043d50f..729f899 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -551,5 +551,15 @@
 
 	  This selection automatically selects the map_ram driver.
 
-endmenu
+config MTD_VMU
+	tristate "Map driver for Dreamcast VMU"
+	depends on MAPLE
+	help
+	  This driver enables access to the Dreamcast Visual Memory Unit (VMU).
 
+	  Most Dreamcast users will want to say Y here.
+
+	  To build this as a module select M here, the module will be called
+	  vmu-flash.
+
+endmenu
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 6d9ba35..26b28a7 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -61,3 +61,4 @@
 obj-$(CONFIG_MTD_OMAP_NOR)	+= omap_nor.o
 obj-$(CONFIG_MTD_INTEL_VR_NOR)	+= intel_vr_nor.o
 obj-$(CONFIG_MTD_BFIN_ASYNC)	+= bfin-async-flash.o
+obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 4b122e7..2297182 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -46,16 +46,19 @@
 
 	physmap_data = dev->dev.platform_data;
 
+	if (info->cmtd) {
 #ifdef CONFIG_MTD_PARTITIONS
-	if (info->nr_parts) {
-		del_mtd_partitions(info->cmtd);
-		kfree(info->parts);
-	} else if (physmap_data->nr_parts)
-		del_mtd_partitions(info->cmtd);
-	else
-		del_mtd_device(info->cmtd);
+		if (info->nr_parts || physmap_data->nr_parts)
+			del_mtd_partitions(info->cmtd);
+		else
+			del_mtd_device(info->cmtd);
 #else
-	del_mtd_device(info->cmtd);
+		del_mtd_device(info->cmtd);
+#endif
+	}
+#ifdef CONFIG_MTD_PARTITIONS
+	if (info->nr_parts)
+		kfree(info->parts);
 #endif
 
 #ifdef CONFIG_MTD_CONCAT
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 771139c..e9026cb 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -41,9 +41,8 @@
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 
-static int __init pxa2xx_flash_probe(struct device *dev)
+static int __init pxa2xx_flash_probe(struct platform_device *pdev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
 	struct flash_platform_data *flash = pdev->dev.platform_data;
 	struct pxa2xx_flash_info *info;
 	struct mtd_partition *parts;
@@ -114,15 +113,15 @@
 		add_mtd_device(info->mtd);
 	}
 
-	dev_set_drvdata(dev, info);
+	platform_set_drvdata(pdev, info);
 	return 0;
 }
 
-static int __exit pxa2xx_flash_remove(struct device *dev)
+static int __exit pxa2xx_flash_remove(struct platform_device *dev)
 {
-	struct pxa2xx_flash_info *info = dev_get_drvdata(dev);
+	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
 
-	dev_set_drvdata(dev, NULL);
+	platform_set_drvdata(dev, NULL);
 
 #ifdef CONFIG_MTD_PARTITIONS
 	if (info->nr_parts)
@@ -141,9 +140,9 @@
 }
 
 #ifdef CONFIG_PM
-static int pxa2xx_flash_suspend(struct device *dev, pm_message_t state)
+static int pxa2xx_flash_suspend(struct platform_device *dev, pm_message_t state)
 {
-	struct pxa2xx_flash_info *info = dev_get_drvdata(dev);
+	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
 	int ret = 0;
 
 	if (info->mtd && info->mtd->suspend)
@@ -151,17 +150,17 @@
 	return ret;
 }
 
-static int pxa2xx_flash_resume(struct device *dev)
+static int pxa2xx_flash_resume(struct platform_device *dev)
 {
-	struct pxa2xx_flash_info *info = dev_get_drvdata(dev);
+	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
 
 	if (info->mtd && info->mtd->resume)
 		info->mtd->resume(info->mtd);
 	return 0;
 }
-static void pxa2xx_flash_shutdown(struct device *dev)
+static void pxa2xx_flash_shutdown(struct platform_device *dev)
 {
-	struct pxa2xx_flash_info *info = dev_get_drvdata(dev);
+	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
 
 	if (info && info->mtd->suspend(info->mtd) == 0)
 		info->mtd->resume(info->mtd);
@@ -172,11 +171,13 @@
 #define pxa2xx_flash_shutdown NULL
 #endif
 
-static struct device_driver pxa2xx_flash_driver = {
-	.name		= "pxa2xx-flash",
-	.bus		= &platform_bus_type,
+static struct platform_driver pxa2xx_flash_driver = {
+	.driver = {
+		.name		= "pxa2xx-flash",
+		.owner		= THIS_MODULE,
+	},
 	.probe		= pxa2xx_flash_probe,
-	.remove		= __exit_p(pxa2xx_flash_remove),
+	.remove		= __devexit_p(pxa2xx_flash_remove),
 	.suspend	= pxa2xx_flash_suspend,
 	.resume		= pxa2xx_flash_resume,
 	.shutdown	= pxa2xx_flash_shutdown,
@@ -184,12 +185,12 @@
 
 static int __init init_pxa2xx_flash(void)
 {
-	return driver_register(&pxa2xx_flash_driver);
+	return platform_driver_register(&pxa2xx_flash_driver);
 }
 
 static void __exit cleanup_pxa2xx_flash(void)
 {
-	driver_unregister(&pxa2xx_flash_driver);
+	platform_driver_unregister(&pxa2xx_flash_driver);
 }
 
 module_init(init_pxa2xx_flash);
diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
new file mode 100644
index 0000000..1f73297
--- /dev/null
+++ b/drivers/mtd/maps/vmu-flash.c
@@ -0,0 +1,832 @@
+/* vmu-flash.c
+ * Driver for SEGA Dreamcast Visual Memory Unit
+ *
+ * Copyright (c) Adrian McMenamin 2002 - 2009
+ * Copyright (c) Paul Mundt 2001
+ *
+ * Licensed under version 2 of the
+ * GNU General Public Licence
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/maple.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+
+struct vmu_cache {
+	unsigned char *buffer;		/* Cache */
+	unsigned int block;		/* Which block was cached */
+	unsigned long jiffies_atc;	/* When was it cached? */
+	int valid;
+};
+
+struct mdev_part {
+	struct maple_device *mdev;
+	int partition;
+};
+
+struct vmupart {
+	u16 user_blocks;
+	u16 root_block;
+	u16 numblocks;
+	char *name;
+	struct vmu_cache *pcache;
+};
+
+struct memcard {
+	u16 tempA;
+	u16 tempB;
+	u32 partitions;
+	u32 blocklen;
+	u32 writecnt;
+	u32 readcnt;
+	u32 removeable;
+	int partition;
+	int read;
+	unsigned char *blockread;
+	struct vmupart *parts;
+	struct mtd_info *mtd;
+};
+
+struct vmu_block {
+	unsigned int num; /* block number */
+	unsigned int ofs; /* block offset */
+};
+
+static struct vmu_block *ofs_to_block(unsigned long src_ofs,
+	struct mtd_info *mtd, int partition)
+{
+	struct vmu_block *vblock;
+	struct maple_device *mdev;
+	struct memcard *card;
+	struct mdev_part *mpart;
+	int num;
+
+	mpart = mtd->priv;
+	mdev = mpart->mdev;
+	card = maple_get_drvdata(mdev);
+
+	if (src_ofs >= card->parts[partition].numblocks * card->blocklen)
+		goto failed;
+
+	num = src_ofs / card->blocklen;
+	if (num > card->parts[partition].numblocks)
+		goto failed;
+
+	vblock = kmalloc(sizeof(struct vmu_block), GFP_KERNEL);
+	if (!vblock)
+		goto failed;
+
+	vblock->num = num;
+	vblock->ofs = src_ofs % card->blocklen;
+	return vblock;
+
+failed:
+	return NULL;
+}
+
+/* Maple bus callback function for reads */
+static void vmu_blockread(struct mapleq *mq)
+{
+	struct maple_device *mdev;
+	struct memcard *card;
+
+	mdev = mq->dev;
+	card = maple_get_drvdata(mdev);
+	/* copy the read in data */
+
+	if (unlikely(!card->blockread))
+		return;
+
+	memcpy(card->blockread, mq->recvbuf->buf + 12,
+		card->blocklen/card->readcnt);
+
+}
+
+/* Interface with maple bus to read blocks
+ * caching the results so that other parts
+ * of the driver can access block reads */
+static int maple_vmu_read_block(unsigned int num, unsigned char *buf,
+	struct mtd_info *mtd)
+{
+	struct memcard *card;
+	struct mdev_part *mpart;
+	struct maple_device *mdev;
+	int partition, error = 0, x, wait;
+	unsigned char *blockread = NULL;
+	struct vmu_cache *pcache;
+	__be32 sendbuf;
+
+	mpart = mtd->priv;
+	mdev = mpart->mdev;
+	partition = mpart->partition;
+	card = maple_get_drvdata(mdev);
+	pcache = card->parts[partition].pcache;
+	pcache->valid = 0;
+
+	/* prepare the cache for this block */
+	if (!pcache->buffer) {
+		pcache->buffer = kmalloc(card->blocklen, GFP_KERNEL);
+		if (!pcache->buffer) {
+			dev_err(&mdev->dev, "VMU at (%d, %d) - read fails due"
+				" to lack of memory\n", mdev->port,
+				mdev->unit);
+			error = -ENOMEM;
+			goto outB;
+		}
+	}
+
+	/*
+	* Reads may be phased - again the hardware spec
+	* supports this - though may not be any devices in
+	* the wild that implement it, but we will here
+	*/
+	for (x = 0; x < card->readcnt; x++) {
+		sendbuf = cpu_to_be32(partition << 24 | x << 16 | num);
+
+		if (atomic_read(&mdev->busy) == 1) {
+			wait_event_interruptible_timeout(mdev->maple_wait,
+				atomic_read(&mdev->busy) == 0, HZ);
+			if (atomic_read(&mdev->busy) == 1) {
+				dev_notice(&mdev->dev, "VMU at (%d, %d)"
+					" is busy\n", mdev->port, mdev->unit);
+				error = -EAGAIN;
+				goto outB;
+			}
+		}
+
+		atomic_set(&mdev->busy, 1);
+		blockread = kmalloc(card->blocklen/card->readcnt, GFP_KERNEL);
+		if (!blockread) {
+			error = -ENOMEM;
+			atomic_set(&mdev->busy, 0);
+			goto outB;
+		}
+		card->blockread = blockread;
+
+		maple_getcond_callback(mdev, vmu_blockread, 0,
+			MAPLE_FUNC_MEMCARD);
+		error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
+				MAPLE_COMMAND_BREAD, 2, &sendbuf);
+		/* Very long timeouts seem to be needed when box is stressed */
+		wait = wait_event_interruptible_timeout(mdev->maple_wait,
+			(atomic_read(&mdev->busy) == 0 ||
+			atomic_read(&mdev->busy) == 2), HZ * 3);
+		/*
+		* MTD layer does not handle hotplugging well
+		* so have to return errors when VMU is unplugged
+		* in the middle of a read (busy == 2)
+		*/
+		if (error || atomic_read(&mdev->busy) == 2) {
+			if (atomic_read(&mdev->busy) == 2)
+				error = -ENXIO;
+			atomic_set(&mdev->busy, 0);
+			card->blockread = NULL;
+			goto outA;
+		}
+		if (wait == 0 || wait == -ERESTARTSYS) {
+			card->blockread = NULL;
+			atomic_set(&mdev->busy, 0);
+			error = -EIO;
+			list_del_init(&(mdev->mq->list));
+			kfree(mdev->mq->sendbuf);
+			mdev->mq->sendbuf = NULL;
+			if (wait == -ERESTARTSYS) {
+				dev_warn(&mdev->dev, "VMU read on (%d, %d)"
+					" interrupted on block 0x%X\n",
+					mdev->port, mdev->unit, num);
+			} else
+				dev_notice(&mdev->dev, "VMU read on (%d, %d)"
+					" timed out on block 0x%X\n",
+					mdev->port, mdev->unit, num);
+			goto outA;
+		}
+
+		memcpy(buf + (card->blocklen/card->readcnt) * x, blockread,
+			card->blocklen/card->readcnt);
+
+		memcpy(pcache->buffer + (card->blocklen/card->readcnt) * x,
+			card->blockread, card->blocklen/card->readcnt);
+		card->blockread = NULL;
+		pcache->block = num;
+		pcache->jiffies_atc = jiffies;
+		pcache->valid = 1;
+		kfree(blockread);
+	}
+
+	return error;
+
+outA:
+	kfree(blockread);
+outB:
+	return error;
+}
+
+/* communicate with maple bus for phased writing */
+static int maple_vmu_write_block(unsigned int num, const unsigned char *buf,
+	struct mtd_info *mtd)
+{
+	struct memcard *card;
+	struct mdev_part *mpart;
+	struct maple_device *mdev;
+	int partition, error, locking, x, phaselen, wait;
+	__be32 *sendbuf;
+
+	mpart = mtd->priv;
+	mdev = mpart->mdev;
+	partition = mpart->partition;
+	card = maple_get_drvdata(mdev);
+
+	phaselen = card->blocklen/card->writecnt;
+
+	sendbuf = kmalloc(phaselen + 4, GFP_KERNEL);
+	if (!sendbuf) {
+		error = -ENOMEM;
+		goto fail_nosendbuf;
+	}
+	for (x = 0; x < card->writecnt; x++) {
+		sendbuf[0] = cpu_to_be32(partition << 24 | x << 16 | num);
+		memcpy(&sendbuf[1], buf + phaselen * x, phaselen);
+		/* wait until the device is not busy doing something else
+		* or 1 second - which ever is longer */
+		if (atomic_read(&mdev->busy) == 1) {
+			wait_event_interruptible_timeout(mdev->maple_wait,
+				atomic_read(&mdev->busy) == 0, HZ);
+			if (atomic_read(&mdev->busy) == 1) {
+				error = -EBUSY;
+				dev_notice(&mdev->dev, "VMU write at (%d, %d)"
+					"failed - device is busy\n",
+					mdev->port, mdev->unit);
+				goto fail_nolock;
+			}
+		}
+		atomic_set(&mdev->busy, 1);
+
+		locking = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
+			MAPLE_COMMAND_BWRITE, phaselen / 4 + 2, sendbuf);
+		wait = wait_event_interruptible_timeout(mdev->maple_wait,
+			atomic_read(&mdev->busy) == 0, HZ/10);
+		if (locking) {
+			error = -EIO;
+			atomic_set(&mdev->busy, 0);
+			goto fail_nolock;
+		}
+		if (atomic_read(&mdev->busy) == 2) {
+			atomic_set(&mdev->busy, 0);
+		} else if (wait == 0 || wait == -ERESTARTSYS) {
+			error = -EIO;
+			dev_warn(&mdev->dev, "Write at (%d, %d) of block"
+				" 0x%X at phase %d failed: could not"
+				" communicate with VMU", mdev->port,
+				mdev->unit, num, x);
+			atomic_set(&mdev->busy, 0);
+			kfree(mdev->mq->sendbuf);
+			mdev->mq->sendbuf = NULL;
+			list_del_init(&(mdev->mq->list));
+			goto fail_nolock;
+		}
+	}
+	kfree(sendbuf);
+
+	return card->blocklen;
+
+fail_nolock:
+	kfree(sendbuf);
+fail_nosendbuf:
+	dev_err(&mdev->dev, "VMU (%d, %d): write failed\n", mdev->port,
+		mdev->unit);
+	return error;
+}
+
+/* mtd function to simulate reading byte by byte */
+static unsigned char vmu_flash_read_char(unsigned long ofs, int *retval,
+	struct mtd_info *mtd)
+{
+	struct vmu_block *vblock;
+	struct memcard *card;
+	struct mdev_part *mpart;
+	struct maple_device *mdev;
+	unsigned char *buf, ret;
+	int partition, error;
+
+	mpart = mtd->priv;
+	mdev = mpart->mdev;
+	partition = mpart->partition;
+	card = maple_get_drvdata(mdev);
+	*retval =  0;
+
+	buf = kmalloc(card->blocklen, GFP_KERNEL);
+	if (!buf) {
+		*retval = 1;
+		ret = -ENOMEM;
+		goto finish;
+	}
+
+	vblock = ofs_to_block(ofs, mtd, partition);
+	if (!vblock) {
+		*retval = 3;
+		ret = -ENOMEM;
+		goto out_buf;
+	}
+
+	error = maple_vmu_read_block(vblock->num, buf, mtd);
+	if (error) {
+		ret = error;
+		*retval = 2;
+		goto out_vblock;
+	}
+
+	ret = buf[vblock->ofs];
+
+out_vblock:
+	kfree(vblock);
+out_buf:
+	kfree(buf);
+finish:
+	return ret;
+}
+
+/* mtd higher order function to read flash */
+static int vmu_flash_read(struct mtd_info *mtd, loff_t from, size_t len,
+	size_t *retlen,  u_char *buf)
+{
+	struct maple_device *mdev;
+	struct memcard *card;
+	struct mdev_part *mpart;
+	struct vmu_cache *pcache;
+	struct vmu_block *vblock;
+	int index = 0, retval, partition, leftover, numblocks;
+	unsigned char cx;
+
+	if (len < 1)
+		return -EIO;
+
+	mpart = mtd->priv;
+	mdev = mpart->mdev;
+	partition = mpart->partition;
+	card = maple_get_drvdata(mdev);
+
+	numblocks = card->parts[partition].numblocks;
+	if (from + len > numblocks * card->blocklen)
+		len = numblocks * card->blocklen - from;
+	if (len == 0)
+		return -EIO;
+	/* Have we cached this bit already? */
+	pcache = card->parts[partition].pcache;
+	do {
+		vblock =  ofs_to_block(from + index, mtd, partition);
+		if (!vblock)
+			return -ENOMEM;
+		/* Have we cached this and is the cache valid and timely? */
+		if (pcache->valid &&
+			time_before(jiffies, pcache->jiffies_atc + HZ) &&
+			(pcache->block == vblock->num)) {
+			/* we have cached it, so do necessary copying */
+			leftover = card->blocklen - vblock->ofs;
+			if (vblock->ofs + len - index < card->blocklen) {
+				/* only a bit of this block to copy */
+				memcpy(buf + index,
+					pcache->buffer + vblock->ofs,
+					len - index);
+				index = len;
+			} else {
+				/* otherwise copy remainder of whole block */
+				memcpy(buf + index, pcache->buffer +
+					vblock->ofs, leftover);
+				index += leftover;
+			}
+		} else {
+			/*
+			* Not cached so read one byte -
+			* but cache the rest of the block
+			*/
+			cx = vmu_flash_read_char(from + index, &retval, mtd);
+			if (retval) {
+				*retlen = index;
+				kfree(vblock);
+				return cx;
+			}
+			memset(buf + index, cx, 1);
+			index++;
+		}
+		kfree(vblock);
+	} while (len > index);
+	*retlen = index;
+
+	return 0;
+}
+
+static int vmu_flash_write(struct mtd_info *mtd, loff_t to, size_t len,
+	size_t *retlen, const u_char *buf)
+{
+	struct maple_device *mdev;
+	struct memcard *card;
+	struct mdev_part *mpart;
+	int index = 0, partition, error = 0, numblocks;
+	struct vmu_cache *pcache;
+	struct vmu_block *vblock;
+	unsigned char *buffer;
+
+	mpart = mtd->priv;
+	mdev = mpart->mdev;
+	partition = mpart->partition;
+	card = maple_get_drvdata(mdev);
+
+	/* simple sanity checks */
+	if (len < 1) {
+		error = -EIO;
+		goto failed;
+	}
+	numblocks = card->parts[partition].numblocks;
+	if (to + len > numblocks * card->blocklen)
+		len = numblocks * card->blocklen - to;
+	if (len == 0) {
+		error = -EIO;
+		goto failed;
+	}
+
+	vblock = ofs_to_block(to, mtd, partition);
+	if (!vblock) {
+		error = -ENOMEM;
+		goto failed;
+	}
+
+	buffer = kmalloc(card->blocklen, GFP_KERNEL);
+	if (!buffer) {
+		error = -ENOMEM;
+		goto fail_buffer;
+	}
+
+	do {
+		/* Read in the block we are to write to */
+		error = maple_vmu_read_block(vblock->num, buffer, mtd);
+		if (error)
+			goto fail_io;
+
+		do {
+			buffer[vblock->ofs] = buf[index];
+			vblock->ofs++;
+			index++;
+			if (index >= len)
+				break;
+		} while (vblock->ofs < card->blocklen);
+
+		/* write out new buffer */
+		error = maple_vmu_write_block(vblock->num, buffer, mtd);
+		/* invalidate the cache */
+		pcache = card->parts[partition].pcache;
+		pcache->valid = 0;
+
+		if (error != card->blocklen)
+			goto fail_io;
+
+		vblock->num++;
+		vblock->ofs = 0;
+	} while (len > index);
+
+	kfree(buffer);
+	*retlen = index;
+	kfree(vblock);
+	return 0;
+
+fail_io:
+	kfree(buffer);
+fail_buffer:
+	kfree(vblock);
+failed:
+	dev_err(&mdev->dev, "VMU write failing with error %d\n", error);
+	return error;
+}
+
+static void vmu_flash_sync(struct mtd_info *mtd)
+{
+	/* Do nothing here */
+}
+
+/* Maple bus callback function to recursively query hardware details */
+static void vmu_queryblocks(struct mapleq *mq)
+{
+	struct maple_device *mdev;
+	unsigned short *res;
+	struct memcard *card;
+	__be32 partnum;
+	struct vmu_cache *pcache;
+	struct mdev_part *mpart;
+	struct mtd_info *mtd_cur;
+	struct vmupart *part_cur;
+	int error;
+
+	mdev = mq->dev;
+	card = maple_get_drvdata(mdev);
+	res = (unsigned short *) (mq->recvbuf->buf);
+	card->tempA = res[12];
+	card->tempB = res[6];
+
+	dev_info(&mdev->dev, "VMU device at partition %d has %d user "
+		"blocks with a root block at %d\n", card->partition,
+		card->tempA, card->tempB);
+
+	part_cur = &card->parts[card->partition];
+	part_cur->user_blocks = card->tempA;
+	part_cur->root_block = card->tempB;
+	part_cur->numblocks = card->tempB + 1;
+	part_cur->name = kmalloc(12, GFP_KERNEL);
+	if (!part_cur->name)
+		goto fail_name;
+
+	sprintf(part_cur->name, "vmu%d.%d.%d",
+		mdev->port, mdev->unit, card->partition);
+	mtd_cur = &card->mtd[card->partition];
+	mtd_cur->name = part_cur->name;
+	mtd_cur->type = 8;
+	mtd_cur->flags = MTD_WRITEABLE|MTD_NO_ERASE;
+	mtd_cur->size = part_cur->numblocks * card->blocklen;
+	mtd_cur->erasesize = card->blocklen;
+	mtd_cur->write = vmu_flash_write;
+	mtd_cur->read = vmu_flash_read;
+	mtd_cur->sync = vmu_flash_sync;
+	mtd_cur->writesize = card->blocklen;
+
+	mpart = kmalloc(sizeof(struct mdev_part), GFP_KERNEL);
+	if (!mpart)
+		goto fail_mpart;
+
+	mpart->mdev = mdev;
+	mpart->partition = card->partition;
+	mtd_cur->priv = mpart;
+	mtd_cur->owner = THIS_MODULE;
+
+	pcache = kzalloc(sizeof(struct vmu_cache), GFP_KERNEL);
+	if (!pcache)
+		goto fail_cache_create;
+	part_cur->pcache = pcache;
+
+	error = add_mtd_device(mtd_cur);
+	if (error)
+		goto fail_mtd_register;
+
+	maple_getcond_callback(mdev, NULL, 0,
+		MAPLE_FUNC_MEMCARD);
+
+	/*
+	* Set up a recursive call to the (probably theoretical)
+	* second or more partition
+	*/
+	if (++card->partition < card->partitions) {
+		partnum = cpu_to_be32(card->partition << 24);
+		maple_getcond_callback(mdev, vmu_queryblocks, 0,
+			MAPLE_FUNC_MEMCARD);
+		maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
+			MAPLE_COMMAND_GETMINFO, 2, &partnum);
+	}
+	return;
+
+fail_mtd_register:
+	dev_err(&mdev->dev, "Could not register maple device at (%d, %d)"
+		"error is 0x%X\n", mdev->port, mdev->unit, error);
+	for (error = 0; error <= card->partition; error++) {
+		kfree(((card->parts)[error]).pcache);
+		((card->parts)[error]).pcache = NULL;
+	}
+fail_cache_create:
+fail_mpart:
+	for (error = 0; error <= card->partition; error++) {
+		kfree(((card->mtd)[error]).priv);
+		((card->mtd)[error]).priv = NULL;
+	}
+	maple_getcond_callback(mdev, NULL, 0,
+		MAPLE_FUNC_MEMCARD);
+	kfree(part_cur->name);
+fail_name:
+	return;
+}
+
+/* Handles very basic info about the flash, queries for details */
+static int __devinit vmu_connect(struct maple_device *mdev)
+{
+	unsigned long test_flash_data, basic_flash_data;
+	int c, error;
+	struct memcard *card;
+	u32 partnum = 0;
+
+	test_flash_data = be32_to_cpu(mdev->devinfo.function);
+	/* Need to count how many bits are set - to find out which
+	 * function_data element has details of the memory card:
+	 * using Brian Kernighan's/Peter Wegner's method */
+	for (c = 0; test_flash_data; c++)
+		test_flash_data &= test_flash_data - 1;
+
+	basic_flash_data = be32_to_cpu(mdev->devinfo.function_data[c - 1]);
+
+	card = kmalloc(sizeof(struct memcard), GFP_KERNEL);
+	if (!card) {
+		error = ENOMEM;
+		goto fail_nomem;
+	}
+
+	card->partitions = (basic_flash_data >> 24 & 0xFF) + 1;
+	card->blocklen = ((basic_flash_data >> 16 & 0xFF) + 1) << 5;
+	card->writecnt = basic_flash_data >> 12 & 0xF;
+	card->readcnt = basic_flash_data >> 8 & 0xF;
+	card->removeable = basic_flash_data >> 7 & 1;
+
+	card->partition = 0;
+
+	/*
+	* Not sure there are actually any multi-partition devices in the
+	* real world, but the hardware supports them, so, so will we
+	*/
+	card->parts = kmalloc(sizeof(struct vmupart) * card->partitions,
+		GFP_KERNEL);
+	if (!card->parts) {
+		error = -ENOMEM;
+		goto fail_partitions;
+	}
+
+	card->mtd = kmalloc(sizeof(struct mtd_info) * card->partitions,
+		GFP_KERNEL);
+	if (!card->mtd) {
+		error = -ENOMEM;
+		goto fail_mtd_info;
+	}
+
+	maple_set_drvdata(mdev, card);
+
+	/*
+	* We want to trap meminfo not get cond
+	* so set interval to zero, but rely on maple bus
+	* driver to pass back the results of the meminfo
+	*/
+	maple_getcond_callback(mdev, vmu_queryblocks, 0,
+		MAPLE_FUNC_MEMCARD);
+
+	/* Make sure we are clear to go */
+	if (atomic_read(&mdev->busy) == 1) {
+		wait_event_interruptible_timeout(mdev->maple_wait,
+			atomic_read(&mdev->busy) == 0, HZ);
+		if (atomic_read(&mdev->busy) == 1) {
+			dev_notice(&mdev->dev, "VMU at (%d, %d) is busy\n",
+				mdev->port, mdev->unit);
+			error = -EAGAIN;
+			goto fail_device_busy;
+		}
+	}
+
+	atomic_set(&mdev->busy, 1);
+
+	/*
+	* Set up the minfo call: vmu_queryblocks will handle
+	* the information passed back
+	*/
+	error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
+		MAPLE_COMMAND_GETMINFO, 2, &partnum);
+	if (error) {
+		dev_err(&mdev->dev, "Could not lock VMU at (%d, %d)"
+			" error is 0x%X\n", mdev->port, mdev->unit, error);
+		goto fail_mtd_info;
+	}
+	return 0;
+
+fail_device_busy:
+	kfree(card->mtd);
+fail_mtd_info:
+	kfree(card->parts);
+fail_partitions:
+	kfree(card);
+fail_nomem:
+	return error;
+}
+
+static void __devexit vmu_disconnect(struct maple_device *mdev)
+{
+	struct memcard *card;
+	struct mdev_part *mpart;
+	int x;
+
+	mdev->callback = NULL;
+	card = maple_get_drvdata(mdev);
+	for (x = 0; x < card->partitions; x++) {
+		mpart = ((card->mtd)[x]).priv;
+		mpart->mdev = NULL;
+		del_mtd_device(&((card->mtd)[x]));
+		kfree(((card->parts)[x]).name);
+	}
+	kfree(card->parts);
+	kfree(card->mtd);
+	kfree(card);
+}
+
+/* Callback to handle eccentricities of both mtd subsystem
+ * and general flakyness of Dreamcast VMUs
+ */
+static int vmu_can_unload(struct maple_device *mdev)
+{
+	struct memcard *card;
+	int x;
+	struct mtd_info *mtd;
+
+	card = maple_get_drvdata(mdev);
+	for (x = 0; x < card->partitions; x++) {
+		mtd = &((card->mtd)[x]);
+		if (mtd->usecount > 0)
+			return 0;
+	}
+	return 1;
+}
+
+#define ERRSTR "VMU at (%d, %d) file error -"
+
+static void vmu_file_error(struct maple_device *mdev, void *recvbuf)
+{
+	enum maple_file_errors error = ((int *)recvbuf)[1];
+
+	switch (error) {
+
+	case MAPLE_FILEERR_INVALID_PARTITION:
+		dev_notice(&mdev->dev, ERRSTR " invalid partition number\n",
+			mdev->port, mdev->unit);
+		break;
+
+	case MAPLE_FILEERR_PHASE_ERROR:
+		dev_notice(&mdev->dev, ERRSTR " phase error\n",
+			mdev->port, mdev->unit);
+		break;
+
+	case MAPLE_FILEERR_INVALID_BLOCK:
+		dev_notice(&mdev->dev, ERRSTR " invalid block number\n",
+			mdev->port, mdev->unit);
+		break;
+
+	case MAPLE_FILEERR_WRITE_ERROR:
+		dev_notice(&mdev->dev, ERRSTR " write error\n",
+			mdev->port, mdev->unit);
+		break;
+
+	case MAPLE_FILEERR_INVALID_WRITE_LENGTH:
+		dev_notice(&mdev->dev, ERRSTR " invalid write length\n",
+			mdev->port, mdev->unit);
+		break;
+
+	case MAPLE_FILEERR_BAD_CRC:
+		dev_notice(&mdev->dev, ERRSTR " bad CRC\n",
+			mdev->port, mdev->unit);
+		break;
+
+	default:
+		dev_notice(&mdev->dev, ERRSTR " 0x%X\n",
+			mdev->port, mdev->unit, error);
+	}
+}
+
+
+static int __devinit probe_maple_vmu(struct device *dev)
+{
+	int error;
+	struct maple_device *mdev = to_maple_dev(dev);
+	struct maple_driver *mdrv = to_maple_driver(dev->driver);
+
+	mdev->can_unload = vmu_can_unload;
+	mdev->fileerr_handler = vmu_file_error;
+	mdev->driver = mdrv;
+
+	error = vmu_connect(mdev);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+static int __devexit remove_maple_vmu(struct device *dev)
+{
+	struct maple_device *mdev = to_maple_dev(dev);
+
+	vmu_disconnect(mdev);
+	return 0;
+}
+
+static struct maple_driver vmu_flash_driver = {
+	.function =	MAPLE_FUNC_MEMCARD,
+	.drv = {
+		.name =		"Dreamcast_visual_memory",
+		.probe =	probe_maple_vmu,
+		.remove = 	__devexit_p(remove_maple_vmu),
+	},
+};
+
+static int __init vmu_flash_map_init(void)
+{
+	return maple_driver_register(&vmu_flash_driver);
+}
+
+static void __exit vmu_flash_map_exit(void)
+{
+	maple_driver_unregister(&vmu_flash_driver);
+}
+
+module_init(vmu_flash_map_init);
+module_exit(vmu_flash_map_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Adrian McMenamin");
+MODULE_DESCRIPTION("Flash mapping for Sega Dreamcast visual memory");
diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c
index ced14b5..72446fb 100644
--- a/drivers/mtd/nand/excite_nandflash.c
+++ b/drivers/mtd/nand/excite_nandflash.c
@@ -128,11 +128,11 @@
  * The binding to the mtd and all allocated
  * resources are released.
  */
-static int __exit excite_nand_remove(struct device *dev)
+static int __exit excite_nand_remove(struct platform_device *dev)
 {
-	struct excite_nand_drvdata * const this = dev_get_drvdata(dev);
+	struct excite_nand_drvdata * const this = platform_get_drvdata(dev);
 
-	dev_set_drvdata(dev, NULL);
+	platform_set_drvdata(dev, NULL);
 
 	if (unlikely(!this)) {
 		printk(KERN_ERR "%s: called %s without private data!!",
@@ -159,9 +159,8 @@
  * it can allocate all necessary resources then calls the
  * nand layer to look for devices.
 */
-static int __init excite_nand_probe(struct device *dev)
+static int __init excite_nand_probe(struct platform_device *pdev)
 {
-	struct platform_device * const pdev = to_platform_device(dev);
 	struct excite_nand_drvdata *drvdata;	/* private driver data */
 	struct nand_chip *board_chip;	/* private flash chip data */
 	struct mtd_info *board_mtd;	/* mtd info for this board */
@@ -175,7 +174,7 @@
 	}
 
 	/* bind private data into driver */
-	dev_set_drvdata(dev, drvdata);
+	platform_set_drvdata(pdev, drvdata);
 
 	/* allocate and map the resource */
 	drvdata->regs =
@@ -219,23 +218,25 @@
 	return 0;
 }
 
-static struct device_driver excite_nand_driver = {
-	.name = "excite_nand",
-	.bus = &platform_bus_type,
+static struct platform_driver excite_nand_driver = {
+	.driver = {
+		.name = "excite_nand",
+		.owner		= THIS_MODULE,
+	},
 	.probe = excite_nand_probe,
-	.remove = __exit_p(excite_nand_remove)
+	.remove = __devexit_p(excite_nand_remove)
 };
 
 static int __init excite_nand_init(void)
 {
 	pr_info("Basler eXcite nand flash driver Version "
 		EXCITE_NANDFLASH_VERSION "\n");
-	return driver_register(&excite_nand_driver);
+	return platform_driver_register(&excite_nand_driver);
 }
 
 static void __exit excite_nand_exit(void)
 {
-	driver_unregister(&excite_nand_driver);
+	platform_driver_unregister(&excite_nand_driver);
 }
 
 module_init(excite_nand_init);
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 582cf80..89bf85a 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -187,7 +187,7 @@
 		return -ENODEV;
 
 	ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
-				   ndfc->ofdev->dev.bus_id, flash_np->name);
+			dev_name(&ndfc->ofdev->dev), flash_np->name);
 	if (!ndfc->mtd.name) {
 		ret = -ENOMEM;
 		goto err;
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 5b69e77..3a496c3 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -36,10 +36,9 @@
 	struct onenand_chip	onenand;
 };
 
-static int __devinit generic_onenand_probe(struct device *dev)
+static int __devinit generic_onenand_probe(struct platform_device *pdev)
 {
 	struct onenand_info *info;
-	struct platform_device *pdev = to_platform_device(dev);
 	struct flash_platform_data *pdata = pdev->dev.platform_data;
 	struct resource *res = pdev->resource;
 	unsigned long size = res->end - res->start + 1;
@@ -49,7 +48,7 @@
 	if (!info)
 		return -ENOMEM;
 
-	if (!request_mem_region(res->start, size, dev->driver->name)) {
+	if (!request_mem_region(res->start, size, pdev->dev.driver->name)) {
 		err = -EBUSY;
 		goto out_free_info;
 	}
@@ -82,7 +81,7 @@
 #endif
 		err = add_mtd_device(&info->mtd);
 
-	dev_set_drvdata(&pdev->dev, info);
+	platform_set_drvdata(pdev, info);
 
 	return 0;
 
@@ -96,14 +95,13 @@
 	return err;
 }
 
-static int __devexit generic_onenand_remove(struct device *dev)
+static int __devexit generic_onenand_remove(struct platform_device *pdev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct onenand_info *info = dev_get_drvdata(&pdev->dev);
+	struct onenand_info *info = platform_get_drvdata(pdev);
 	struct resource *res = pdev->resource;
 	unsigned long size = res->end - res->start + 1;
 
-	dev_set_drvdata(&pdev->dev, NULL);
+	platform_set_drvdata(pdev, NULL);
 
 	if (info) {
 		if (info->parts)
@@ -120,9 +118,11 @@
 	return 0;
 }
 
-static struct device_driver generic_onenand_driver = {
-	.name		= DRIVER_NAME,
-	.bus		= &platform_bus_type,
+static struct platform_driver generic_onenand_driver = {
+	.driver = {
+		.name		= DRIVER_NAME,
+		.owner		= THIS_MODULE,
+	},
 	.probe		= generic_onenand_probe,
 	.remove		= __devexit_p(generic_onenand_remove),
 };
@@ -131,12 +131,12 @@
 
 static int __init generic_onenand_init(void)
 {
-	return driver_register(&generic_onenand_driver);
+	return platform_driver_register(&generic_onenand_driver);
 }
 
 static void __exit generic_onenand_exit(void)
 {
-	driver_unregister(&generic_onenand_driver);
+	platform_driver_unregister(&generic_onenand_driver);
 }
 
 module_init(generic_onenand_init);
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 4e7a5fa..664835b 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -237,7 +237,7 @@
 {
 }
 
-static int __init mipsnet_probe(struct device *dev)
+static int __init mipsnet_probe(struct platform_device *dev)
 {
 	struct net_device *netdev;
 	int err;
@@ -248,7 +248,7 @@
 		goto out;
 	}
 
-	dev_set_drvdata(dev, netdev);
+	platform_set_drvdata(dev, netdev);
 
 	netdev->open			= mipsnet_open;
 	netdev->stop			= mipsnet_close;
@@ -293,23 +293,25 @@
 	return err;
 }
 
-static int __devexit mipsnet_device_remove(struct device *device)
+static int __devexit mipsnet_device_remove(struct platform_device *device)
 {
-	struct net_device *dev = dev_get_drvdata(device);
+	struct net_device *dev = platform_get_drvdata(device);
 
 	unregister_netdev(dev);
 	release_region(dev->base_addr, sizeof(struct mipsnet_regs));
 	free_netdev(dev);
-	dev_set_drvdata(device, NULL);
+	platform_set_drvdata(device, NULL);
 
 	return 0;
 }
 
-static struct device_driver mipsnet_driver = {
-	.name	= mipsnet_string,
-	.bus	= &platform_bus_type,
-	.probe	= mipsnet_probe,
-	.remove	= __devexit_p(mipsnet_device_remove),
+static struct platform_driver mipsnet_driver = {
+	.driver = {
+		.name		= mipsnet_string,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= mipsnet_probe,
+	.remove		= __devexit_p(mipsnet_device_remove),
 };
 
 static int __init mipsnet_init_module(void)
@@ -319,7 +321,7 @@
 	printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
 	       "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
 
-	err = driver_register(&mipsnet_driver);
+	err = platform_driver_register(&mipsnet_driver);
 	if (err)
 		printk(KERN_ERR "Driver registration failed\n");
 
@@ -328,7 +330,7 @@
 
 static void __exit mipsnet_exit_module(void)
 {
-	driver_unregister(&mipsnet_driver);
+	platform_driver_unregister(&mipsnet_driver);
 }
 
 module_init(mipsnet_init_module);
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index d4fb4ac..4e9bd38 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2649,8 +2649,6 @@
 	int err = -ENODEV;
 
 	sbus_dp = to_of_device(op->dev.parent)->node;
-	if (is_qfe)
-		sbus_dp = to_of_device(op->dev.parent->parent)->node;
 
 	/* We can match PCI devices too, do not accept those here. */
 	if (strcmp(sbus_dp->name, "sbus"))
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index d539d9d..bb5a1c9 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -479,7 +479,7 @@
 	res = &dino_dev->hba.lmmio_space;
 	res->flags = IORESOURCE_MEM;
 	size = scnprintf(name, sizeof(name), "Dino LMMIO (%s)", 
-			 bus->bridge->bus_id);
+			 dev_name(bus->bridge));
 	res->name = kmalloc(size+1, GFP_KERNEL);
 	if(res->name)
 		strcpy((char *)res->name, name);
@@ -493,7 +493,7 @@
 		struct list_head *ln, *tmp_ln;
 
 		printk(KERN_ERR "Dino: cannot attach bus %s\n",
-		       bus->bridge->bus_id);
+		       dev_name(bus->bridge));
 		/* kill the bus, we can't do anything with it */
 		list_for_each_safe(ln, tmp_ln, &bus->devices) {
 			struct pci_dev *dev = pci_dev_b(ln);
@@ -587,7 +587,7 @@
 			bus->resource[i+1] = &res[i];
 		}
 
-	} else if(bus->self) {
+	} else if (bus->parent) {
 		int i;
 
 		pci_read_bridge_bases(bus);
@@ -611,12 +611,12 @@
 			}
 					
 			DBG("DEBUG %s assigning %d [0x%lx,0x%lx]\n",
-			    bus->self->dev.bus_id, i,
+			    dev_name(&bus->self->dev), i,
 			    bus->self->resource[i].start,
 			    bus->self->resource[i].end);
 			pci_assign_resource(bus->self, i);
 			DBG("DEBUG %s after assign %d [0x%lx,0x%lx]\n",
-			    bus->self->dev.bus_id, i,
+			    dev_name(&bus->self->dev), i,
 			    bus->self->resource[i].start,
 			    bus->self->resource[i].end);
 		}
@@ -1026,7 +1026,8 @@
 		dino_current_bus = bus->subordinate + 1;
 		pci_bus_assign_resources(bus);
 	} else {
-		printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", dev->dev.bus_id, dino_current_bus);
+		printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n",
+		       dev_name(&dev->dev), dino_current_bus);
 		/* increment the bus number in case of duplicates */
 		dino_current_bus++;
 	}
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index e76db9e..d336329 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -186,29 +186,34 @@
 	*irqp = irq;
 }
 
-static struct device *next_device(struct klist_iter *i)
+struct gsc_fixup_struct {
+	void (*choose_irq)(struct parisc_device *, void *);
+	void *ctrl;
+};
+
+static int gsc_fixup_irqs_callback(struct device *dev, void *data)
 {
-	struct klist_node * n = klist_next(i);
-	return n ? container_of(n, struct device, knode_parent) : NULL;
+	struct parisc_device *padev = to_parisc_device(dev);
+	struct gsc_fixup_struct *gf = data;
+
+	/* work-around for 715/64 and others which have parent
+	   at path [5] and children at path [5/0/x] */
+	if (padev->id.hw_type == HPHW_FAULTY)
+		gsc_fixup_irqs(padev, gf->ctrl, gf->choose_irq);
+	gf->choose_irq(padev, gf->ctrl);
+
+	return 0;
 }
 
 void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
 			void (*choose_irq)(struct parisc_device *, void *))
 {
-	struct device *dev;
-	struct klist_iter i;
+	struct gsc_fixup_struct data = {
+		.choose_irq	= choose_irq,
+		.ctrl		= ctrl,
+	};
 
-	klist_iter_init(&parent->dev.klist_children, &i);
-	while ((dev = next_device(&i))) {
-		struct parisc_device *padev = to_parisc_device(dev);
-
-		/* work-around for 715/64 and others which have parent 
-		   at path [5] and children at path [5/0/x] */
-		if (padev->id.hw_type == HPHW_FAULTY)
-			return gsc_fixup_irqs(padev, ctrl, choose_irq);
-		choose_irq(padev, ctrl);
-	}
-	klist_iter_exit(&i);
+	device_for_each_child(&parent->dev, &data, gsc_fixup_irqs_callback);
 }
 
 int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 0797659..501aaf1 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -487,7 +487,7 @@
 	}
 
 	/* Check if pcidev behind a PPB */
-	if (NULL != pcidev->bus->self) {
+	if (pcidev->bus->parent) {
 		/* Convert pcidev INTR_PIN into something we
 		** can lookup in the IRT.
 		*/
@@ -523,10 +523,9 @@
 #endif /* PCI_BRIDGE_FUNCS */
 
 		/*
-		** Locate the host slot the PPB nearest the Host bus
-		** adapter.
-		*/
-		while (NULL != p->parent->self)
+		 * Locate the host slot of the PPB.
+		 */
+		while (p->parent->parent)
 			p = p->parent;
 
 		intr_slot = PCI_SLOT(p->self->devfn);
@@ -709,11 +708,14 @@
 	struct vector_info *vi = iosapic_get_vector(irq);
 	u32 d0, d1, dummy_d0;
 	unsigned long flags;
+	int dest_cpu;
 
-	if (cpu_check_affinity(irq, dest))
+	dest_cpu = cpu_check_affinity(irq, dest);
+	if (dest_cpu < 0)
 		return;
 
-	vi->txn_addr = txn_affinity_addr(irq, cpumask_first(dest));
+	irq_desc[irq].affinity = cpumask_of_cpu(dest_cpu);
+	vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
 
 	spin_lock_irqsave(&iosapic_lock, flags);
 	/* d1 contains the destination CPU, so only want to set that
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index d8233de..59fbbf1 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -644,7 +644,7 @@
 	** Properly Setup MMIO resources for this bus.
 	** pci_alloc_primary_bus() mangles this.
 	*/
-	if (bus->self) {
+	if (bus->parent) {
 		int i;
 		/* PCI-PCI Bridge */
 		pci_read_bridge_bases(bus);
@@ -802,7 +802,7 @@
 ** Can't fixup here anyway....garr...
 */
 	if (fbb_enable) {
-		if (bus->self) {
+		if (bus->parent) {
 			u8 control;
 			/* enable on PPB */
 			(void) pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &control);
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index a70cf16..e5999c4 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -1206,31 +1206,49 @@
 	return (void *) pdir_base;
 }
 
-static struct device *next_device(struct klist_iter *i)
+struct ibase_data_struct {
+	struct ioc *ioc;
+	int ioc_num;
+};
+
+static int setup_ibase_imask_callback(struct device *dev, void *data)
 {
-        struct klist_node * n = klist_next(i);
-        return n ? container_of(n, struct device, knode_parent) : NULL;
+	/* lba_set_iregs() is in drivers/parisc/lba_pci.c */
+        extern void lba_set_iregs(struct parisc_device *, u32, u32);
+	struct parisc_device *lba = to_parisc_device(dev);
+	struct ibase_data_struct *ibd = data;
+	int rope_num = (lba->hpa.start >> 13) & 0xf;
+	if (rope_num >> 3 == ibd->ioc_num)
+		lba_set_iregs(lba, ibd->ioc->ibase, ibd->ioc->imask);
+	return 0;
 }
 
 /* setup Mercury or Elroy IBASE/IMASK registers. */
 static void 
 setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 {
-	/* lba_set_iregs() is in drivers/parisc/lba_pci.c */
-        extern void lba_set_iregs(struct parisc_device *, u32, u32);
-	struct device *dev;
-	struct klist_iter i;
+	struct ibase_data_struct ibase_data = {
+		.ioc		= ioc,
+		.ioc_num	= ioc_num,
+	};
 
-	klist_iter_init(&sba->dev.klist_children, &i);
-	while ((dev = next_device(&i))) {
-		struct parisc_device *lba = to_parisc_device(dev);
-		int rope_num = (lba->hpa.start >> 13) & 0xf;
-		if (rope_num >> 3 == ioc_num)
-			lba_set_iregs(lba, ioc->ibase, ioc->imask);
-	}
-	klist_iter_exit(&i);
+	device_for_each_child(&sba->dev, &ibase_data,
+			      setup_ibase_imask_callback);
 }
 
+#ifdef SBA_AGP_SUPPORT
+static int
+sba_ioc_find_quicksilver(struct device *dev, void *data)
+{
+	int *agp_found = data;
+	struct parisc_device *lba = to_parisc_device(dev);
+
+	if (IS_QUICKSILVER(lba))
+		*agp_found = 1;
+	return 0;
+}
+#endif
+
 static void
 sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 {
@@ -1332,9 +1350,6 @@
 	WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM);
 
 #ifdef SBA_AGP_SUPPORT
-{
-	struct klist_iter i;
-	struct device *dev = NULL;
 
 	/*
 	** If an AGP device is present, only use half of the IOV space
@@ -1344,13 +1359,7 @@
 	** We program the next pdir index after we stop w/ a key for
 	** the GART code to handshake on.
 	*/
-	klist_iter_init(&sba->dev.klist_children, &i);
-	while ((dev = next_device(&i))) {
-		struct parisc_device *lba = to_parisc_device(dev);
-		if (IS_QUICKSILVER(lba))
-			agp_found = 1;
-	}
-	klist_iter_exit(&i);
+	device_for_each_child(&sba->dev, &agp_found, sba_ioc_find_quicksilver);
 
 	if (agp_found && sba_reserve_agpgart) {
 		printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n",
@@ -1358,9 +1367,7 @@
 		ioc->pdir_size /= 2;
 		ioc->pdir_base[PDIR_INDEX(iova_space_size/2)] = SBA_AGPGART_COOKIE;
 	}
-}
 #endif /*SBA_AGP_SUPPORT*/
-
 }
 
 static void
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index eacfb13..9aa4fe1 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -143,7 +143,7 @@
 
 config HOTPLUG_PCI_RPA
 	tristate "RPA PCI Hotplug driver"
-	depends on PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
+	depends on PPC_PSERIES && EEH && !HOTPLUG_PCI_FAKE
 	help
 	  Say Y here if you have a RPA system that supports PCI Hotplug.
 
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index a13abf5..8450f4a 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -225,7 +225,8 @@
 
 void cpqhp_create_debugfs_files(struct controller *ctrl)
 {
-	ctrl->dentry = debugfs_create_file(ctrl->pci_dev->dev.bus_id, S_IRUGO, root, ctrl, &debug_ops);
+	ctrl->dentry = debugfs_create_file(dev_name(&ctrl->pci_dev->dev),
+					   S_IRUGO, root, ctrl, &debug_ops);
 }
 
 void cpqhp_remove_debugfs_files(struct controller *ctrl)
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index d0c9736..3825750 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -133,6 +133,9 @@
 						   bool enable)
 {
 	set_device_error_reporting(dev, &enable);
+
+	if (!dev->subordinate)
+		return;
 	pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
 }
 
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 248b4db..5ea566e 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -103,6 +103,7 @@
 static void pcie_portdrv_remove (struct pci_dev *dev)
 {
 	pcie_port_device_remove(dev);
+	pci_disable_device(dev);
 	kfree(pci_get_drvdata(dev));
 }
 
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index f20d553..92b9efe 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -23,6 +23,7 @@
 #include <linux/acpi.h>
 #include <linux/kallsyms.h>
 #include <linux/dmi.h>
+#include <linux/pci-aspm.h>
 #include "pci.h"
 
 int isa_dma_bridge_buggy;
@@ -1749,6 +1750,30 @@
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt);
 
+/*
+ * The 82575 and 82598 may experience data corruption issues when transitioning
+ * out of L0S.  To prevent this we need to disable L0S on the pci-e link
+ */
+static void __devinit quirk_disable_aspm_l0s(struct pci_dev *dev)
+{
+	dev_info(&dev->dev, "Disabling L0s\n");
+	pci_disable_link_state(dev, PCIE_LINK_STATE_L0S);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a7, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a9, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10b6, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c6, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c7, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c8, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10d6, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10db, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10dd, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10e1, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10ec, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
+
 static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
 {
 	/* rev 1 ncr53c810 chips don't set the class at all which means
@@ -2097,7 +2122,7 @@
 
 		if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
 					 &flags) == 0) {
-			dev_info(&dev->dev, "Enabling HT MSI Mapping\n");
+			dev_info(&dev->dev, "Disabling HT MSI Mapping\n");
 
 			pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
 					      flags & ~HT_MSI_FLAGS_ENABLE);
@@ -2141,6 +2166,10 @@
 	int pos;
 	int found;
 
+	/* Enabling HT MSI mapping on this device breaks MCP51 */
+	if (dev->device == 0x270)
+		return;
+
 	/* check if there is HT MSI cap or enabled on this device */
 	found = ht_check_msi_mapping(dev);
 
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index fc1de46..9001334 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -468,13 +468,13 @@
 	return ret;
 }
 
-int au1x00_drv_pcmcia_remove(struct device *dev)
+int au1x00_drv_pcmcia_remove(struct platform_device *dev)
 {
-	struct skt_dev_info *sinfo = dev_get_drvdata(dev);
+	struct skt_dev_info *sinfo = platform_get_drvdata(dev);
 	int i;
 
 	mutex_lock(&pcmcia_sockets_lock);
-	dev_set_drvdata(dev, NULL);
+	platform_set_drvdata(dev, NULL);
 
 	for (i = 0; i < sinfo->nskt; i++) {
 		struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i);
@@ -498,13 +498,13 @@
  * PCMCIA "Driver" API
  */
 
-static int au1x00_drv_pcmcia_probe(struct device *dev)
+static int au1x00_drv_pcmcia_probe(struct platform_device *dev)
 {
 	int i, ret = -ENODEV;
 
 	mutex_lock(&pcmcia_sockets_lock);
 	for (i=0; i < ARRAY_SIZE(au1x00_pcmcia_hw_init); i++) {
-		ret = au1x00_pcmcia_hw_init[i](dev);
+		ret = au1x00_pcmcia_hw_init[i](&dev->dev);
 		if (ret == 0)
 			break;
 	}
@@ -512,14 +512,26 @@
 	return ret;
 }
 
+static int au1x00_drv_pcmcia_suspend(struct platform_device *dev,
+				     pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&dev->dev, state);
+}
 
-static struct device_driver au1x00_pcmcia_driver = {
+static int au1x00_drv_pcmcia_resume(struct platform_device *dev)
+{
+	return pcmcia_socket_dev_resume(&dev->dev);
+}
+
+static struct platform_driver au1x00_pcmcia_driver = {
+	.driver = {
+		.name		= "au1x00-pcmcia",
+		.owner		= THIS_MODULE,
+	},
 	.probe		= au1x00_drv_pcmcia_probe,
 	.remove		= au1x00_drv_pcmcia_remove,
-	.name		= "au1x00-pcmcia",
-	.bus		= &platform_bus_type,
-	.suspend	= pcmcia_socket_dev_suspend,
-	.resume		= pcmcia_socket_dev_resume,
+	.suspend 	= au1x00_drv_pcmcia_suspend,
+	.resume 	= au1x00_drv_pcmcia_resume,
 };
 
 
@@ -533,8 +545,7 @@
 static int __init au1x00_pcmcia_init(void)
 {
 	int error = 0;
-	if ((error = driver_register(&au1x00_pcmcia_driver)))
-		return error;
+	error = platform_driver_register(&au1x00_pcmcia_driver);
 	return error;
 }
 
@@ -544,7 +555,7 @@
  */
 static void __exit au1x00_pcmcia_exit(void)
 {
-	driver_unregister(&au1x00_pcmcia_driver);
+	platform_driver_unregister(&au1x00_pcmcia_driver);
 }
 
 module_init(au1x00_pcmcia_init);
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 71653ab..40d4953 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1238,6 +1238,16 @@
 	return 0;
 }
 
+static int i82365_drv_pcmcia_suspend(struct platform_device *dev,
+				     pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&dev->dev, state);
+}
+
+static int i82365_drv_pcmcia_resume(struct platform_device *dev)
+{
+	return pcmcia_socket_dev_resume(&dev->dev);
+}
 static struct pccard_operations pcic_operations = {
 	.init			= pcic_init,
 	.get_status		= pcic_get_status,
@@ -1248,11 +1258,13 @@
 
 /*====================================================================*/
 
-static struct device_driver i82365_driver = {
-	.name = "i82365",
-	.bus = &platform_bus_type,
-	.suspend = pcmcia_socket_dev_suspend,
-	.resume = pcmcia_socket_dev_resume,
+static struct platform_driver i82365_driver = {
+	.driver = {
+		.name = "i82365",
+		.owner		= THIS_MODULE,
+	},
+	.suspend 	= i82365_drv_pcmcia_suspend,
+	.resume 	= i82365_drv_pcmcia_resume,
 };
 
 static struct platform_device *i82365_device;
@@ -1261,7 +1273,7 @@
 {
     int i, ret;
 
-    ret = driver_register(&i82365_driver);
+    ret = platform_driver_register(&i82365_driver);
     if (ret)
 	goto err_out;
 
@@ -1337,7 +1349,7 @@
 	pnp_disable_dev(i82365_pnpdev);
 #endif
 err_driver_unregister:
-    driver_unregister(&i82365_driver);
+    platform_driver_unregister(&i82365_driver);
 err_out:
     return ret;
 } /* init_i82365 */
@@ -1365,7 +1377,7 @@
     if (i82365_pnpdev)
     		pnp_disable_dev(i82365_pnpdev);
 #endif
-    driver_unregister(&i82365_driver);
+    platform_driver_unregister(&i82365_driver);
 } /* exit_i82365 */
 
 module_init(init_i82365);
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 2ab4f22..62b4ecc 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -696,13 +696,25 @@
 	.set_mem_map		= pcc_set_mem_map,
 };
 
+static int cfc_drv_pcmcia_suspend(struct platform_device *dev,
+				     pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&dev->dev, state);
+}
+
+static int cfc_drv_pcmcia_resume(struct platform_device *dev)
+{
+	return pcmcia_socket_dev_resume(&dev->dev);
+}
 /*====================================================================*/
 
-static struct device_driver pcc_driver = {
-	.name = "cfc",
-	.bus = &platform_bus_type,
-	.suspend = pcmcia_socket_dev_suspend,
-	.resume = pcmcia_socket_dev_resume,
+static struct platform_driver pcc_driver = {
+	.driver = {
+		.name		= "cfc",
+		.owner		= THIS_MODULE,
+	},
+	.suspend 	= cfc_drv_pcmcia_suspend,
+	.resume 	= cfc_drv_pcmcia_resume,
 };
 
 static struct platform_device pcc_device = {
@@ -716,13 +728,13 @@
 {
 	int i, ret;
 
-	ret = driver_register(&pcc_driver);
+	ret = platform_driver_register(&pcc_driver);
 	if (ret)
 		return ret;
 
 	ret = platform_device_register(&pcc_device);
 	if (ret){
-		driver_unregister(&pcc_driver);
+		platform_driver_unregister(&pcc_driver);
 		return ret;
 	}
 
@@ -754,7 +766,7 @@
 	if (pcc_sockets == 0) {
 		printk("socket is not found.\n");
 		platform_device_unregister(&pcc_device);
-		driver_unregister(&pcc_driver);
+		platform_driver_unregister(&pcc_driver);
 		return -ENODEV;
 	}
 
@@ -802,7 +814,7 @@
 	if (poll_interval != 0)
 		del_timer_sync(&poll_timer);
 
-	driver_unregister(&pcc_driver);
+	platform_driver_unregister(&pcc_driver);
 } /* exit_m32r_pcc */
 
 module_init(init_m32r_pcc);
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 2f108c2..12034b4 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -672,13 +672,25 @@
 	.set_mem_map		= pcc_set_mem_map,
 };
 
+static int pcc_drv_pcmcia_suspend(struct platform_device *dev,
+				     pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&dev->dev, state);
+}
+
+static int pcc_drv_pcmcia_resume(struct platform_device *dev)
+{
+	return pcmcia_socket_dev_resume(&dev->dev);
+}
 /*====================================================================*/
 
-static struct device_driver pcc_driver = {
-	.name = "pcc",
-	.bus = &platform_bus_type,
-	.suspend = pcmcia_socket_dev_suspend,
-	.resume = pcmcia_socket_dev_resume,
+static struct platform_driver pcc_driver = {
+	.driver = {
+		.name		= "pcc",
+		.owner		= THIS_MODULE,
+	},
+	.suspend 	= pcc_drv_pcmcia_suspend,
+	.resume 	= pcc_drv_pcmcia_resume,
 };
 
 static struct platform_device pcc_device = {
@@ -692,13 +704,13 @@
 {
 	int i, ret;
 
-	ret = driver_register(&pcc_driver);
+	ret = platform_driver_register(&pcc_driver);
 	if (ret)
 		return ret;
 
 	ret = platform_device_register(&pcc_device);
 	if (ret){
-		driver_unregister(&pcc_driver);
+		platform_driver_unregister(&pcc_driver);
 		return ret;
 	}
 
@@ -715,7 +727,7 @@
 	if (pcc_sockets == 0) {
 		printk("socket is not found.\n");
 		platform_device_unregister(&pcc_device);
-		driver_unregister(&pcc_driver);
+		platform_driver_unregister(&pcc_driver);
 		return -ENODEV;
 	}
 
@@ -763,7 +775,7 @@
 	if (poll_interval != 0)
 		del_timer_sync(&poll_timer);
 
-	driver_unregister(&pcc_driver);
+	platform_driver_unregister(&pcc_driver);
 } /* exit_m32r_pcc */
 
 module_init(init_m32r_pcc);
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index c0e2afc..e592e0e 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -153,7 +153,7 @@
 		unsigned long align, struct pcmcia_socket *s)
 {
 	struct resource *res = make_resource(0, num, IORESOURCE_IO,
-					     s->dev.bus_id);
+					     dev_name(&s->dev));
 	struct pcmcia_align_data data;
 	unsigned long min = base;
 	int ret;
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index c5b2a44..d8da5ac 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -65,7 +65,7 @@
 #endif
 };
 
-static int sa11x0_drv_pcmcia_probe(struct device *dev)
+static int sa11x0_drv_pcmcia_probe(struct platform_device *dev)
 {
 	int i, ret = -ENODEV;
 
@@ -73,7 +73,7 @@
 	 * Initialise any "on-board" PCMCIA sockets.
 	 */
 	for (i = 0; i < ARRAY_SIZE(sa11x0_pcmcia_hw_init); i++) {
-		ret = sa11x0_pcmcia_hw_init[i](dev);
+		ret = sa11x0_pcmcia_hw_init[i](&dev->dev);
 		if (ret == 0)
 			break;
 	}
@@ -81,13 +81,31 @@
 	return ret;
 }
 
-static struct device_driver sa11x0_pcmcia_driver = {
+static int sa11x0_drv_pcmcia_remove(struct platform_device *dev)
+{
+	return soc_common_drv_pcmcia_remove(&dev->dev);
+}
+
+static int sa11x0_drv_pcmcia_suspend(struct platform_device *dev,
+				     pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&dev->dev, state);
+}
+
+static int sa11x0_drv_pcmcia_resume(struct platform_device *dev)
+{
+	return pcmcia_socket_dev_resume(&dev->dev);
+}
+
+static struct platform_driver sa11x0_pcmcia_driver = {
+	.driver = {
+		.name		= "sa11x0-pcmcia",
+		.owner		= THIS_MODULE,
+	},
 	.probe		= sa11x0_drv_pcmcia_probe,
-	.remove		= soc_common_drv_pcmcia_remove,
-	.name		= "sa11x0-pcmcia",
-	.bus		= &platform_bus_type,
-	.suspend 	= pcmcia_socket_dev_suspend,
-	.resume 	= pcmcia_socket_dev_resume,
+	.remove		= sa11x0_drv_pcmcia_remove,
+	.suspend 	= sa11x0_drv_pcmcia_suspend,
+	.resume 	= sa11x0_drv_pcmcia_resume,
 };
 
 /* sa11x0_pcmcia_init()
@@ -100,7 +118,7 @@
  */
 static int __init sa11x0_pcmcia_init(void)
 {
-	return driver_register(&sa11x0_pcmcia_driver);
+	return platform_driver_register(&sa11x0_pcmcia_driver);
 }
 
 /* sa11x0_pcmcia_exit()
@@ -110,7 +128,7 @@
  */
 static void __exit sa11x0_pcmcia_exit(void)
 {
-	driver_unregister(&sa11x0_pcmcia_driver);
+	platform_driver_unregister(&sa11x0_pcmcia_driver);
 }
 
 MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 2a613e9..9ad97ea 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -363,13 +363,25 @@
     return id;
 }
 
+static int tcic_drv_pcmcia_suspend(struct platform_device *dev,
+				     pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&dev->dev, state);
+}
+
+static int tcic_drv_pcmcia_resume(struct platform_device *dev)
+{
+	return pcmcia_socket_dev_resume(&dev->dev);
+}
 /*====================================================================*/
 
-static struct device_driver tcic_driver = {
-	.name = "tcic-pcmcia",
-	.bus = &platform_bus_type,
-	.suspend = pcmcia_socket_dev_suspend,
-	.resume = pcmcia_socket_dev_resume,
+static struct platform_driver tcic_driver = {
+	.driver = {
+		.name = "tcic-pcmcia",
+		.owner		= THIS_MODULE,
+	},
+	.suspend 	= tcic_drv_pcmcia_suspend,
+	.resume 	= tcic_drv_pcmcia_resume,
 };
 
 static struct platform_device tcic_device = {
@@ -383,7 +395,7 @@
     int i, sock, ret = 0;
     u_int mask, scan;
 
-    if (driver_register(&tcic_driver))
+    if (platform_driver_register(&tcic_driver))
 	return -1;
     
     printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
@@ -391,7 +403,7 @@
 
     if (!request_region(tcic_base, 16, "tcic-2")) {
 	printk("could not allocate ports,\n ");
-	driver_unregister(&tcic_driver);
+	platform_driver_unregister(&tcic_driver);
 	return -ENODEV;
     }
     else {
@@ -414,7 +426,7 @@
     if (sock == 0) {
 	printk("not found.\n");
 	release_region(tcic_base, 16);
-	driver_unregister(&tcic_driver);
+	platform_driver_unregister(&tcic_driver);
 	return -ENODEV;
     }
 
@@ -542,7 +554,7 @@
     }
 
     platform_device_unregister(&tcic_device);
-    driver_unregister(&tcic_driver);
+    platform_driver_unregister(&tcic_driver);
 } /* exit_tcic */
 
 /*====================================================================*/
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index b2c4124..659421d 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -704,24 +704,37 @@
 
 __setup("vrc4171_card=", vrc4171_card_setup);
 
-static struct device_driver vrc4171_card_driver = {
-	.name		= vrc4171_card_name,
-	.bus		= &platform_bus_type,
-	.suspend	= pcmcia_socket_dev_suspend,
-	.resume		= pcmcia_socket_dev_resume,
+static int vrc4171_card_suspend(struct platform_device *dev,
+				     pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&dev->dev, state);
+}
+
+static int vrc4171_card_resume(struct platform_device *dev)
+{
+	return pcmcia_socket_dev_resume(&dev->dev);
+}
+
+static struct platform_driver vrc4171_card_driver = {
+	.driver = {
+		.name		= vrc4171_card_name,
+		.owner		= THIS_MODULE,
+	},
+	.suspend	= vrc4171_card_suspend,
+	.resume		= vrc4171_card_resume,
 };
 
 static int __devinit vrc4171_card_init(void)
 {
 	int retval;
 
-	retval = driver_register(&vrc4171_card_driver);
+	retval = platform_driver_register(&vrc4171_card_driver);
 	if (retval < 0)
 		return retval;
 
 	retval = platform_device_register(&vrc4171_card_device);
 	if (retval < 0) {
-		driver_unregister(&vrc4171_card_driver);
+		platform_driver_unregister(&vrc4171_card_driver);
 		return retval;
 	}
 
@@ -735,11 +748,12 @@
 	if (retval < 0) {
 		vrc4171_remove_sockets();
 		platform_device_unregister(&vrc4171_card_device);
-		driver_unregister(&vrc4171_card_driver);
+		platform_driver_unregister(&vrc4171_card_driver);
 		return retval;
 	}
 
-	printk(KERN_INFO "%s, connected to IRQ %d\n", vrc4171_card_driver.name, vrc4171_irq);
+	printk(KERN_INFO "%s, connected to IRQ %d\n",
+		vrc4171_card_driver.driver.name, vrc4171_irq);
 
 	return 0;
 }
@@ -749,7 +763,7 @@
 	free_irq(vrc4171_irq, vrc4171_sockets);
 	vrc4171_remove_sockets();
 	platform_device_unregister(&vrc4171_card_device);
-	driver_unregister(&vrc4171_card_driver);
+	platform_driver_unregister(&vrc4171_card_driver);
 }
 
 module_init(vrc4171_card_init);
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index b3866ad..3608081 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -15,8 +15,7 @@
 if X86_PLATFORM_DEVICES
 
 config ACER_WMI
-	tristate "Acer WMI Laptop Extras (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "Acer WMI Laptop Extras"
 	depends on ACPI
 	depends on LEDS_CLASS
 	depends on NEW_LEDS
@@ -39,9 +38,9 @@
 	tristate "Asus Laptop Extras (EXPERIMENTAL)"
 	depends on ACPI
 	depends on EXPERIMENTAL && !ACPI_ASUS
-	depends on LEDS_CLASS
-	depends on NEW_LEDS
-	depends on BACKLIGHT_CLASS_DEVICE
+	select LEDS_CLASS
+	select NEW_LEDS
+	select BACKLIGHT_CLASS_DEVICE
 	depends on INPUT
 	---help---
 	  This is the new Linux driver for Asus laptops. It may also support some
@@ -185,11 +184,11 @@
 config THINKPAD_ACPI
 	tristate "ThinkPad ACPI Laptop Extras"
 	depends on ACPI
+	depends on INPUT
 	select BACKLIGHT_LCD_SUPPORT
 	select BACKLIGHT_CLASS_DEVICE
 	select HWMON
 	select NVRAM
-	select INPUT
 	select NEW_LEDS
 	select LEDS_CLASS
 	select NET
@@ -315,9 +314,8 @@
 
 
 config ACPI_WMI
-	tristate "WMI (EXPERIMENTAL)"
+	tristate "WMI"
 	depends on ACPI
-	depends on EXPERIMENTAL
 	help
 	  This driver adds support for the ACPI-WMI (Windows Management
 	  Instrumentation) mapper device (PNP0C14) found on some systems.
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 94c9f911..a6a42e8 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1026,7 +1026,7 @@
 	kfree(wireless_rfkill->data);
 	rfkill_unregister(wireless_rfkill);
 	if (has_cap(ACER_CAP_BLUETOOTH)) {
-		kfree(wireless_rfkill->data);
+		kfree(bluetooth_rfkill->data);
 		rfkill_unregister(bluetooth_rfkill);
 	}
 	return;
@@ -1297,7 +1297,7 @@
 
 	set_quirks();
 
-	if (!acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
+	if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
 		interface->capability &= ~ACER_CAP_BRIGHTNESS;
 		printk(ACER_INFO "Brightness must be controlled by "
 		       "generic video driver\n");
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 56af6cf..eeafc6c 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -815,6 +815,7 @@
 static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
 	static struct key_entry *key;
+	u16 count;
 
 	/* TODO Find a better way to handle events count. */
 	if (!hotk)
@@ -832,9 +833,11 @@
 		lcd_blank(FB_BLANK_POWERDOWN);
 	}
 
+	count = hotk->event_count[event % 128]++;
+	acpi_bus_generate_proc_event(hotk->device, event, count);
 	acpi_bus_generate_netlink_event(hotk->device->pnp.device_class,
 					dev_name(&hotk->device->dev), event,
-					hotk->event_count[event % 128]++);
+					count);
 
 	if (hotk->inputdev) {
 		key = asus_get_entry_by_scancode(event);
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 786ed86..6f54fd1 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -557,13 +557,17 @@
 static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
 	static struct key_entry *key;
+	u16 count;
+
 	if (!ehotk)
 		return;
 	if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
 		notify_brn();
+	count = ehotk->event_count[event % 128]++;
+	acpi_bus_generate_proc_event(ehotk->device, event, count);
 	acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
 					dev_name(&ehotk->device->dev), event,
-					ehotk->event_count[event % 128]++);
+					count);
 	if (ehotk->inputdev) {
 		key = eepc_get_entry_by_scancode(event);
 		if (key) {
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index bcbc051..d243320 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -7532,7 +7532,7 @@
  * if it is not there yet.
  */
 #define IBM_BIOS_MODULE_ALIAS(__type) \
-	MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW")
+	MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW*")
 
 /* Non-ancient thinkpads */
 MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
@@ -7541,9 +7541,9 @@
 /* Ancient thinkpad BIOSes have to be identified by
  * BIOS type or model number, and there are far less
  * BIOS types than model numbers... */
-IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]");
-IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]");
-IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
+IBM_BIOS_MODULE_ALIAS("I[BDHIMNOTWVYZ]");
+IBM_BIOS_MODULE_ALIAS("1[0368A-GIKM-PST]");
+IBM_BIOS_MODULE_ALIAS("K[UX-Z]");
 
 MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
 MODULE_DESCRIPTION(TPACPI_DESC);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 8a8b377..2f269e11 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -708,7 +708,7 @@
 
 static int __init acpi_wmi_init(void)
 {
-	acpi_status result;
+	int result;
 
 	INIT_LIST_HEAD(&wmi_blocks.list);
 
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index 1d76892..a52d4a1 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -180,10 +180,13 @@
 	di->empty_uAh = battery_interpolate(scale, di->temp_C / 10);
 	di->empty_uAh *= 1000; /* convert to µAh */
 
-	/* From Maxim Application Note 131: remaining capacity =
-	 * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */
-	di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) /
-			    (di->full_active_uAh - di->empty_uAh);
+	if (di->full_active_uAh == di->empty_uAh)
+		di->rem_capacity = 0;
+	else
+		/* From Maxim Application Note 131: remaining capacity =
+		 * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */
+		di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) /
+				    (di->full_active_uAh - di->empty_uAh);
 
 	if (di->rem_capacity < 0)
 		di->rem_capacity = 0;
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index addb87c..3222fa3 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -193,7 +193,7 @@
 }
 
 static struct device rio_bus = {
-	.bus_id = "rapidio",
+	.init_name = "rapidio",
 };
 
 struct bus_type rio_bus_type = {
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index d5e4e63..86c61f1 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -351,7 +351,7 @@
 	/* register irq handler after we know what name we'll use */
 	ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
 				IRQF_DISABLED | IRQF_SHARED,
-				rtc->rtcdev->dev.bus_id, rtc);
+				dev_name(&rtc->rtcdev->dev), rtc);
 	if (ret) {
 		dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS);
 		rtc_device_unregister(rtc->rtcdev);
@@ -366,7 +366,7 @@
 
 	if (gpbr_readl(rtc) == 0)
 		dev_warn(&pdev->dev, "%s: SET TIME!\n",
-				rtc->rtcdev->dev.bus_id);
+				dev_name(&rtc->rtcdev->dev));
 
 	return 0;
 
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 2cbeb07..bd1ce8e 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -377,13 +377,13 @@
 
 	/* handle periodic and alarm irqs */
 	if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED,
-			rtc->dev.bus_id, rtc)) {
+			dev_name(&rtc->dev), rtc)) {
 		pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
 			pdev->name, omap_rtc_timer);
 		goto fail0;
 	}
 	if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED,
-			rtc->dev.bus_id, rtc)) {
+			dev_name(&rtc->dev), rtc)) {
 		pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
 			pdev->name, omap_rtc_alarm);
 		goto fail1;
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 1c3fc6b..4898f7f 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -28,7 +28,7 @@
 #include <asm/rtc.h>
 
 #define DRV_NAME	"sh-rtc"
-#define DRV_VERSION	"0.2.0"
+#define DRV_VERSION	"0.2.1"
 
 #define RTC_REG(r)	((r) * rtc_reg_size)
 
@@ -99,56 +99,51 @@
 	unsigned short periodic_freq;
 };
 
-static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
+static int __sh_rtc_interrupt(struct sh_rtc *rtc)
 {
-	struct sh_rtc *rtc = dev_id;
-	unsigned int tmp;
-
-	spin_lock(&rtc->lock);
+	unsigned int tmp, pending;
 
 	tmp = readb(rtc->regbase + RCR1);
+	pending = tmp & RCR1_CF;
 	tmp &= ~RCR1_CF;
 	writeb(tmp, rtc->regbase + RCR1);
 
 	/* Users have requested One x Second IRQ */
-	if (rtc->periodic_freq & PF_OXS)
+	if (pending && rtc->periodic_freq & PF_OXS)
 		rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
 
-	spin_unlock(&rtc->lock);
-
-	return IRQ_HANDLED;
+	return pending;
 }
 
-static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
+static int __sh_rtc_alarm(struct sh_rtc *rtc)
 {
-	struct sh_rtc *rtc = dev_id;
-	unsigned int tmp;
-
-	spin_lock(&rtc->lock);
+	unsigned int tmp, pending;
 
 	tmp = readb(rtc->regbase + RCR1);
+	pending = tmp & RCR1_AF;
 	tmp &= ~(RCR1_AF | RCR1_AIE);
-		writeb(tmp, rtc->regbase + RCR1);
+	writeb(tmp, rtc->regbase + RCR1);
 
-	rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+	if (pending)
+		rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
 
-	spin_unlock(&rtc->lock);
-
-	return IRQ_HANDLED;
+	return pending;
 }
 
-static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
+static int __sh_rtc_periodic(struct sh_rtc *rtc)
 {
-	struct sh_rtc *rtc = dev_id;
 	struct rtc_device *rtc_dev = rtc->rtc_dev;
-	unsigned int tmp;
-
-	spin_lock(&rtc->lock);
+	struct rtc_task *irq_task;
+	unsigned int tmp, pending;
 
 	tmp = readb(rtc->regbase + RCR2);
+	pending = tmp & RCR2_PEF;
 	tmp &= ~RCR2_PEF;
 	writeb(tmp, rtc->regbase + RCR2);
 
+	if (!pending)
+		return 0;
+
 	/* 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;
@@ -157,16 +152,65 @@
 			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);
+			irq_task = rtc_dev->irq_task;
+			if (irq_task)
+				irq_task->func(irq_task->private_data);
 			spin_unlock(&rtc_dev->irq_task_lock);
 		} else
 			rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
 	}
 
+	return pending;
+}
+
+static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
+{
+	struct sh_rtc *rtc = dev_id;
+	int ret;
+
+	spin_lock(&rtc->lock);
+	ret = __sh_rtc_interrupt(rtc);
 	spin_unlock(&rtc->lock);
 
-	return IRQ_HANDLED;
+	return IRQ_RETVAL(ret);
+}
+
+static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
+{
+	struct sh_rtc *rtc = dev_id;
+	int ret;
+
+	spin_lock(&rtc->lock);
+	ret = __sh_rtc_alarm(rtc);
+	spin_unlock(&rtc->lock);
+
+	return IRQ_RETVAL(ret);
+}
+
+static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
+{
+	struct sh_rtc *rtc = dev_id;
+	int ret;
+
+	spin_lock(&rtc->lock);
+	ret = __sh_rtc_periodic(rtc);
+	spin_unlock(&rtc->lock);
+
+	return IRQ_RETVAL(ret);
+}
+
+static irqreturn_t sh_rtc_shared(int irq, void *dev_id)
+{
+	struct sh_rtc *rtc = dev_id;
+	int ret;
+
+	spin_lock(&rtc->lock);
+	ret = __sh_rtc_interrupt(rtc);
+	ret |= __sh_rtc_alarm(rtc);
+	ret |= __sh_rtc_periodic(rtc);
+	spin_unlock(&rtc->lock);
+
+	return IRQ_RETVAL(ret);
 }
 
 static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
@@ -275,6 +319,25 @@
 	return 0;
 }
 
+static inline void sh_rtc_setcie(struct device *dev, unsigned int enable)
+{
+	struct sh_rtc *rtc = dev_get_drvdata(dev);
+	unsigned int tmp;
+
+	spin_lock_irq(&rtc->lock);
+
+	tmp = readb(rtc->regbase + RCR1);
+
+	if (!enable)
+		tmp &= ~RCR1_CIE;
+	else
+		tmp |= RCR1_CIE;
+
+	writeb(tmp, rtc->regbase + RCR1);
+
+	spin_unlock_irq(&rtc->lock);
+}
+
 static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
 	struct sh_rtc *rtc = dev_get_drvdata(dev);
@@ -291,9 +354,11 @@
 		break;
 	case RTC_UIE_OFF:
 		rtc->periodic_freq &= ~PF_OXS;
+		sh_rtc_setcie(dev, 0);
 		break;
 	case RTC_UIE_ON:
 		rtc->periodic_freq |= PF_OXS;
+		sh_rtc_setcie(dev, 1);
 		break;
 	case RTC_IRQP_READ:
 		ret = put_user(rtc->rtc_dev->irq_freq,
@@ -356,18 +421,17 @@
 		tm->tm_sec--;
 #endif
 
+	/* only keep the carry interrupt enabled if UIE is on */
+	if (!(rtc->periodic_freq & PF_OXS))
+		sh_rtc_setcie(dev, 0);
+
 	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
 		"mday=%d, mon=%d, year=%d, wday=%d\n",
 		__func__,
 		tm->tm_sec, tm->tm_min, tm->tm_hour,
 		tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
 
-	if (rtc_valid_tm(tm) < 0) {
-		dev_err(dev, "invalid date\n");
-		rtc_time_to_tm(0, tm);
-	}
-
-	return 0;
+	return rtc_valid_tm(tm);
 }
 
 static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -572,7 +636,7 @@
 {
 	struct sh_rtc *rtc;
 	struct resource *res;
-	unsigned int tmp;
+	struct rtc_time r;
 	int ret;
 
 	rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
@@ -585,26 +649,12 @@
 	ret = platform_get_irq(pdev, 0);
 	if (unlikely(ret <= 0)) {
 		ret = -ENOENT;
-		dev_err(&pdev->dev, "No IRQ for period\n");
+		dev_err(&pdev->dev, "No IRQ resource\n");
 		goto err_badres;
 	}
 	rtc->periodic_irq = ret;
-
-	ret = platform_get_irq(pdev, 1);
-	if (unlikely(ret <= 0)) {
-		ret = -ENOENT;
-		dev_err(&pdev->dev, "No IRQ for carry\n");
-		goto err_badres;
-	}
-	rtc->carry_irq = ret;
-
-	ret = platform_get_irq(pdev, 2);
-	if (unlikely(ret <= 0)) {
-		ret = -ENOENT;
-		dev_err(&pdev->dev, "No IRQ for alarm\n");
-		goto err_badres;
-	}
-	rtc->alarm_irq = ret;
+	rtc->carry_irq = platform_get_irq(pdev, 1);
+	rtc->alarm_irq = platform_get_irq(pdev, 2);
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (unlikely(res == NULL)) {
@@ -646,47 +696,66 @@
 	}
 
 	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_unmap;
+	if (rtc->carry_irq <= 0) {
+		/* register shared periodic/carry/alarm irq */
+		ret = request_irq(rtc->periodic_irq, sh_rtc_shared,
+				  IRQF_DISABLED, "sh-rtc", rtc);
+		if (unlikely(ret)) {
+			dev_err(&pdev->dev,
+				"request IRQ failed with %d, IRQ %d\n", ret,
+				rtc->periodic_irq);
+			goto err_unmap;
+		}
+	} else {
+		/* 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_unmap;
+		}
+
+		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_unmap;
+		}
+
+		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_unmap;
+		}
 	}
 
-	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_unmap;
+	/* everything disabled by default */
+	rtc->periodic_freq = 0;
+	rtc->rtc_dev->irq_freq = 0;
+	sh_rtc_setpie(&pdev->dev, 0);
+	sh_rtc_setaie(&pdev->dev, 0);
+	sh_rtc_setcie(&pdev->dev, 0);
+
+	/* reset rtc to epoch 0 if time is invalid */
+	if (rtc_read_time(rtc->rtc_dev, &r) < 0) {
+		rtc_time_to_tm(0, &r);
+		rtc_set_time(rtc->rtc_dev, &r);
 	}
 
-	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_unmap;
-	}
-
-	tmp = readb(rtc->regbase + RCR1);
-	tmp &= ~RCR1_CF;
-	tmp |= RCR1_CIE;
-	writeb(tmp, rtc->regbase + RCR1);
-
+	device_init_wakeup(&pdev->dev, 1);
 	return 0;
 
 err_unmap:
@@ -708,10 +777,13 @@
 
 	sh_rtc_setpie(&pdev->dev, 0);
 	sh_rtc_setaie(&pdev->dev, 0);
+	sh_rtc_setcie(&pdev->dev, 0);
 
-	free_irq(rtc->carry_irq, rtc);
 	free_irq(rtc->periodic_irq, rtc);
-	free_irq(rtc->alarm_irq, rtc);
+	if (rtc->carry_irq > 0) {
+		free_irq(rtc->carry_irq, rtc);
+		free_irq(rtc->alarm_irq, rtc);
+	}
 
 	release_resource(rtc->res);
 
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c
index ad35f76..a6341e4 100644
--- a/drivers/rtc/rtc-twl4030.c
+++ b/drivers/rtc/rtc-twl4030.c
@@ -426,7 +426,7 @@
 
 	ret = request_irq(irq, twl4030_rtc_interrupt,
 				IRQF_TRIGGER_RISING,
-				rtc->dev.bus_id, rtc);
+				dev_name(&rtc->dev), rtc);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "IRQ is not free.\n");
 		goto out1;
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 918e6fc..b91c171 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -104,8 +104,9 @@
 	rc = device_schedule_callback(dev, ccwgroup_ungroup_callback);
 out:
 	if (rc) {
-		/* Release onoff "lock" when ungrouping failed. */
-		atomic_set(&gdev->onoff, 0);
+		if (rc != -EAGAIN)
+			/* Release onoff "lock" when ungrouping failed. */
+			atomic_set(&gdev->onoff, 0);
 		return rc;
 	}
 	return count;
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 0a2f2ed..93eca17 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -84,8 +84,8 @@
 		kfree(private);
 	} else {
 		sch->private = private;
-		if (sch->dev.uevent_suppress) {
-			sch->dev.uevent_suppress = 0;
+		if (dev_get_uevent_suppress(&sch->dev)) {
+			dev_set_uevent_suppress(&sch->dev, 0);
 			kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
 		}
 	}
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 8019288..427d11d 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -272,7 +272,7 @@
 	 * the subchannel driver can decide itself when it wants to inform
 	 * userspace of its existence.
 	 */
-	sch->dev.uevent_suppress = 1;
+	dev_set_uevent_suppress(&sch->dev, 1);
 	css_update_ssd_info(sch);
 	/* make it known to the system */
 	ret = css_sch_device_register(sch);
@@ -287,7 +287,7 @@
 		 * a fitting driver module may be loaded based on the
 		 * modalias.
 		 */
-		sch->dev.uevent_suppress = 0;
+		dev_set_uevent_suppress(&sch->dev, 0);
 		kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
 	}
 	return ret;
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 23d5752..e28f8ae 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -799,7 +799,7 @@
 		return;
 	other_sch = to_subchannel(cdev->dev.parent);
 	/* Note: device_move() changes cdev->dev.parent */
-	ret = device_move(&cdev->dev, &sch->dev);
+	ret = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV);
 	if (ret) {
 		CIO_MSG_EVENT(0, "Moving disconnected device 0.%x.%04x failed "
 			      "(ret=%d)!\n", cdev->private->dev_id.ssid,
@@ -830,7 +830,7 @@
 	 * Try to move the ccw device to its new subchannel.
 	 * Note: device_move() changes cdev->dev.parent
 	 */
-	ret = device_move(&cdev->dev, &sch->dev);
+	ret = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV);
 	if (ret) {
 		CIO_MSG_EVENT(0, "Moving device 0.%x.%04x from orphanage "
 			      "failed (ret=%d)!\n",
@@ -897,7 +897,8 @@
 	 * ccw device can take its place on the subchannel.
 	 * Note: device_move() changes cdev->dev.parent
 	 */
-	ret = device_move(&cdev->dev, &css->pseudo_subchannel->dev);
+	ret = device_move(&cdev->dev, &css->pseudo_subchannel->dev,
+		DPM_ORDER_NONE);
 	if (ret) {
 		CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to orphanage failed "
 			      "(ret=%d)!\n", cdev->private->dev_id.ssid,
@@ -981,7 +982,7 @@
 	 * Now we know this subchannel will stay, we can throw
 	 * our delayed uevent.
 	 */
-	sch->dev.uevent_suppress = 0;
+	dev_set_uevent_suppress(&sch->dev, 0);
 	kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
 	/* make it known to the system */
 	ret = ccw_device_register(cdev);
@@ -1129,7 +1130,7 @@
 	 * Try to move the ccw device to its new subchannel.
 	 * Note: device_move() changes cdev->dev.parent
 	 */
-	rc = device_move(&cdev->dev, &sch->dev);
+	rc = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV);
 	mutex_unlock(&sch->reg_mutex);
 	if (rc) {
 		CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to subchannel "
@@ -1243,7 +1244,7 @@
 		 * the ccw_device and exit. This happens for all early
 		 * devices, e.g. the console.
 		 */
-		sch->dev.uevent_suppress = 0;
+		dev_set_uevent_suppress(&sch->dev, 0);
 		kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
 		cdev->dev.groups = ccwdev_attr_groups;
 		device_initialize(&cdev->dev);
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index f08e169..7e30e5f 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -129,7 +129,7 @@
 	bp->waiting = 1;
 	add_wait_queue(&bp->wq, &wait);
 	while (limit-- > 0) {
-		unsigned long val;
+		long val;
 
 		val = wait_event_interruptible_timeout(
 				bp->wq,
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index a9a9893..e6d1fc8 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -38,9 +38,6 @@
 #include <linux/string.h>
 #include <linux/genhd.h>
 #include <linux/blkdev.h>
-
-#define MAJOR_NR	JSFD_MAJOR
-
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 29dc735..124f660 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -51,6 +51,7 @@
 MODULE_DESCRIPTION("OPENPROM Configuration Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("1.0");
+MODULE_ALIAS_MISCDEV(SUN_OPENPROM_MINOR);
 
 /* Private data kept by the driver for each descriptor. */
 typedef struct openprom_private_data
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c
index d4bda20..61af3d9 100644
--- a/drivers/scsi/a4000t.c
+++ b/drivers/scsi/a4000t.c
@@ -35,7 +35,7 @@
 
 #define A4000T_SCSI_ADDR 0xdd0040
 
-static int __devinit a4000t_probe(struct device *dev)
+static int __devinit a4000t_probe(struct platform_device *dev)
 {
 	struct Scsi_Host *host;
 	struct NCR_700_Host_Parameters *hostdata;
@@ -61,7 +61,8 @@
 	hostdata->dcntl_extra = EA_710;
 
 	/* and register the chip */
-	host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, dev);
+	host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata,
+			      &dev->dev);
 	if (!host) {
 		printk(KERN_ERR "a4000t-scsi: No host detected; "
 				"board configuration problem?\n");
@@ -78,7 +79,7 @@
 		goto out_put_host;
 	}
 
-	dev_set_drvdata(dev, host);
+	platform_set_drvdata(dev, host);
 	scsi_scan_host(host);
 
 	return 0;
@@ -93,9 +94,9 @@
 	return -ENODEV;
 }
 
-static __devexit int a4000t_device_remove(struct device *dev)
+static __devexit int a4000t_device_remove(struct platform_device *dev)
 {
-	struct Scsi_Host *host = dev_get_drvdata(dev);
+	struct Scsi_Host *host = platform_get_drvdata(dev);
 	struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
 
 	scsi_remove_host(host);
@@ -108,25 +109,27 @@
 	return 0;
 }
 
-static struct device_driver a4000t_scsi_driver = {
-	.name	= "a4000t-scsi",
-	.bus	= &platform_bus_type,
-	.probe	= a4000t_probe,
-	.remove	= __devexit_p(a4000t_device_remove),
+static struct platform_driver a4000t_scsi_driver = {
+	.driver = {
+		.name           = "a4000t-scsi",
+		.owner          = THIS_MODULE,
+	},
+	.probe          = a4000t_probe,
+	.remove         = __devexit_p(a4000t_device_remove),
 };
 
 static int __init a4000t_scsi_init(void)
 {
 	int err;
 
-	err = driver_register(&a4000t_scsi_driver);
+	err = platform_driver_register(&a4000t_scsi_driver);
 	if (err)
 		return err;
 
 	a4000t_scsi_device = platform_device_register_simple("a4000t-scsi",
 			-1, NULL, 0);
 	if (IS_ERR(a4000t_scsi_device)) {
-		driver_unregister(&a4000t_scsi_driver);
+		platform_driver_register(&a4000t_scsi_driver);
 		return PTR_ERR(a4000t_scsi_device);
 	}
 
@@ -136,7 +139,7 @@
 static void __exit a4000t_scsi_exit(void)
 {
 	platform_device_unregister(a4000t_scsi_device);
-	driver_unregister(&a4000t_scsi_driver);
+	platform_driver_unregister(&a4000t_scsi_driver);
 }
 
 module_init(a4000t_scsi_init);
diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c
index d858f3d..5799cb5 100644
--- a/drivers/scsi/bvme6000_scsi.c
+++ b/drivers/scsi/bvme6000_scsi.c
@@ -34,7 +34,7 @@
 static struct platform_device *bvme6000_scsi_device;
 
 static __devinit int
-bvme6000_probe(struct device *dev)
+bvme6000_probe(struct platform_device *dev)
 {
 	struct Scsi_Host *host;
 	struct NCR_700_Host_Parameters *hostdata;
@@ -58,7 +58,8 @@
 	hostdata->ctest7_extra = CTEST7_TT1;
 
 	/* and register the chip */
-	host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, dev);
+	host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata,
+			      &dev->dev);
 	if (!host) {
 		printk(KERN_ERR "bvme6000-scsi: No host detected; "
 				"board configuration problem?\n");
@@ -73,7 +74,7 @@
 		goto out_put_host;
 	}
 
-	dev_set_drvdata(dev, host);
+	platform_set_drvdata(dev, host);
 	scsi_scan_host(host);
 
 	return 0;
@@ -87,9 +88,9 @@
 }
 
 static __devexit int
-bvme6000_device_remove(struct device *dev)
+bvme6000_device_remove(struct platform_device *dev)
 {
-	struct Scsi_Host *host = dev_get_drvdata(dev);
+	struct Scsi_Host *host = platform_get_drvdata(dev);
 	struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
 
 	scsi_remove_host(host);
@@ -100,25 +101,27 @@
 	return 0;
 }
 
-static struct device_driver bvme6000_scsi_driver = {
-	.name	= "bvme6000-scsi",
-	.bus	= &platform_bus_type,
-	.probe	= bvme6000_probe,
-	.remove	= __devexit_p(bvme6000_device_remove),
+static struct platform_driver bvme6000_scsi_driver = {
+	.driver = {
+		.name		= "bvme6000-scsi",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= bvme6000_probe,
+	.remove		= __devexit_p(bvme6000_device_remove),
 };
 
 static int __init bvme6000_scsi_init(void)
 {
 	int err;
 
-	err = driver_register(&bvme6000_scsi_driver);
+	err = platform_driver_register(&bvme6000_scsi_driver);
 	if (err)
 		return err;
 
 	bvme6000_scsi_device = platform_device_register_simple("bvme6000-scsi",
 							       -1, NULL, 0);
 	if (IS_ERR(bvme6000_scsi_device)) {
-		driver_unregister(&bvme6000_scsi_driver);
+		platform_driver_unregister(&bvme6000_scsi_driver);
 		return PTR_ERR(bvme6000_scsi_device);
 	}
 
@@ -128,7 +131,7 @@
 static void __exit bvme6000_scsi_exit(void)
 {
 	platform_device_unregister(bvme6000_scsi_device);
-	driver_unregister(&bvme6000_scsi_driver);
+	platform_driver_unregister(&bvme6000_scsi_driver);
 }
 
 module_init(bvme6000_scsi_init);
diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c
index bf7fe6f..8862758 100644
--- a/drivers/scsi/fcoe/fc_transport_fcoe.c
+++ b/drivers/scsi/fcoe/fc_transport_fcoe.c
@@ -33,19 +33,19 @@
 static DEFINE_MUTEX(fcoe_transports_lock);
 
 /**
- * fcoe_transport_default - returns ptr to the default transport fcoe_sw
- **/
+ * fcoe_transport_default() - Returns ptr to the default transport fcoe_sw
+ */
 struct fcoe_transport *fcoe_transport_default(void)
 {
 	return &fcoe_sw_transport;
 }
 
 /**
- * fcoe_transport_to_pcidev - get the pci dev from a netdev
+ * fcoe_transport_to_pcidev() - get the pci dev from a netdev
  * @netdev: the netdev that pci dev will be retrived from
  *
  * Returns: NULL or the corrsponding pci_dev
- **/
+ */
 struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev)
 {
 	if (!netdev->dev.parent)
@@ -54,18 +54,17 @@
 }
 
 /**
- * fcoe_transport_device_lookup - find out netdev is managed by the
- * transport
- * assign a transport to a device
+ * fcoe_transport_device_lookup() - Lookup a transport
  * @netdev: the netdev the transport to be attached to
  *
  * This will look for existing offload driver, if not found, it falls back to
  * the default sw hba (fcoe_sw) as its fcoe transport.
  *
  * Returns: 0 for success
- **/
-static struct fcoe_transport_internal *fcoe_transport_device_lookup(
-	struct fcoe_transport *t, struct net_device *netdev)
+ */
+static struct fcoe_transport_internal *
+fcoe_transport_device_lookup(struct fcoe_transport *t,
+			     struct net_device *netdev)
 {
 	struct fcoe_transport_internal *ti;
 
@@ -81,14 +80,14 @@
 	return NULL;
 }
 /**
- * fcoe_transport_device_add - assign a transport to a device
+ * fcoe_transport_device_add() - Assign a transport to a device
  * @netdev: the netdev the transport to be attached to
  *
  * This will look for existing offload driver, if not found, it falls back to
  * the default sw hba (fcoe_sw) as its fcoe transport.
  *
  * Returns: 0 for success
- **/
+ */
 static int fcoe_transport_device_add(struct fcoe_transport *t,
 				     struct net_device *netdev)
 {
@@ -123,14 +122,14 @@
 }
 
 /**
- * fcoe_transport_device_remove - remove a device from its transport
+ * fcoe_transport_device_remove() - Remove a device from its transport
  * @netdev: the netdev the transport to be attached to
  *
- * this removes the device from the transport so the given transport will
+ * This removes the device from the transport so the given transport will
  * not manage this device any more
  *
  * Returns: 0 for success
- **/
+ */
 static int fcoe_transport_device_remove(struct fcoe_transport *t,
 					struct net_device *netdev)
 {
@@ -155,13 +154,13 @@
 }
 
 /**
- * fcoe_transport_device_remove_all - remove all from transport devlist
+ * fcoe_transport_device_remove_all() - Remove all from transport devlist
  *
- * this removes the device from the transport so the given transport will
+ * This removes the device from the transport so the given transport will
  * not manage this device any more
  *
  * Returns: 0 for success
- **/
+ */
 static void fcoe_transport_device_remove_all(struct fcoe_transport *t)
 {
 	struct fcoe_transport_internal *ti, *tmp;
@@ -175,18 +174,18 @@
 }
 
 /**
- * fcoe_transport_match - use the bus device match function to match the hw
- * @t: the fcoe transport
- * @netdev:
+ * fcoe_transport_match() - Use the bus device match function to match the hw
+ * @t: The fcoe transport to check
+ * @netdev: The netdev to match against
  *
- * This function is used to check if the givne transport wants to manage the
+ * This function is used to check if the given transport wants to manage the
  * input netdev. if the transports implements the match function, it will be
  * called, o.w. we just compare the pci vendor and device id.
  *
  * Returns: true for match up
- **/
+ */
 static bool fcoe_transport_match(struct fcoe_transport *t,
-				struct net_device *netdev)
+				 struct net_device *netdev)
 {
 	/* match transport by vendor and device id */
 	struct pci_dev *pci;
@@ -210,17 +209,17 @@
 }
 
 /**
- * fcoe_transport_lookup - check if the transport is already registered
+ * fcoe_transport_lookup() - Check if the transport is already registered
  * @t: the transport to be looked up
  *
  * This compares the parent device (pci) vendor and device id
  *
  * Returns: NULL if not found
  *
- * TODO - return default sw transport if no other transport is found
- **/
-static struct fcoe_transport *fcoe_transport_lookup(
-	struct net_device *netdev)
+ * TODO: return default sw transport if no other transport is found
+ */
+static struct fcoe_transport *
+fcoe_transport_lookup(struct net_device *netdev)
 {
 	struct fcoe_transport *t;
 
@@ -239,11 +238,11 @@
 }
 
 /**
- * fcoe_transport_register - adds a fcoe transport to the fcoe transports list
+ * fcoe_transport_register() - Adds a fcoe transport to the fcoe transports list
  * @t: ptr to the fcoe transport to be added
  *
  * Returns: 0 for success
- **/
+ */
 int fcoe_transport_register(struct fcoe_transport *t)
 {
 	struct fcoe_transport *tt;
@@ -259,9 +258,6 @@
 	list_add_tail(&t->list, &fcoe_transports);
 	mutex_unlock(&fcoe_transports_lock);
 
-	mutex_init(&t->devlock);
-	INIT_LIST_HEAD(&t->devlist);
-
 	printk(KERN_DEBUG "fcoe_transport_register:%s\n", t->name);
 
 	return 0;
@@ -269,11 +265,11 @@
 EXPORT_SYMBOL_GPL(fcoe_transport_register);
 
 /**
- * fcoe_transport_unregister - remove the tranport fro the fcoe transports list
+ * fcoe_transport_unregister() - Remove the tranport fro the fcoe transports list
  * @t: ptr to the fcoe transport to be removed
  *
  * Returns: 0 for success
- **/
+ */
 int fcoe_transport_unregister(struct fcoe_transport *t)
 {
 	struct fcoe_transport *tt, *tmp;
@@ -294,8 +290,8 @@
 }
 EXPORT_SYMBOL_GPL(fcoe_transport_unregister);
 
-/*
- * fcoe_load_transport_driver - load an offload driver by alias name
+/**
+ * fcoe_load_transport_driver() - Load an offload driver by alias name
  * @netdev: the target net device
  *
  * Requests for an offload driver module as the fcoe transport, if fails, it
@@ -307,7 +303,7 @@
  * 	3. pure hw fcoe hba may not have netdev
  *
  * Returns: 0 for success
- **/
+ */
 int fcoe_load_transport_driver(struct net_device *netdev)
 {
 	struct pci_dev *pci;
@@ -335,14 +331,14 @@
 EXPORT_SYMBOL_GPL(fcoe_load_transport_driver);
 
 /**
- * fcoe_transport_attach - load transport to fcoe
+ * fcoe_transport_attach() - Load transport to fcoe
  * @netdev: the netdev the transport to be attached to
  *
  * This will look for existing offload driver, if not found, it falls back to
  * the default sw hba (fcoe_sw) as its fcoe transport.
  *
  * Returns: 0 for success
- **/
+ */
 int fcoe_transport_attach(struct net_device *netdev)
 {
 	struct fcoe_transport *t;
@@ -373,11 +369,11 @@
 EXPORT_SYMBOL_GPL(fcoe_transport_attach);
 
 /**
- * fcoe_transport_release - unload transport from fcoe
+ * fcoe_transport_release() - Unload transport from fcoe
  * @netdev: the net device on which fcoe is to be released
  *
  * Returns: 0 for success
- **/
+ */
 int fcoe_transport_release(struct net_device *netdev)
 {
 	struct fcoe_transport *t;
@@ -410,12 +406,12 @@
 EXPORT_SYMBOL_GPL(fcoe_transport_release);
 
 /**
- * fcoe_transport_init - initializes fcoe transport layer
+ * fcoe_transport_init() - Initializes fcoe transport layer
  *
  * This prepares for the fcoe transport layer
  *
  * Returns: none
- **/
+ */
 int __init fcoe_transport_init(void)
 {
 	INIT_LIST_HEAD(&fcoe_transports);
@@ -424,12 +420,13 @@
 }
 
 /**
- * fcoe_transport_exit - cleans up the fcoe transport layer
+ * fcoe_transport_exit() - Cleans up the fcoe transport layer
+ *
  * This cleans up the fcoe transport layer. removing any transport on the list,
  * note that the transport destroy func is not called here.
  *
  * Returns: none
- **/
+ */
 int __exit fcoe_transport_exit(void)
 {
 	struct fcoe_transport *t, *tmp;
diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c
index dc4cd5e..da210eb 100644
--- a/drivers/scsi/fcoe/fcoe_sw.c
+++ b/drivers/scsi/fcoe/fcoe_sw.c
@@ -104,19 +104,19 @@
 	.max_sectors = 0xffff,
 };
 
-/*
- * fcoe_sw_lport_config - sets up the fc_lport
+/**
+ * fcoe_sw_lport_config() - sets up the fc_lport
  * @lp: ptr to the fc_lport
  * @shost: ptr to the parent scsi host
  *
  * Returns: 0 for success
- *
  */
 static int fcoe_sw_lport_config(struct fc_lport *lp)
 {
 	int i = 0;
 
-	lp->link_status = 0;
+	lp->link_up = 0;
+	lp->qfull = 0;
 	lp->max_retry_count = 3;
 	lp->e_d_tov = 2 * 1000;	/* FC-FS default */
 	lp->r_a_tov = 2 * 2 * 1000;
@@ -136,16 +136,14 @@
 	return 0;
 }
 
-/*
- * fcoe_sw_netdev_config - sets up fcoe_softc for lport and network
- * related properties
+/**
+ * fcoe_sw_netdev_config() - Set up netdev for SW FCoE
  * @lp : ptr to the fc_lport
  * @netdev : ptr to the associated netdevice struct
  *
  * Must be called after fcoe_sw_lport_config() as it will use lport mutex
  *
  * Returns : 0 for success
- *
  */
 static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 {
@@ -181,9 +179,8 @@
 	if (fc_set_mfs(lp, mfs))
 		return -EINVAL;
 
-	lp->link_status = ~FC_PAUSE & ~FC_LINK_UP;
 	if (!fcoe_link_ok(lp))
-		lp->link_status |= FC_LINK_UP;
+		lp->link_up = 1;
 
 	/* offload features support */
 	if (fc->real_dev->features & NETIF_F_SG)
@@ -191,6 +188,7 @@
 
 
 	skb_queue_head_init(&fc->fcoe_pending_queue);
+	fc->fcoe_pending_queue_active = 0;
 
 	/* setup Source Mac Address */
 	memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr,
@@ -224,16 +222,15 @@
 	return 0;
 }
 
-/*
- * fcoe_sw_shost_config - sets up fc_lport->host
+/**
+ * fcoe_sw_shost_config() - Sets up fc_lport->host
  * @lp : ptr to the fc_lport
  * @shost : ptr to the associated scsi host
  * @dev : device associated to scsi host
  *
- * Must be called after fcoe_sw_lport_config) and fcoe_sw_netdev_config()
+ * Must be called after fcoe_sw_lport_config() and fcoe_sw_netdev_config()
  *
  * Returns : 0 for success
- *
  */
 static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
 				struct device *dev)
@@ -261,8 +258,8 @@
 	return 0;
 }
 
-/*
- * fcoe_sw_em_config - allocates em for this lport
+/**
+ * fcoe_sw_em_config() - allocates em for this lport
  * @lp: the port that em is to allocated for
  *
  * Returns : 0 on success
@@ -279,8 +276,8 @@
 	return 0;
 }
 
-/*
- * fcoe_sw_destroy - FCoE software HBA tear-down function
+/**
+ * fcoe_sw_destroy() - FCoE software HBA tear-down function
  * @netdev: ptr to the associated net_device
  *
  * Returns: 0 if link is OK for use by FCoE.
@@ -301,7 +298,7 @@
 	if (!lp)
 		return -ENODEV;
 
-	fc = fcoe_softc(lp);
+	fc = lport_priv(lp);
 
 	/* Logout of the fabric */
 	fc_fabric_logoff(lp);
@@ -353,8 +350,8 @@
 	.frame_send = fcoe_xmit,
 };
 
-/*
- * fcoe_sw_create - this function creates the fcoe interface
+/**
+ * fcoe_sw_create() - this function creates the fcoe interface
  * @netdev: pointer the associated netdevice
  *
  * Creates fc_lport struct and scsi_host for lport, configures lport
@@ -440,8 +437,8 @@
 	return rc;
 }
 
-/*
- * fcoe_sw_match - the fcoe sw transport match function
+/**
+ * fcoe_sw_match() - The FCoE SW transport match function
  *
  * Returns : false always
  */
@@ -461,8 +458,8 @@
 	.device = 0xffff,
 };
 
-/*
- * fcoe_sw_init - registers fcoe_sw_transport
+/**
+ * fcoe_sw_init() - Registers fcoe_sw_transport
  *
  * Returns : 0 on success
  */
@@ -471,17 +468,22 @@
 	/* attach to scsi transport */
 	scsi_transport_fcoe_sw =
 		fc_attach_transport(&fcoe_sw_transport_function);
+
 	if (!scsi_transport_fcoe_sw) {
 		printk(KERN_ERR "fcoe_sw_init:fc_attach_transport() failed\n");
 		return -ENODEV;
 	}
+
+	mutex_init(&fcoe_sw_transport.devlock);
+	INIT_LIST_HEAD(&fcoe_sw_transport.devlist);
+
 	/* register sw transport */
 	fcoe_transport_register(&fcoe_sw_transport);
 	return 0;
 }
 
-/*
- * fcoe_sw_exit - unregisters fcoe_sw_transport
+/**
+ * fcoe_sw_exit() - Unregisters fcoe_sw_transport
  *
  * Returns : 0 on success
  */
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index e419f48..5548bf3 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -49,6 +49,7 @@
 static int debug_fcoe;
 
 #define FCOE_MAX_QUEUE_DEPTH  256
+#define FCOE_LOW_QUEUE_DEPTH  32
 
 /* destination address mode */
 #define FCOE_GW_ADDR_MODE	    0x00
@@ -69,8 +70,6 @@
 
 /* Function Prototyes */
 static int fcoe_check_wait_queue(struct fc_lport *);
-static void fcoe_insert_wait_queue_head(struct fc_lport *, struct sk_buff *);
-static void fcoe_insert_wait_queue(struct fc_lport *, struct sk_buff *);
 static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *);
 #ifdef CONFIG_HOTPLUG_CPU
 static int fcoe_cpu_callback(struct notifier_block *, ulong, void *);
@@ -91,13 +90,13 @@
 };
 
 /**
- * fcoe_create_percpu_data - creates the associated cpu data
+ * fcoe_create_percpu_data() - creates the associated cpu data
  * @cpu: index for the cpu where fcoe cpu data will be created
  *
  * create percpu stats block, from cpu add notifier
  *
  * Returns: none
- **/
+ */
 static void fcoe_create_percpu_data(int cpu)
 {
 	struct fc_lport *lp;
@@ -115,13 +114,13 @@
 }
 
 /**
- * fcoe_destroy_percpu_data - destroys the associated cpu data
+ * fcoe_destroy_percpu_data() - destroys the associated cpu data
  * @cpu: index for the cpu where fcoe cpu data will destroyed
  *
  * destroy percpu stats block called by cpu add/remove notifier
  *
  * Retuns: none
- **/
+ */
 static void fcoe_destroy_percpu_data(int cpu)
 {
 	struct fc_lport *lp;
@@ -137,7 +136,7 @@
 }
 
 /**
- * fcoe_cpu_callback - fcoe cpu hotplug event callback
+ * fcoe_cpu_callback() - fcoe cpu hotplug event callback
  * @nfb: callback data block
  * @action: event triggering the callback
  * @hcpu: index for the cpu of this event
@@ -145,7 +144,7 @@
  * this creates or destroys per cpu data for fcoe
  *
  * Returns NOTIFY_OK always.
- **/
+ */
 static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action,
 			     void *hcpu)
 {
@@ -166,7 +165,7 @@
 #endif /* CONFIG_HOTPLUG_CPU */
 
 /**
- * fcoe_rcv - this is the fcoe receive function called by NET_RX_SOFTIRQ
+ * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ
  * @skb: the receive skb
  * @dev: associated net device
  * @ptype: context
@@ -175,7 +174,7 @@
  * this function will receive the packet and build fc frame and pass it up
  *
  * Returns: 0 for success
- **/
+ */
 int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
 	     struct packet_type *ptype, struct net_device *olddev)
 {
@@ -265,11 +264,11 @@
 EXPORT_SYMBOL_GPL(fcoe_rcv);
 
 /**
- * fcoe_start_io - pass to netdev to start xmit for fcoe
+ * fcoe_start_io() - pass to netdev to start xmit for fcoe
  * @skb: the skb to be xmitted
  *
  * Returns: 0 for success
- **/
+ */
 static inline int fcoe_start_io(struct sk_buff *skb)
 {
 	int rc;
@@ -283,12 +282,12 @@
 }
 
 /**
- * fcoe_get_paged_crc_eof - in case we need alloc a page for crc_eof
+ * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof
  * @skb: the skb to be xmitted
  * @tlen: total len
  *
  * Returns: 0 for success
- **/
+ */
 static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
 {
 	struct fcoe_percpu_s *fps;
@@ -326,13 +325,12 @@
 }
 
 /**
- * fcoe_fc_crc - calculates FC CRC in this fcoe skb
+ * fcoe_fc_crc() - calculates FC CRC in this fcoe skb
  * @fp: the fc_frame containg data to be checksummed
  *
  * This uses crc32() to calculate the crc for fc frame
  * Return   : 32 bit crc
- *
- **/
+ */
 u32 fcoe_fc_crc(struct fc_frame *fp)
 {
 	struct sk_buff *skb = fp_skb(fp);
@@ -363,13 +361,12 @@
 EXPORT_SYMBOL_GPL(fcoe_fc_crc);
 
 /**
- * fcoe_xmit - FCoE frame transmit function
+ * fcoe_xmit() - FCoE frame transmit function
  * @lp:	the associated local port
  * @fp: the fc_frame to be transmitted
  *
  * Return   : 0 for success
- *
- **/
+ */
 int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 {
 	int wlen, rc = 0;
@@ -389,7 +386,7 @@
 
 	WARN_ON((fr_len(fp) % sizeof(u32)) != 0);
 
-	fc = fcoe_softc(lp);
+	fc = lport_priv(lp);
 	/*
 	 * if it is a flogi then we need to learn gw-addr
 	 * and my own fcid
@@ -439,7 +436,7 @@
 	if (skb_is_nonlinear(skb)) {
 		skb_frag_t *frag;
 		if (fcoe_get_paged_crc_eof(skb, tlen)) {
-			kfree(skb);
+			kfree_skb(skb);
 			return -ENOMEM;
 		}
 		frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
@@ -502,21 +499,22 @@
 		rc = fcoe_start_io(skb);
 
 	if (rc) {
-		fcoe_insert_wait_queue(lp, skb);
+		spin_lock_bh(&fc->fcoe_pending_queue.lock);
+		__skb_queue_tail(&fc->fcoe_pending_queue, skb);
+		spin_unlock_bh(&fc->fcoe_pending_queue.lock);
 		if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
-			fc_pause(lp);
+			lp->qfull = 1;
 	}
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(fcoe_xmit);
 
-/*
- * fcoe_percpu_receive_thread - recv thread per cpu
+/**
+ * fcoe_percpu_receive_thread() - recv thread per cpu
  * @arg: ptr to the fcoe per cpu struct
  *
  * Return: 0 for success
- *
  */
 int fcoe_percpu_receive_thread(void *arg)
 {
@@ -533,7 +531,7 @@
 	struct fcoe_softc *fc;
 	struct fcoe_hdr *hp;
 
-	set_user_nice(current, 19);
+	set_user_nice(current, -20);
 
 	while (!kthread_should_stop()) {
 
@@ -658,7 +656,7 @@
 }
 
 /**
- * fcoe_recv_flogi - flogi receive function
+ * fcoe_recv_flogi() - flogi receive function
  * @fc: associated fcoe_softc
  * @fp: the recieved frame
  * @sa: the source address of this flogi
@@ -667,7 +665,7 @@
  * mac address for the initiator, eitehr OUI based or GW based.
  *
  * Returns: none
- **/
+ */
 static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa)
 {
 	struct fc_frame_header *fh;
@@ -715,32 +713,23 @@
 }
 
 /**
- * fcoe_watchdog - fcoe timer callback
+ * fcoe_watchdog() - fcoe timer callback
  * @vp:
  *
- * This checks the pending queue length for fcoe and put fcoe to be paused state
+ * This checks the pending queue length for fcoe and set lport qfull
  * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the
  * fcoe_hostlist.
  *
  * Returns: 0 for success
- **/
+ */
 void fcoe_watchdog(ulong vp)
 {
-	struct fc_lport *lp;
 	struct fcoe_softc *fc;
-	int paused = 0;
 
 	read_lock(&fcoe_hostlist_lock);
 	list_for_each_entry(fc, &fcoe_hostlist, list) {
-		lp = fc->lp;
-		if (lp) {
-			if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
-				paused = 1;
-			if (fcoe_check_wait_queue(lp) <	 FCOE_MAX_QUEUE_DEPTH) {
-				if (paused)
-					fc_unpause(lp);
-			}
-		}
+		if (fc->lp)
+			fcoe_check_wait_queue(fc->lp);
 	}
 	read_unlock(&fcoe_hostlist_lock);
 
@@ -750,96 +739,64 @@
 
 
 /**
- * fcoe_check_wait_queue - put the skb into fcoe pending xmit queue
+ * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue
  * @lp: the fc_port for this skb
  * @skb: the associated skb to be xmitted
  *
  * This empties the wait_queue, dequeue the head of the wait_queue queue
  * and calls fcoe_start_io() for each packet, if all skb have been
- * transmitted, return 0 if a error occurs, then restore wait_queue and
- * try again later.
+ * transmitted, return qlen or -1 if a error occurs, then restore
+ * wait_queue and  try again later.
  *
  * The wait_queue is used when the skb transmit fails. skb will go
  * in the wait_queue which will be emptied by the time function OR
  * by the next skb transmit.
  *
  * Returns: 0 for success
- **/
+ */
 static int fcoe_check_wait_queue(struct fc_lport *lp)
 {
-	int rc, unpause = 0;
-	int paused = 0;
+	struct fcoe_softc *fc = lport_priv(lp);
 	struct sk_buff *skb;
-	struct fcoe_softc *fc;
+	int rc = -1;
 
-	fc = fcoe_softc(lp);
 	spin_lock_bh(&fc->fcoe_pending_queue.lock);
+	if (fc->fcoe_pending_queue_active)
+		goto out;
+	fc->fcoe_pending_queue_active = 1;
 
-	/*
-	 * is this interface paused?
-	 */
-	if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
-		paused = 1;
-	if (fc->fcoe_pending_queue.qlen) {
-		while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) {
-			spin_unlock_bh(&fc->fcoe_pending_queue.lock);
-			rc = fcoe_start_io(skb);
-			if (rc) {
-				fcoe_insert_wait_queue_head(lp, skb);
-				return rc;
-			}
-			spin_lock_bh(&fc->fcoe_pending_queue.lock);
+	while (fc->fcoe_pending_queue.qlen) {
+		/* keep qlen > 0 until fcoe_start_io succeeds */
+		fc->fcoe_pending_queue.qlen++;
+		skb = __skb_dequeue(&fc->fcoe_pending_queue);
+
+		spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+		rc = fcoe_start_io(skb);
+		spin_lock_bh(&fc->fcoe_pending_queue.lock);
+
+		if (rc) {
+			__skb_queue_head(&fc->fcoe_pending_queue, skb);
+			/* undo temporary increment above */
+			fc->fcoe_pending_queue.qlen--;
+			break;
 		}
-		if (fc->fcoe_pending_queue.qlen < FCOE_MAX_QUEUE_DEPTH)
-			unpause = 1;
+		/* undo temporary increment above */
+		fc->fcoe_pending_queue.qlen--;
 	}
+
+	if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
+		lp->qfull = 0;
+	fc->fcoe_pending_queue_active = 0;
+	rc = fc->fcoe_pending_queue.qlen;
+out:
 	spin_unlock_bh(&fc->fcoe_pending_queue.lock);
-	if ((unpause) && (paused))
-		fc_unpause(lp);
-	return fc->fcoe_pending_queue.qlen;
+	return rc;
 }
 
 /**
- * fcoe_insert_wait_queue_head - puts skb to fcoe pending queue head
- * @lp: the fc_port for this skb
- * @skb: the associated skb to be xmitted
- *
- * Returns: none
- **/
-static void fcoe_insert_wait_queue_head(struct fc_lport *lp,
-					struct sk_buff *skb)
-{
-	struct fcoe_softc *fc;
-
-	fc = fcoe_softc(lp);
-	spin_lock_bh(&fc->fcoe_pending_queue.lock);
-	__skb_queue_head(&fc->fcoe_pending_queue, skb);
-	spin_unlock_bh(&fc->fcoe_pending_queue.lock);
-}
-
-/**
- * fcoe_insert_wait_queue - put the skb into fcoe pending queue tail
- * @lp: the fc_port for this skb
- * @skb: the associated skb to be xmitted
- *
- * Returns: none
- **/
-static void fcoe_insert_wait_queue(struct fc_lport *lp,
-				   struct sk_buff *skb)
-{
-	struct fcoe_softc *fc;
-
-	fc = fcoe_softc(lp);
-	spin_lock_bh(&fc->fcoe_pending_queue.lock);
-	__skb_queue_tail(&fc->fcoe_pending_queue, skb);
-	spin_unlock_bh(&fc->fcoe_pending_queue.lock);
-}
-
-/**
- * fcoe_dev_setup - setup link change notification interface
- *
- **/
-static void fcoe_dev_setup(void)
+ * fcoe_dev_setup() - setup link change notification interface
+ */
+static void fcoe_dev_setup()
 {
 	/*
 	 * here setup a interface specific wd time to
@@ -849,15 +806,15 @@
 }
 
 /**
- * fcoe_dev_setup - cleanup link change notification interface
- **/
+ * fcoe_dev_setup() - cleanup link change notification interface
+ */
 static void fcoe_dev_cleanup(void)
 {
 	unregister_netdevice_notifier(&fcoe_notifier);
 }
 
 /**
- * fcoe_device_notification - netdev event notification callback
+ * fcoe_device_notification() - netdev event notification callback
  * @notifier: context of the notification
  * @event: type of event
  * @ptr: fixed array for output parsed ifname
@@ -865,7 +822,7 @@
  * This function is called by the ethernet driver in case of link change event
  *
  * Returns: 0 for success
- **/
+ */
 static int fcoe_device_notification(struct notifier_block *notifier,
 				    ulong event, void *ptr)
 {
@@ -873,7 +830,7 @@
 	struct net_device *real_dev = ptr;
 	struct fcoe_softc *fc;
 	struct fcoe_dev_stats *stats;
-	u16 new_status;
+	u32 new_link_up;
 	u32 mfs;
 	int rc = NOTIFY_OK;
 
@@ -890,17 +847,15 @@
 		goto out;
 	}
 
-	new_status = lp->link_status;
+	new_link_up = lp->link_up;
 	switch (event) {
 	case NETDEV_DOWN:
 	case NETDEV_GOING_DOWN:
-		new_status &= ~FC_LINK_UP;
+		new_link_up = 0;
 		break;
 	case NETDEV_UP:
 	case NETDEV_CHANGE:
-		new_status &= ~FC_LINK_UP;
-		if (!fcoe_link_ok(lp))
-			new_status |= FC_LINK_UP;
+		new_link_up = !fcoe_link_ok(lp);
 		break;
 	case NETDEV_CHANGEMTU:
 		mfs = fc->real_dev->mtu -
@@ -908,17 +863,15 @@
 			 sizeof(struct fcoe_crc_eof));
 		if (mfs >= FC_MIN_MAX_FRAME)
 			fc_set_mfs(lp, mfs);
-		new_status &= ~FC_LINK_UP;
-		if (!fcoe_link_ok(lp))
-			new_status |= FC_LINK_UP;
+		new_link_up = !fcoe_link_ok(lp);
 		break;
 	case NETDEV_REGISTER:
 		break;
 	default:
 		FC_DBG("unknown event %ld call", event);
 	}
-	if (lp->link_status != new_status) {
-		if ((new_status & FC_LINK_UP) == FC_LINK_UP)
+	if (lp->link_up != new_link_up) {
+		if (new_link_up)
 			fc_linkup(lp);
 		else {
 			stats = lp->dev_stats[smp_processor_id()];
@@ -933,12 +886,12 @@
 }
 
 /**
- * fcoe_if_to_netdev - parse a name buffer to get netdev
+ * fcoe_if_to_netdev() - parse a name buffer to get netdev
  * @ifname: fixed array for output parsed ifname
  * @buffer: incoming buffer to be copied
  *
  * Returns: NULL or ptr to netdeive
- **/
+ */
 static struct net_device *fcoe_if_to_netdev(const char *buffer)
 {
 	char *cp;
@@ -955,13 +908,13 @@
 }
 
 /**
- * fcoe_netdev_to_module_owner - finds out the nic drive moddule of the netdev
+ * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev
  * @netdev: the target netdev
  *
  * Returns: ptr to the struct module, NULL for failure
- **/
-static struct module *fcoe_netdev_to_module_owner(
-	const struct net_device *netdev)
+ */
+static struct module *
+fcoe_netdev_to_module_owner(const struct net_device *netdev)
 {
 	struct device *dev;
 
@@ -979,12 +932,14 @@
 }
 
 /**
- * fcoe_ethdrv_get - holds the nic driver module by  try_module_get() for
- * the corresponding netdev.
+ * fcoe_ethdrv_get() - Hold the Ethernet driver
  * @netdev: the target netdev
  *
+ * Holds the Ethernet driver module by try_module_get() for
+ * the corresponding netdev.
+ *
  * Returns: 0 for succsss
- **/
+ */
 static int fcoe_ethdrv_get(const struct net_device *netdev)
 {
 	struct module *owner;
@@ -999,12 +954,14 @@
 }
 
 /**
- * fcoe_ethdrv_get - releases the nic driver module by module_put for
- * the corresponding netdev.
+ * fcoe_ethdrv_put() - Release the Ethernet driver
  * @netdev: the target netdev
  *
+ * Releases the Ethernet driver module by module_put for
+ * the corresponding netdev.
+ *
  * Returns: 0 for succsss
- **/
+ */
 static int fcoe_ethdrv_put(const struct net_device *netdev)
 {
 	struct module *owner;
@@ -1020,12 +977,12 @@
 }
 
 /**
- * fcoe_destroy- handles the destroy from sysfs
+ * fcoe_destroy() - handles the destroy from sysfs
  * @buffer: expcted to be a eth if name
  * @kp: associated kernel param
  *
  * Returns: 0 for success
- **/
+ */
 static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 {
 	int rc;
@@ -1058,12 +1015,12 @@
 }
 
 /**
- * fcoe_create - handles the create call from sysfs
+ * fcoe_create() - Handles the create call from sysfs
  * @buffer: expcted to be a eth if name
  * @kp: associated kernel param
  *
  * Returns: 0 for success
- **/
+ */
 static int fcoe_create(const char *buffer, struct kernel_param *kp)
 {
 	int rc;
@@ -1104,8 +1061,8 @@
 __MODULE_PARM_TYPE(destroy, "string");
 MODULE_PARM_DESC(destroy, "Destroy fcoe port");
 
-/*
- * fcoe_link_ok - check if link is ok for the fc_lport
+/**
+ * fcoe_link_ok() - Check if link is ok for the fc_lport
  * @lp: ptr to the fc_lport
  *
  * Any permanently-disqualifying conditions have been previously checked.
@@ -1120,7 +1077,7 @@
  */
 int fcoe_link_ok(struct fc_lport *lp)
 {
-	struct fcoe_softc *fc = fcoe_softc(lp);
+	struct fcoe_softc *fc = lport_priv(lp);
 	struct net_device *dev = fc->real_dev;
 	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
 	int rc = 0;
@@ -1149,9 +1106,8 @@
 }
 EXPORT_SYMBOL_GPL(fcoe_link_ok);
 
-/*
- * fcoe_percpu_clean - frees skb of the corresponding lport from the per
- * cpu queue.
+/**
+ * fcoe_percpu_clean() - Clear the pending skbs for an lport
  * @lp: the fc_lport
  */
 void fcoe_percpu_clean(struct fc_lport *lp)
@@ -1185,11 +1141,11 @@
 EXPORT_SYMBOL_GPL(fcoe_percpu_clean);
 
 /**
- * fcoe_clean_pending_queue - dequeue skb and free it
+ * fcoe_clean_pending_queue() - Dequeue a skb and free it
  * @lp: the corresponding fc_lport
  *
  * Returns: none
- **/
+ */
 void fcoe_clean_pending_queue(struct fc_lport *lp)
 {
 	struct fcoe_softc  *fc = lport_priv(lp);
@@ -1206,21 +1162,21 @@
 EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
 
 /**
- * libfc_host_alloc - allocate a Scsi_Host with room for the fc_lport
+ * libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport
  * @sht: ptr to the scsi host templ
  * @priv_size: size of private data after fc_lport
  *
  * Returns: ptr to Scsi_Host
- * TODO - to libfc?
+ * TODO: to libfc?
  */
-static inline struct Scsi_Host *libfc_host_alloc(
-	struct scsi_host_template *sht, int priv_size)
+static inline struct Scsi_Host *
+libfc_host_alloc(struct scsi_host_template *sht, int priv_size)
 {
 	return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size);
 }
 
 /**
- * fcoe_host_alloc - allocate a Scsi_Host with room for the fcoe_softc
+ * fcoe_host_alloc() - Allocate a Scsi_Host with room for the fcoe_softc
  * @sht: ptr to the scsi host templ
  * @priv_size: size of private data after fc_lport
  *
@@ -1232,8 +1188,8 @@
 }
 EXPORT_SYMBOL_GPL(fcoe_host_alloc);
 
-/*
- * fcoe_reset - resets the fcoe
+/**
+ * fcoe_reset() - Resets the fcoe
  * @shost: shost the reset is from
  *
  * Returns: always 0
@@ -1246,8 +1202,8 @@
 }
 EXPORT_SYMBOL_GPL(fcoe_reset);
 
-/*
- * fcoe_wwn_from_mac - converts 48-bit IEEE MAC address to 64-bit FC WWN.
+/**
+ * fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN.
  * @mac: mac address
  * @scheme: check port
  * @port: port indicator for converting
@@ -1286,14 +1242,15 @@
 	return wwn;
 }
 EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
-/*
- * fcoe_hostlist_lookup_softc - find the corresponding lport by a given device
+
+/**
+ * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device
  * @device: this is currently ptr to net_device
  *
  * Returns: NULL or the located fcoe_softc
  */
-static struct fcoe_softc *fcoe_hostlist_lookup_softc(
-	const struct net_device *dev)
+static struct fcoe_softc *
+fcoe_hostlist_lookup_softc(const struct net_device *dev)
 {
 	struct fcoe_softc *fc;
 
@@ -1308,8 +1265,8 @@
 	return NULL;
 }
 
-/*
- * fcoe_hostlist_lookup - find the corresponding lport by netdev
+/**
+ * fcoe_hostlist_lookup() - Find the corresponding lport by netdev
  * @netdev: ptr to net_device
  *
  * Returns: 0 for success
@@ -1324,8 +1281,8 @@
 }
 EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup);
 
-/*
- * fcoe_hostlist_add - add a lport to lports list
+/**
+ * fcoe_hostlist_add() - Add a lport to lports list
  * @lp: ptr to the fc_lport to badded
  *
  * Returns: 0 for success
@@ -1336,7 +1293,7 @@
 
 	fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
 	if (!fc) {
-		fc = fcoe_softc(lp);
+		fc = lport_priv(lp);
 		write_lock_bh(&fcoe_hostlist_lock);
 		list_add_tail(&fc->list, &fcoe_hostlist);
 		write_unlock_bh(&fcoe_hostlist_lock);
@@ -1345,8 +1302,8 @@
 }
 EXPORT_SYMBOL_GPL(fcoe_hostlist_add);
 
-/*
- * fcoe_hostlist_remove - remove a lport from lports list
+/**
+ * fcoe_hostlist_remove() - remove a lport from lports list
  * @lp: ptr to the fc_lport to badded
  *
  * Returns: 0 for success
@@ -1366,12 +1323,12 @@
 EXPORT_SYMBOL_GPL(fcoe_hostlist_remove);
 
 /**
- * fcoe_libfc_config - sets up libfc related properties for lport
+ * fcoe_libfc_config() - sets up libfc related properties for lport
  * @lp: ptr to the fc_lport
  * @tt: libfc function template
  *
  * Returns : 0 for success
- **/
+ */
 int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt)
 {
 	/* Set the function pointers set by the LLDD */
@@ -1389,14 +1346,14 @@
 EXPORT_SYMBOL_GPL(fcoe_libfc_config);
 
 /**
- * fcoe_init - fcoe module loading initialization
+ * fcoe_init() - fcoe module loading initialization
  *
  * Initialization routine
  * 1. Will create fc transport software structure
  * 2. initialize the link list of port information structure
  *
  * Returns 0 on success, negative on failure
- **/
+ */
 static int __init fcoe_init(void)
 {
 	int cpu;
@@ -1433,7 +1390,6 @@
 			} else {
 				fcoe_percpu[cpu] = NULL;
 				kfree(p);
-
 			}
 		}
 	}
@@ -1443,11 +1399,9 @@
 	 */
 	fcoe_dev_setup();
 
-	init_timer(&fcoe_timer);
-	fcoe_timer.data = 0;
-	fcoe_timer.function = fcoe_watchdog;
-	fcoe_timer.expires = (jiffies + (10 * HZ));
-	add_timer(&fcoe_timer);
+	setup_timer(&fcoe_timer, fcoe_watchdog, 0);
+
+	mod_timer(&fcoe_timer, jiffies + (10 * HZ));
 
 	/* initiatlize the fcoe transport */
 	fcoe_transport_init();
@@ -1459,10 +1413,10 @@
 module_init(fcoe_init);
 
 /**
- * fcoe_exit - fcoe module unloading cleanup
+ * fcoe_exit() - fcoe module unloading cleanup
  *
  * Returns 0 on success, negative on failure
- **/
+ */
 static void __exit fcoe_exit(void)
 {
 	u32 idx;
@@ -1483,7 +1437,7 @@
 	 */
 	del_timer_sync(&fcoe_timer);
 
-	/* releases the assocaited fcoe transport for each lport */
+	/* releases the associated fcoe transport for each lport */
 	list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
 		fcoe_transport_release(fc->real_dev);
 
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 4a4e695..f23c4ca 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -103,7 +103,7 @@
 
 	hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
 	if (!hostdata) {
-		dev_printk(KERN_ERR, dev, "Failed to allocate host data\n");
+		dev_printk(KERN_ERR, &dev->dev, "Failed to allocate host data\n");
 		return -ENOMEM;
 	}
 
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index dd1564c..e57556ea 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -64,7 +64,7 @@
 static void fc_disc_restart(struct fc_disc *);
 
 /**
- * fc_disc_lookup_rport - lookup a remote port by port_id
+ * fc_disc_lookup_rport() - lookup a remote port by port_id
  * @lport: Fibre Channel host port instance
  * @port_id: remote port port_id to match
  */
@@ -92,7 +92,7 @@
 }
 
 /**
- * fc_disc_stop_rports - delete all the remote ports associated with the lport
+ * fc_disc_stop_rports() - delete all the remote ports associated with the lport
  * @disc: The discovery job to stop rports on
  *
  * Locking Note: This function expects that the lport mutex is locked before
@@ -117,7 +117,7 @@
 }
 
 /**
- * fc_disc_rport_callback - Event handler for rport events
+ * fc_disc_rport_callback() - Event handler for rport events
  * @lport: The lport which is receiving the event
  * @rport: The rport which the event has occured on
  * @event: The event that occured
@@ -151,7 +151,7 @@
 }
 
 /**
- * fc_disc_recv_rscn_req - Handle Registered State Change Notification (RSCN)
+ * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
  * @sp: Current sequence of the RSCN exchange
  * @fp: RSCN Frame
  * @lport: Fibre Channel host port instance
@@ -246,7 +246,7 @@
 			list_del(&dp->peers);
 			rport = lport->tt.rport_lookup(lport, dp->ids.port_id);
 			if (rport) {
-				rdata = RPORT_TO_PRIV(rport);
+				rdata = rport->dd_data;
 				list_del(&rdata->peers);
 				lport->tt.rport_logoff(rport);
 			}
@@ -265,7 +265,7 @@
 }
 
 /**
- * fc_disc_recv_req - Handle incoming requests
+ * fc_disc_recv_req() - Handle incoming requests
  * @sp: Current sequence of the request exchange
  * @fp: The frame
  * @lport: The FC local port
@@ -294,7 +294,7 @@
 }
 
 /**
- * fc_disc_restart - Restart discovery
+ * fc_disc_restart() - Restart discovery
  * @lport: FC discovery context
  *
  * Locking Note: This function expects that the disc mutex
@@ -322,7 +322,7 @@
 }
 
 /**
- * fc_disc_start - Fibre Channel Target discovery
+ * fc_disc_start() - Fibre Channel Target discovery
  * @lport: FC local port
  *
  * Returns non-zero if discovery cannot be started.
@@ -383,7 +383,7 @@
 };
 
 /**
- * fc_disc_new_target - Handle new target found by discovery
+ * fc_disc_new_target() - Handle new target found by discovery
  * @lport: FC local port
  * @rport: The previous FC remote port (NULL if new remote port)
  * @ids: Identifiers for the new FC remote port
@@ -396,7 +396,7 @@
 			      struct fc_rport_identifiers *ids)
 {
 	struct fc_lport *lport = disc->lport;
-	struct fc_rport_libfc_priv *rp;
+	struct fc_rport_libfc_priv *rdata;
 	int error = 0;
 
 	if (rport && ids->port_name) {
@@ -430,15 +430,15 @@
 				dp.ids.port_name = ids->port_name;
 				dp.ids.node_name = ids->node_name;
 				dp.ids.roles = ids->roles;
-				rport = fc_rport_rogue_create(&dp);
+				rport = lport->tt.rport_create(&dp);
 			}
 			if (!rport)
 				error = -ENOMEM;
 		}
 		if (rport) {
-			rp = rport->dd_data;
-			rp->ops = &fc_disc_rport_ops;
-			rp->rp_state = RPORT_ST_INIT;
+			rdata = rport->dd_data;
+			rdata->ops = &fc_disc_rport_ops;
+			rdata->rp_state = RPORT_ST_INIT;
 			lport->tt.rport_login(rport);
 		}
 	}
@@ -446,20 +446,20 @@
 }
 
 /**
- * fc_disc_del_target - Delete a target
+ * fc_disc_del_target() - Delete a target
  * @disc: FC discovery context
  * @rport: The remote port to be removed
  */
 static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport)
 {
 	struct fc_lport *lport = disc->lport;
-	struct fc_rport_libfc_priv *rdata = RPORT_TO_PRIV(rport);
+	struct fc_rport_libfc_priv *rdata = rport->dd_data;
 	list_del(&rdata->peers);
 	lport->tt.rport_logoff(rport);
 }
 
 /**
- * fc_disc_done - Discovery has been completed
+ * fc_disc_done() - Discovery has been completed
  * @disc: FC discovery context
  */
 static void fc_disc_done(struct fc_disc *disc)
@@ -479,7 +479,7 @@
 }
 
 /**
- * fc_disc_error - Handle error on dNS request
+ * fc_disc_error() - Handle error on dNS request
  * @disc: FC discovery context
  * @fp: The frame pointer
  */
@@ -519,7 +519,7 @@
 }
 
 /**
- * fc_disc_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request
+ * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request
  * @lport: FC discovery context
  *
  * Locking Note: This function expects that the disc_mutex is locked
@@ -553,7 +553,7 @@
 }
 
 /**
- * fc_disc_gpn_ft_parse - Parse the list of IDs and names resulting from a request
+ * fc_disc_gpn_ft_parse() - Parse the list of IDs and names resulting from a request
  * @lport: Fibre Channel host port instance
  * @buf: GPN_FT response buffer
  * @len: size of response buffer
@@ -617,7 +617,7 @@
 
 		if ((dp.ids.port_id != fc_host_port_id(lport->host)) &&
 		    (dp.ids.port_name != lport->wwpn)) {
-			rport = fc_rport_rogue_create(&dp);
+			rport = lport->tt.rport_create(&dp);
 			if (rport) {
 				rdata = rport->dd_data;
 				rdata->ops = &fc_disc_rport_ops;
@@ -658,7 +658,10 @@
 	return error;
 }
 
-/*
+/**
+ * fc_disc_timeout() - Retry handler for the disc component
+ * @work: Structure holding disc obj that needs retry discovery
+ *
  * Handle retry of memory allocation for remote ports.
  */
 static void fc_disc_timeout(struct work_struct *work)
@@ -673,7 +676,7 @@
 }
 
 /**
- * fc_disc_gpn_ft_resp - Handle a response frame from Get Port Names (GPN_FT)
+ * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT)
  * @sp: Current sequence of GPN_FT exchange
  * @fp: response frame
  * @lp_arg: Fibre Channel host port instance
@@ -712,9 +715,7 @@
 			       fr_len(fp));
 		} else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
 
-			/*
-			 * Accepted.  Parse response.
-			 */
+			/* Accepted, parse the response. */
 			buf = cp + 1;
 			len -= sizeof(*cp);
 		} else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
@@ -746,7 +747,7 @@
 }
 
 /**
- * fc_disc_single - Discover the directory information for a single target
+ * fc_disc_single() - Discover the directory information for a single target
  * @lport: FC local port
  * @dp: The port to rediscover
  *
@@ -769,7 +770,7 @@
 	if (rport)
 		fc_disc_del_target(disc, rport);
 
-	new_rport = fc_rport_rogue_create(dp);
+	new_rport = lport->tt.rport_create(dp);
 	if (new_rport) {
 		rdata = new_rport->dd_data;
 		rdata->ops = &fc_disc_rport_ops;
@@ -782,7 +783,7 @@
 }
 
 /**
- * fc_disc_stop - Stop discovery for a given lport
+ * fc_disc_stop() - Stop discovery for a given lport
  * @lport: The lport that discovery should stop for
  */
 void fc_disc_stop(struct fc_lport *lport)
@@ -796,7 +797,7 @@
 }
 
 /**
- * fc_disc_stop_final - Stop discovery for a given lport
+ * fc_disc_stop_final() - Stop discovery for a given lport
  * @lport: The lport that discovery should stop for
  *
  * This function will block until discovery has been
@@ -809,7 +810,7 @@
 }
 
 /**
- * fc_disc_init - Initialize the discovery block
+ * fc_disc_init() - Initialize the discovery block
  * @lport: FC local port
  */
 int fc_disc_init(struct fc_lport *lport)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 66db08a..505825b 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -32,8 +32,6 @@
 #include <scsi/libfc.h>
 #include <scsi/fc_encode.h>
 
-#define	  FC_DEF_R_A_TOV      (10 * 1000) /* resource allocation timeout */
-
 /*
  * fc_exch_debug can be set in debugger or at compile time to get more logs.
  */
@@ -627,7 +625,6 @@
 {
 	struct fc_exch *ep;
 	struct fc_frame_header *fh;
-	u16 rxid;
 
 	ep = mp->lp->tt.exch_get(mp->lp, fp);
 	if (ep) {
@@ -654,18 +651,6 @@
 		if ((ntoh24(fh->fh_f_ctl) & FC_FC_SEQ_INIT) == 0)
 			ep->esb_stat &= ~ESB_ST_SEQ_INIT;
 
-		/*
-		 * Set the responder ID in the frame header.
-		 * The old one should've been 0xffff.
-		 * If it isn't, don't assign one.
-		 * Incoming basic link service frames may specify
-		 * a referenced RX_ID.
-		 */
-		if (fh->fh_type != FC_TYPE_BLS) {
-			rxid = ntohs(fh->fh_rx_id);
-			WARN_ON(rxid != FC_XID_UNKNOWN);
-			fh->fh_rx_id = htons(ep->rxid);
-		}
 		fc_exch_hold(ep);	/* hold for caller */
 		spin_unlock_bh(&ep->ex_lock);	/* lock from exch_get */
 	}
@@ -677,8 +662,8 @@
  * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold
  * on the ep that should be released by the caller.
  */
-static enum fc_pf_rjt_reason
-fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp)
+static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp,
+						 struct fc_frame *fp)
 {
 	struct fc_frame_header *fh = fc_frame_header_get(fp);
 	struct fc_exch *ep = NULL;
@@ -996,9 +981,9 @@
  * Send BLS Reject.
  * This is for rejecting BA_ABTS only.
  */
-static void
-fc_exch_send_ba_rjt(struct fc_frame *rx_fp, enum fc_ba_rjt_reason reason,
-		    enum fc_ba_rjt_explan explan)
+static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
+				enum fc_ba_rjt_reason reason,
+				enum fc_ba_rjt_explan explan)
 {
 	struct fc_frame *fp;
 	struct fc_frame_header *rx_fh;
@@ -1096,7 +1081,7 @@
 		ap->ba_high_seq_cnt = fh->fh_seq_cnt;
 		ap->ba_low_seq_cnt = htons(sp->cnt);
 	}
-	sp = fc_seq_start_next(sp);
+	sp = fc_seq_start_next_locked(sp);
 	spin_unlock_bh(&ep->ex_lock);
 	fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS);
 	fc_frame_free(rx_fp);
@@ -1480,10 +1465,11 @@
  * If sid is non-zero, reset only exchanges we source from that FID.
  * If did is non-zero, reset only exchanges destined to that FID.
  */
-void fc_exch_mgr_reset(struct fc_exch_mgr *mp, u32 sid, u32 did)
+void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
 {
 	struct fc_exch *ep;
 	struct fc_exch *next;
+	struct fc_exch_mgr *mp = lp->emp;
 
 	spin_lock_bh(&mp->em_lock);
 restart:
@@ -1607,7 +1593,7 @@
 	if (IS_ERR(fp)) {
 		int err = PTR_ERR(fp);
 
-		if (err == -FC_EX_CLOSED)
+		if (err == -FC_EX_CLOSED || err == -FC_EX_TIMEOUT)
 			goto cleanup;
 		FC_DBG("Cannot process RRQ, because of frame error %d\n", err);
 		return;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 404e63f..2a631d7 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -161,7 +161,7 @@
 }
 
 /**
- * fc_fcp_pkt_release - release hold on scsi_pkt packet
+ * fc_fcp_pkt_release() - release hold on scsi_pkt packet
  * @fsp:	fcp packet struct
  *
  * This is used by upper layer scsi driver.
@@ -183,8 +183,7 @@
 }
 
 /**
- * fc_fcp_pkt_destory - release hold on scsi_pkt packet
- *
+ * fc_fcp_pkt_destory() - release hold on scsi_pkt packet
  * @seq:		exchange sequence
  * @fsp:	fcp packet struct
  *
@@ -199,7 +198,7 @@
 }
 
 /**
- * fc_fcp_lock_pkt - lock a packet and get a ref to it.
+ * fc_fcp_lock_pkt() - lock a packet and get a ref to it.
  * @fsp:	fcp packet
  *
  * We should only return error if we return a command to scsi-ml before
@@ -291,9 +290,7 @@
 	buf = fc_frame_payload_get(fp, 0);
 
 	if (offset + len > fsp->data_len) {
-		/*
-		 * this should never happen
-		 */
+		/* this should never happen */
 		if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) &&
 		    fc_frame_crc_check(fp))
 			goto crc_err;
@@ -387,8 +384,8 @@
 		fc_fcp_complete_locked(fsp);
 }
 
-/*
- * fc_fcp_send_data -  Send SCSI data to target.
+/**
+ * fc_fcp_send_data() -  Send SCSI data to target.
  * @fsp: ptr to fc_fcp_pkt
  * @sp: ptr to this sequence
  * @offset: starting offset for this data request
@@ -610,8 +607,8 @@
 	}
 }
 
-/*
- * fc_fcp_reduce_can_queue - drop can_queue
+/**
+ * fc_fcp_reduce_can_queue() - drop can_queue
  * @lp: lport to drop queueing for
  *
  * If we are getting memory allocation failures, then we may
@@ -642,9 +639,11 @@
 	spin_unlock_irqrestore(lp->host->host_lock, flags);
 }
 
-/*
- * exch mgr calls this routine to process scsi
- * exchanges.
+/**
+ * fc_fcp_recv() - Reveive FCP frames
+ * @seq: The sequence the frame is on
+ * @fp: The FC frame
+ * @arg: The related FCP packet
  *
  * Return   : None
  * Context  : called from Soft IRQ context
@@ -832,7 +831,7 @@
 }
 
 /**
- * fc_fcp_complete_locked - complete processing of a fcp packet
+ * fc_fcp_complete_locked() - complete processing of a fcp packet
  * @fsp:	fcp packet
  *
  * This function may sleep if a timer is pending. The packet lock must be
@@ -900,7 +899,7 @@
 }
 
 /**
- * fc_fcp_cleanup_each_cmd - run fn on each active command
+ * fc_fcp_cleanup_each_cmd() - Cleanup active commads
  * @lp:		logical port
  * @id:		target id
  * @lun:	lun
@@ -952,7 +951,7 @@
 }
 
 /**
- * fc_fcp_pkt_send - send a fcp packet to the lower level.
+ * fc_fcp_pkt_send() - send a fcp packet to the lower level.
  * @lp:		fc lport
  * @fsp:	fc packet.
  *
@@ -1621,7 +1620,7 @@
 static inline int fc_fcp_lport_queue_ready(struct fc_lport *lp)
 {
 	/* lock ? */
-	return (lp->state == LPORT_ST_READY) && (lp->link_status & FC_LINK_UP);
+	return (lp->state == LPORT_ST_READY) && lp->link_up && !lp->qfull;
 }
 
 /**
@@ -1727,7 +1726,7 @@
 EXPORT_SYMBOL(fc_queuecommand);
 
 /**
- * fc_io_compl -  Handle responses for completed commands
+ * fc_io_compl() -  Handle responses for completed commands
  * @fsp:	scsi packet
  *
  * Translates a error to a Linux SCSI error.
@@ -1810,12 +1809,12 @@
 		sc_cmd->result = DID_ERROR << 16;
 		break;
 	case FC_DATA_UNDRUN:
-		if (fsp->cdb_status == 0) {
+		if ((fsp->cdb_status == 0) && !(fsp->req_flags & FC_SRB_READ)) {
 			/*
 			 * scsi status is good but transport level
-			 * underrun. for read it should be an error??
+			 * underrun.
 			 */
-			sc_cmd->result = (DID_OK << 16) | fsp->cdb_status;
+			sc_cmd->result = DID_OK << 16;
 		} else {
 			/*
 			 * scsi got underrun, this is an error
@@ -1857,7 +1856,7 @@
 }
 
 /**
- * fc_fcp_complete - complete processing of a fcp packet
+ * fc_fcp_complete() - complete processing of a fcp packet
  * @fsp:	fcp packet
  *
  * This function may sleep if a fsp timer is pending.
@@ -1874,9 +1873,10 @@
 EXPORT_SYMBOL(fc_fcp_complete);
 
 /**
- * fc_eh_abort - Abort a command...from scsi host template
+ * fc_eh_abort() - Abort a command
  * @sc_cmd:	scsi command to abort
  *
+ * From scsi host template.
  * send ABTS to the target device  and wait for the response
  * sc_cmd is the pointer to the command to be aborted.
  */
@@ -1890,7 +1890,7 @@
 	lp = shost_priv(sc_cmd->device->host);
 	if (lp->state != LPORT_ST_READY)
 		return rc;
-	else if (!(lp->link_status & FC_LINK_UP))
+	else if (!lp->link_up)
 		return rc;
 
 	spin_lock_irqsave(lp->host->host_lock, flags);
@@ -1920,7 +1920,7 @@
 EXPORT_SYMBOL(fc_eh_abort);
 
 /**
- * fc_eh_device_reset: Reset a single LUN
+ * fc_eh_device_reset() Reset a single LUN
  * @sc_cmd:	scsi command
  *
  * Set from scsi host template to send tm cmd to the target and wait for the
@@ -1973,7 +1973,7 @@
 EXPORT_SYMBOL(fc_eh_device_reset);
 
 /**
- * fc_eh_host_reset - The reset function will reset the ports on the host.
+ * fc_eh_host_reset() - The reset function will reset the ports on the host.
  * @sc_cmd:	scsi command
  */
 int fc_eh_host_reset(struct scsi_cmnd *sc_cmd)
@@ -1999,7 +1999,7 @@
 EXPORT_SYMBOL(fc_eh_host_reset);
 
 /**
- * fc_slave_alloc - configure queue depth
+ * fc_slave_alloc() - configure queue depth
  * @sdev:	scsi device
  *
  * Configures queue depth based on host's cmd_per_len. If not set
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 0b9bdb1..2ae50a1 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -139,7 +139,7 @@
 }
 
 /**
- * fc_lport_rport_callback - Event handler for rport events
+ * fc_lport_rport_callback() - Event handler for rport events
  * @lport: The lport which is receiving the event
  * @rport: The rport which the event has occured on
  * @event: The event that occured
@@ -195,7 +195,7 @@
 }
 
 /**
- * fc_lport_state - Return a string which represents the lport's state
+ * fc_lport_state() - Return a string which represents the lport's state
  * @lport: The lport whose state is to converted to a string
  */
 static const char *fc_lport_state(struct fc_lport *lport)
@@ -209,7 +209,7 @@
 }
 
 /**
- * fc_lport_ptp_setup - Create an rport for point-to-point mode
+ * fc_lport_ptp_setup() - Create an rport for point-to-point mode
  * @lport: The lport to attach the ptp rport to
  * @fid: The FID of the ptp rport
  * @remote_wwpn: The WWPN of the ptp rport
@@ -232,7 +232,7 @@
 		lport->ptp_rp = NULL;
 	}
 
-	lport->ptp_rp = fc_rport_rogue_create(&dp);
+	lport->ptp_rp = lport->tt.rport_create(&dp);
 
 	lport->tt.rport_login(lport->ptp_rp);
 
@@ -250,7 +250,7 @@
 {
 	struct fc_lport *lp = shost_priv(shost);
 
-	if ((lp->link_status & FC_LINK_UP) == FC_LINK_UP)
+	if (lp->link_up)
 		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
 	else
 		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
@@ -351,7 +351,7 @@
 }
 
 /**
- * fc_lport_recv_rlir_req - Handle received Registered Link Incident Report.
+ * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report.
  * @lport: Fibre Channel local port recieving the RLIR
  * @sp: current sequence in the RLIR exchange
  * @fp: RLIR request frame
@@ -370,7 +370,7 @@
 }
 
 /**
- * fc_lport_recv_echo_req - Handle received ECHO request
+ * fc_lport_recv_echo_req() - Handle received ECHO request
  * @lport: Fibre Channel local port recieving the ECHO
  * @sp: current sequence in the ECHO exchange
  * @fp: ECHO request frame
@@ -412,7 +412,7 @@
 }
 
 /**
- * fc_lport_recv_echo_req - Handle received Request Node ID data request
+ * fc_lport_recv_echo_req() - Handle received Request Node ID data request
  * @lport: Fibre Channel local port recieving the RNID
  * @sp: current sequence in the RNID exchange
  * @fp: RNID request frame
@@ -479,7 +479,7 @@
 }
 
 /**
- * fc_lport_recv_adisc_req - Handle received Address Discovery Request
+ * fc_lport_recv_adisc_req() - Handle received Address Discovery Request
  * @lport: Fibre Channel local port recieving the ADISC
  * @sp: current sequence in the ADISC exchange
  * @fp: ADISC request frame
@@ -529,7 +529,7 @@
 }
 
 /**
- * fc_lport_recv_logo_req - Handle received fabric LOGO request
+ * fc_lport_recv_logo_req() - Handle received fabric LOGO request
  * @lport: Fibre Channel local port recieving the LOGO
  * @sp: current sequence in the LOGO exchange
  * @fp: LOGO request frame
@@ -546,7 +546,7 @@
 }
 
 /**
- * fc_fabric_login - Start the lport state machine
+ * fc_fabric_login() - Start the lport state machine
  * @lport: The lport that should log into the fabric
  *
  * Locking Note: This function should not be called
@@ -568,7 +568,7 @@
 EXPORT_SYMBOL(fc_fabric_login);
 
 /**
- * fc_linkup - Handler for transport linkup events
+ * fc_linkup() - Handler for transport linkup events
  * @lport: The lport whose link is up
  */
 void fc_linkup(struct fc_lport *lport)
@@ -577,8 +577,8 @@
 		       fc_host_port_id(lport->host));
 
 	mutex_lock(&lport->lp_mutex);
-	if ((lport->link_status & FC_LINK_UP) != FC_LINK_UP) {
-		lport->link_status |= FC_LINK_UP;
+	if (!lport->link_up) {
+		lport->link_up = 1;
 
 		if (lport->state == LPORT_ST_RESET)
 			fc_lport_enter_flogi(lport);
@@ -588,7 +588,7 @@
 EXPORT_SYMBOL(fc_linkup);
 
 /**
- * fc_linkdown - Handler for transport linkdown events
+ * fc_linkdown() - Handler for transport linkdown events
  * @lport: The lport whose link is down
  */
 void fc_linkdown(struct fc_lport *lport)
@@ -597,8 +597,8 @@
 	FC_DEBUG_LPORT("Link is down for port (%6x)\n",
 		       fc_host_port_id(lport->host));
 
-	if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) {
-		lport->link_status &= ~(FC_LINK_UP);
+	if (lport->link_up) {
+		lport->link_up = 0;
 		fc_lport_enter_reset(lport);
 		lport->tt.fcp_cleanup(lport);
 	}
@@ -607,48 +607,25 @@
 EXPORT_SYMBOL(fc_linkdown);
 
 /**
- * fc_pause - Pause the flow of frames
- * @lport: The lport to be paused
- */
-void fc_pause(struct fc_lport *lport)
-{
-	mutex_lock(&lport->lp_mutex);
-	lport->link_status |= FC_PAUSE;
-	mutex_unlock(&lport->lp_mutex);
-}
-EXPORT_SYMBOL(fc_pause);
-
-/**
- * fc_unpause - Unpause the flow of frames
- * @lport: The lport to be unpaused
- */
-void fc_unpause(struct fc_lport *lport)
-{
-	mutex_lock(&lport->lp_mutex);
-	lport->link_status &= ~(FC_PAUSE);
-	mutex_unlock(&lport->lp_mutex);
-}
-EXPORT_SYMBOL(fc_unpause);
-
-/**
- * fc_fabric_logoff - Logout of the fabric
+ * fc_fabric_logoff() - Logout of the fabric
  * @lport:	      fc_lport pointer to logoff the fabric
  *
  * Return value:
  *	0 for success, -1 for failure
- **/
+ */
 int fc_fabric_logoff(struct fc_lport *lport)
 {
 	lport->tt.disc_stop_final(lport);
 	mutex_lock(&lport->lp_mutex);
 	fc_lport_enter_logo(lport);
 	mutex_unlock(&lport->lp_mutex);
+	cancel_delayed_work_sync(&lport->retry_work);
 	return 0;
 }
 EXPORT_SYMBOL(fc_fabric_logoff);
 
 /**
- * fc_lport_destroy - unregister a fc_lport
+ * fc_lport_destroy() - unregister a fc_lport
  * @lport:	      fc_lport pointer to unregister
  *
  * Return value:
@@ -658,26 +635,25 @@
  * clean-up all the allocated memory
  * and free up other system resources.
  *
- **/
+ */
 int fc_lport_destroy(struct fc_lport *lport)
 {
 	lport->tt.frame_send = fc_frame_drop;
 	lport->tt.fcp_abort_io(lport);
-	lport->tt.exch_mgr_reset(lport->emp, 0, 0);
+	lport->tt.exch_mgr_reset(lport, 0, 0);
 	return 0;
 }
 EXPORT_SYMBOL(fc_lport_destroy);
 
 /**
- * fc_set_mfs - sets up the mfs for the corresponding fc_lport
+ * fc_set_mfs() - sets up the mfs for the corresponding fc_lport
  * @lport: fc_lport pointer to unregister
  * @mfs: the new mfs for fc_lport
  *
  * Set mfs for the given fc_lport to the new mfs.
  *
  * Return: 0 for success
- *
- **/
+ */
 int fc_set_mfs(struct fc_lport *lport, u32 mfs)
 {
 	unsigned int old_mfs;
@@ -706,7 +682,7 @@
 EXPORT_SYMBOL(fc_set_mfs);
 
 /**
- * fc_lport_disc_callback - Callback for discovery events
+ * fc_lport_disc_callback() - Callback for discovery events
  * @lport: FC local port
  * @event: The discovery event
  */
@@ -731,7 +707,7 @@
 }
 
 /**
- * fc_rport_enter_ready - Enter the ready state and start discovery
+ * fc_rport_enter_ready() - Enter the ready state and start discovery
  * @lport: Fibre Channel local port that is ready
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -748,7 +724,7 @@
 }
 
 /**
- * fc_lport_recv_flogi_req - Receive a FLOGI request
+ * fc_lport_recv_flogi_req() - Receive a FLOGI request
  * @sp_in: The sequence the FLOGI is on
  * @rx_fp: The frame the FLOGI is in
  * @lport: The lport that recieved the request
@@ -838,7 +814,7 @@
 }
 
 /**
- * fc_lport_recv_req - The generic lport request handler
+ * fc_lport_recv_req() - The generic lport request handler
  * @lport: The lport that received the request
  * @sp: The sequence the request is on
  * @fp: The frame the request is in
@@ -934,7 +910,7 @@
 }
 
 /**
- * fc_lport_reset - Reset an lport
+ * fc_lport_reset() - Reset an lport
  * @lport: The lport which should be reset
  *
  * Locking Note: This functions should not be called with the
@@ -942,6 +918,7 @@
  */
 int fc_lport_reset(struct fc_lport *lport)
 {
+	cancel_delayed_work_sync(&lport->retry_work);
 	mutex_lock(&lport->lp_mutex);
 	fc_lport_enter_reset(lport);
 	mutex_unlock(&lport->lp_mutex);
@@ -950,7 +927,7 @@
 EXPORT_SYMBOL(fc_lport_reset);
 
 /**
- * fc_rport_enter_reset - Reset the local port
+ * fc_rport_enter_reset() - Reset the local port
  * @lport: Fibre Channel local port to be reset
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -973,16 +950,16 @@
 
 	lport->tt.disc_stop(lport);
 
-	lport->tt.exch_mgr_reset(lport->emp, 0, 0);
+	lport->tt.exch_mgr_reset(lport, 0, 0);
 	fc_host_fabric_name(lport->host) = 0;
 	fc_host_port_id(lport->host) = 0;
 
-	if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP)
+	if (lport->link_up)
 		fc_lport_enter_flogi(lport);
 }
 
 /**
- * fc_lport_error - Handler for any errors
+ * fc_lport_error() - Handler for any errors
  * @lport: The fc_lport object
  * @fp: The frame pointer
  *
@@ -1029,8 +1006,8 @@
 }
 
 /**
- * fc_lport_rft_id_resp - Handle response to Register Fibre
- *			  Channel Types by ID (RPN_ID) request
+ * fc_lport_rft_id_resp() - Handle response to Register Fibre
+ *			    Channel Types by ID (RPN_ID) request
  * @sp: current sequence in RPN_ID exchange
  * @fp: response frame
  * @lp_arg: Fibre Channel host port instance
@@ -1053,17 +1030,17 @@
 
 	FC_DEBUG_LPORT("Received a RFT_ID response\n");
 
+	if (IS_ERR(fp)) {
+		fc_lport_error(lport, fp);
+		goto err;
+	}
+
 	if (lport->state != LPORT_ST_RFT_ID) {
 		FC_DBG("Received a RFT_ID response, but in state %s\n",
 		       fc_lport_state(lport));
 		goto out;
 	}
 
-	if (IS_ERR(fp)) {
-		fc_lport_error(lport, fp);
-		goto err;
-	}
-
 	fh = fc_frame_header_get(fp);
 	ct = fc_frame_payload_get(fp, sizeof(*ct));
 
@@ -1081,8 +1058,8 @@
 }
 
 /**
- * fc_lport_rpn_id_resp - Handle response to Register Port
- *			  Name by ID (RPN_ID) request
+ * fc_lport_rpn_id_resp() - Handle response to Register Port
+ *			    Name by ID (RPN_ID) request
  * @sp: current sequence in RPN_ID exchange
  * @fp: response frame
  * @lp_arg: Fibre Channel host port instance
@@ -1105,17 +1082,17 @@
 
 	FC_DEBUG_LPORT("Received a RPN_ID response\n");
 
+	if (IS_ERR(fp)) {
+		fc_lport_error(lport, fp);
+		goto err;
+	}
+
 	if (lport->state != LPORT_ST_RPN_ID) {
 		FC_DBG("Received a RPN_ID response, but in state %s\n",
 		       fc_lport_state(lport));
 		goto out;
 	}
 
-	if (IS_ERR(fp)) {
-		fc_lport_error(lport, fp);
-		goto err;
-	}
-
 	fh = fc_frame_header_get(fp);
 	ct = fc_frame_payload_get(fp, sizeof(*ct));
 	if (fh && ct && fh->fh_type == FC_TYPE_CT &&
@@ -1133,7 +1110,7 @@
 }
 
 /**
- * fc_lport_scr_resp - Handle response to State Change Register (SCR) request
+ * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request
  * @sp: current sequence in SCR exchange
  * @fp: response frame
  * @lp_arg: Fibre Channel lport port instance that sent the registration request
@@ -1155,17 +1132,17 @@
 
 	FC_DEBUG_LPORT("Received a SCR response\n");
 
+	if (IS_ERR(fp)) {
+		fc_lport_error(lport, fp);
+		goto err;
+	}
+
 	if (lport->state != LPORT_ST_SCR) {
 		FC_DBG("Received a SCR response, but in state %s\n",
 		       fc_lport_state(lport));
 		goto out;
 	}
 
-	if (IS_ERR(fp)) {
-		fc_lport_error(lport, fp);
-		goto err;
-	}
-
 	op = fc_frame_payload_op(fp);
 	if (op == ELS_LS_ACC)
 		fc_lport_enter_ready(lport);
@@ -1179,7 +1156,7 @@
 }
 
 /**
- * fc_lport_enter_scr - Send a State Change Register (SCR) request
+ * fc_lport_enter_scr() - Send a State Change Register (SCR) request
  * @lport: Fibre Channel local port to register for state changes
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -1206,7 +1183,7 @@
 }
 
 /**
- * fc_lport_enter_rft_id - Register FC4-types with the name server
+ * fc_lport_enter_rft_id() - Register FC4-types with the name server
  * @lport: Fibre Channel local port to register
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -1248,7 +1225,7 @@
 }
 
 /**
- * fc_rport_enter_rft_id - Register port name with the name server
+ * fc_rport_enter_rft_id() - Register port name with the name server
  * @lport: Fibre Channel local port to register
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -1281,7 +1258,7 @@
 };
 
 /**
- * fc_rport_enter_dns - Create a rport to the name server
+ * fc_rport_enter_dns() - Create a rport to the name server
  * @lport: Fibre Channel local port requesting a rport for the name server
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -1304,7 +1281,7 @@
 
 	fc_lport_state_enter(lport, LPORT_ST_DNS);
 
-	rport = fc_rport_rogue_create(&dp);
+	rport = lport->tt.rport_create(&dp);
 	if (!rport)
 		goto err;
 
@@ -1318,7 +1295,7 @@
 }
 
 /**
- * fc_lport_timeout - Handler for the retry_work timer.
+ * fc_lport_timeout() - Handler for the retry_work timer.
  * @work: The work struct of the fc_lport
  */
 static void fc_lport_timeout(struct work_struct *work)
@@ -1359,7 +1336,7 @@
 }
 
 /**
- * fc_lport_logo_resp - Handle response to LOGO request
+ * fc_lport_logo_resp() - Handle response to LOGO request
  * @sp: current sequence in LOGO exchange
  * @fp: response frame
  * @lp_arg: Fibre Channel lport port instance that sent the LOGO request
@@ -1381,17 +1358,17 @@
 
 	FC_DEBUG_LPORT("Received a LOGO response\n");
 
+	if (IS_ERR(fp)) {
+		fc_lport_error(lport, fp);
+		goto err;
+	}
+
 	if (lport->state != LPORT_ST_LOGO) {
 		FC_DBG("Received a LOGO response, but in state %s\n",
 		       fc_lport_state(lport));
 		goto out;
 	}
 
-	if (IS_ERR(fp)) {
-		fc_lport_error(lport, fp);
-		goto err;
-	}
-
 	op = fc_frame_payload_op(fp);
 	if (op == ELS_LS_ACC)
 		fc_lport_enter_reset(lport);
@@ -1405,7 +1382,7 @@
 }
 
 /**
- * fc_rport_enter_logo - Logout of the fabric
+ * fc_rport_enter_logo() - Logout of the fabric
  * @lport: Fibre Channel local port to be logged out
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -1437,7 +1414,7 @@
 }
 
 /**
- * fc_lport_flogi_resp - Handle response to FLOGI request
+ * fc_lport_flogi_resp() - Handle response to FLOGI request
  * @sp: current sequence in FLOGI exchange
  * @fp: response frame
  * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request
@@ -1465,17 +1442,17 @@
 
 	FC_DEBUG_LPORT("Received a FLOGI response\n");
 
+	if (IS_ERR(fp)) {
+		fc_lport_error(lport, fp);
+		goto err;
+	}
+
 	if (lport->state != LPORT_ST_FLOGI) {
 		FC_DBG("Received a FLOGI response, but in state %s\n",
 		       fc_lport_state(lport));
 		goto out;
 	}
 
-	if (IS_ERR(fp)) {
-		fc_lport_error(lport, fp);
-		goto err;
-	}
-
 	fh = fc_frame_header_get(fp);
 	did = ntoh24(fh->fh_d_id);
 	if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
@@ -1532,7 +1509,7 @@
 }
 
 /**
- * fc_rport_enter_flogi - Send a FLOGI request to the fabric manager
+ * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager
  * @lport: Fibre Channel local port to be logged in to the fabric
  *
  * Locking Note: The lport lock is expected to be held before calling
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index e780d8c..dae6513 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -81,6 +81,7 @@
 				   struct fc_seq *, struct fc_frame *);
 static void fc_rport_timeout(struct work_struct *);
 static void fc_rport_error(struct fc_rport *, struct fc_frame *);
+static void fc_rport_error_retry(struct fc_rport *, struct fc_frame *);
 static void fc_rport_work(struct work_struct *);
 
 static const char *fc_rport_state_names[] = {
@@ -145,7 +146,7 @@
 }
 
 /**
- * fc_rport_state - return a string for the state the rport is in
+ * fc_rport_state() - return a string for the state the rport is in
  * @rport: The rport whose state we want to get a string for
  */
 static const char *fc_rport_state(struct fc_rport *rport)
@@ -160,7 +161,7 @@
 }
 
 /**
- * fc_set_rport_loss_tmo - Set the remote port loss timeout in seconds.
+ * fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds.
  * @rport: Pointer to Fibre Channel remote port structure
  * @timeout: timeout in seconds
  */
@@ -174,12 +175,12 @@
 EXPORT_SYMBOL(fc_set_rport_loss_tmo);
 
 /**
- * fc_plogi_get_maxframe - Get max payload from the common service parameters
+ * fc_plogi_get_maxframe() - Get max payload from the common service parameters
  * @flp: FLOGI payload structure
  * @maxval: upper limit, may be less than what is in the service parameters
  */
-static unsigned int
-fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval)
+static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp,
+					  unsigned int maxval)
 {
 	unsigned int mfs;
 
@@ -197,7 +198,7 @@
 }
 
 /**
- * fc_rport_state_enter - Change the rport's state
+ * fc_rport_state_enter() - Change the rport's state
  * @rport: The rport whose state should change
  * @new: The new state of the rport
  *
@@ -214,6 +215,7 @@
 
 static void fc_rport_work(struct work_struct *work)
 {
+	u32 port_id;
 	struct fc_rport_libfc_priv *rdata =
 		container_of(work, struct fc_rport_libfc_priv, event_work);
 	enum fc_rport_event event;
@@ -279,14 +281,18 @@
 			rport_ops->event_callback(lport, rport, event);
 		if (trans_state == FC_PORTSTATE_ROGUE)
 			put_device(&rport->dev);
-		else
+		else {
+			port_id = rport->port_id;
 			fc_remote_port_delete(rport);
+			lport->tt.exch_mgr_reset(lport, 0, port_id);
+			lport->tt.exch_mgr_reset(lport, port_id, 0);
+		}
 	} else
 		mutex_unlock(&rdata->rp_mutex);
 }
 
 /**
- * fc_rport_login - Start the remote port login state machine
+ * fc_rport_login() - Start the remote port login state machine
  * @rport: Fibre Channel remote port
  *
  * Locking Note: Called without the rport lock held. This
@@ -309,7 +315,7 @@
 }
 
 /**
- * fc_rport_logoff - Logoff and remove an rport
+ * fc_rport_logoff() - Logoff and remove an rport
  * @rport: Fibre Channel remote port to be removed
  *
  * Locking Note: Called without the rport lock held. This
@@ -347,7 +353,7 @@
 }
 
 /**
- * fc_rport_enter_ready - The rport is ready
+ * fc_rport_enter_ready() - The rport is ready
  * @rport: Fibre Channel remote port that is ready
  *
  * Locking Note: The rport lock is expected to be held before calling
@@ -366,7 +372,7 @@
 }
 
 /**
- * fc_rport_timeout - Handler for the retry_work timer.
+ * fc_rport_timeout() - Handler for the retry_work timer.
  * @work: The work struct of the fc_rport_libfc_priv
  *
  * Locking Note: Called without the rport lock held. This
@@ -405,59 +411,75 @@
 }
 
 /**
- * fc_rport_error - Handler for any errors
+ * fc_rport_error() - Error handler, called once retries have been exhausted
  * @rport: The fc_rport object
  * @fp: The frame pointer
  *
- * If the error was caused by a resource allocation failure
- * then wait for half a second and retry, otherwise retry
- * immediately.
- *
  * Locking Note: The rport lock is expected to be held before
  * calling this routine
  */
 static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
 {
 	struct fc_rport_libfc_priv *rdata = rport->dd_data;
-	unsigned long delay = 0;
 
 	FC_DEBUG_RPORT("Error %ld in state %s, retries %d\n",
 		       PTR_ERR(fp), fc_rport_state(rport), rdata->retries);
 
-	if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
-		/*
-		 * Memory allocation failure, or the exchange timed out.
-		 *  Retry after delay
-		 */
-		if (rdata->retries < rdata->local_port->max_retry_count) {
-			rdata->retries++;
-			if (!fp)
-				delay = msecs_to_jiffies(500);
-			get_device(&rport->dev);
-			schedule_delayed_work(&rdata->retry_work, delay);
-		} else {
-			switch (rdata->rp_state) {
-			case RPORT_ST_PLOGI:
-			case RPORT_ST_PRLI:
-			case RPORT_ST_LOGO:
-				rdata->event = RPORT_EV_FAILED;
-				queue_work(rport_event_queue,
-					   &rdata->event_work);
-				break;
-			case RPORT_ST_RTV:
-				fc_rport_enter_ready(rport);
-				break;
-			case RPORT_ST_NONE:
-			case RPORT_ST_READY:
-			case RPORT_ST_INIT:
-				break;
-			}
-		}
+	switch (rdata->rp_state) {
+	case RPORT_ST_PLOGI:
+	case RPORT_ST_PRLI:
+	case RPORT_ST_LOGO:
+		rdata->event = RPORT_EV_FAILED;
+		queue_work(rport_event_queue,
+			   &rdata->event_work);
+		break;
+	case RPORT_ST_RTV:
+		fc_rport_enter_ready(rport);
+		break;
+	case RPORT_ST_NONE:
+	case RPORT_ST_READY:
+	case RPORT_ST_INIT:
+		break;
 	}
 }
 
 /**
- * fc_rport_plogi_recv_resp - Handle incoming ELS PLOGI response
+ * fc_rport_error_retry() - Error handler when retries are desired
+ * @rport: The fc_rport object
+ * @fp: The frame pointer
+ *
+ * If the error was an exchange timeout retry immediately,
+ * otherwise wait for E_D_TOV.
+ *
+ * Locking Note: The rport lock is expected to be held before
+ * calling this routine
+ */
+static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp)
+{
+	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	unsigned long delay = FC_DEF_E_D_TOV;
+
+	/* make sure this isn't an FC_EX_CLOSED error, never retry those */
+	if (PTR_ERR(fp) == -FC_EX_CLOSED)
+		return fc_rport_error(rport, fp);
+
+	if (rdata->retries < rdata->local_port->max_retry_count) {
+		FC_DEBUG_RPORT("Error %ld in state %s, retrying\n",
+			       PTR_ERR(fp), fc_rport_state(rport));
+		rdata->retries++;
+		/* no additional delay on exchange timeouts */
+		if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
+			delay = 0;
+		get_device(&rport->dev);
+		schedule_delayed_work(&rdata->retry_work, delay);
+		return;
+	}
+
+	return fc_rport_error(rport, fp);
+}
+
+/**
+ * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response
  * @sp: current sequence in the PLOGI exchange
  * @fp: response frame
  * @rp_arg: Fibre Channel remote port
@@ -483,17 +505,17 @@
 	FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n",
 		       rport->port_id);
 
+	if (IS_ERR(fp)) {
+		fc_rport_error_retry(rport, fp);
+		goto err;
+	}
+
 	if (rdata->rp_state != RPORT_ST_PLOGI) {
 		FC_DBG("Received a PLOGI response, but in state %s\n",
 		       fc_rport_state(rport));
 		goto out;
 	}
 
-	if (IS_ERR(fp)) {
-		fc_rport_error(rport, fp);
-		goto err;
-	}
-
 	op = fc_frame_payload_op(fp);
 	if (op == ELS_LS_ACC &&
 	    (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
@@ -522,7 +544,7 @@
 		else
 			fc_rport_enter_prli(rport);
 	} else
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 
 out:
 	fc_frame_free(fp);
@@ -532,7 +554,7 @@
 }
 
 /**
- * fc_rport_enter_plogi - Send Port Login (PLOGI) request to peer
+ * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer
  * @rport: Fibre Channel remote port to send PLOGI to
  *
  * Locking Note: The rport lock is expected to be held before calling
@@ -552,20 +574,20 @@
 	rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
 	if (!fp) {
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 		return;
 	}
 	rdata->e_d_tov = lport->e_d_tov;
 
 	if (!lport->tt.elsct_send(lport, rport, fp, ELS_PLOGI,
 				  fc_rport_plogi_resp, rport, lport->e_d_tov))
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 	else
 		get_device(&rport->dev);
 }
 
 /**
- * fc_rport_prli_resp - Process Login (PRLI) response handler
+ * fc_rport_prli_resp() - Process Login (PRLI) response handler
  * @sp: current sequence in the PRLI exchange
  * @fp: response frame
  * @rp_arg: Fibre Channel remote port
@@ -592,17 +614,17 @@
 	FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n",
 		       rport->port_id);
 
+	if (IS_ERR(fp)) {
+		fc_rport_error_retry(rport, fp);
+		goto err;
+	}
+
 	if (rdata->rp_state != RPORT_ST_PRLI) {
 		FC_DBG("Received a PRLI response, but in state %s\n",
 		       fc_rport_state(rport));
 		goto out;
 	}
 
-	if (IS_ERR(fp)) {
-		fc_rport_error(rport, fp);
-		goto err;
-	}
-
 	op = fc_frame_payload_op(fp);
 	if (op == ELS_LS_ACC) {
 		pp = fc_frame_payload_get(fp, sizeof(*pp));
@@ -635,7 +657,7 @@
 }
 
 /**
- * fc_rport_logo_resp - Logout (LOGO) response handler
+ * fc_rport_logo_resp() - Logout (LOGO) response handler
  * @sp: current sequence in the LOGO exchange
  * @fp: response frame
  * @rp_arg: Fibre Channel remote port
@@ -657,7 +679,7 @@
 		       rport->port_id);
 
 	if (IS_ERR(fp)) {
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 		goto err;
 	}
 
@@ -684,7 +706,7 @@
 }
 
 /**
- * fc_rport_enter_prli - Send Process Login (PRLI) request to peer
+ * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer
  * @rport: Fibre Channel remote port to send PRLI to
  *
  * Locking Note: The rport lock is expected to be held before calling
@@ -707,19 +729,19 @@
 
 	fp = fc_frame_alloc(lport, sizeof(*pp));
 	if (!fp) {
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 		return;
 	}
 
 	if (!lport->tt.elsct_send(lport, rport, fp, ELS_PRLI,
 				  fc_rport_prli_resp, rport, lport->e_d_tov))
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 	else
 		get_device(&rport->dev);
 }
 
 /**
- * fc_rport_els_rtv_resp - Request Timeout Value response handler
+ * fc_rport_els_rtv_resp() - Request Timeout Value response handler
  * @sp: current sequence in the RTV exchange
  * @fp: response frame
  * @rp_arg: Fibre Channel remote port
@@ -742,17 +764,17 @@
 	FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n",
 		       rport->port_id);
 
+	if (IS_ERR(fp)) {
+		fc_rport_error(rport, fp);
+		goto err;
+	}
+
 	if (rdata->rp_state != RPORT_ST_RTV) {
 		FC_DBG("Received a RTV response, but in state %s\n",
 		       fc_rport_state(rport));
 		goto out;
 	}
 
-	if (IS_ERR(fp)) {
-		fc_rport_error(rport, fp);
-		goto err;
-	}
-
 	op = fc_frame_payload_op(fp);
 	if (op == ELS_LS_ACC) {
 		struct fc_els_rtv_acc *rtv;
@@ -785,7 +807,7 @@
 }
 
 /**
- * fc_rport_enter_rtv - Send Request Timeout Value (RTV) request to peer
+ * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer
  * @rport: Fibre Channel remote port to send RTV to
  *
  * Locking Note: The rport lock is expected to be held before calling
@@ -804,19 +826,19 @@
 
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv));
 	if (!fp) {
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 		return;
 	}
 
 	if (!lport->tt.elsct_send(lport, rport, fp, ELS_RTV,
 				     fc_rport_rtv_resp, rport, lport->e_d_tov))
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 	else
 		get_device(&rport->dev);
 }
 
 /**
- * fc_rport_enter_logo - Send Logout (LOGO) request to peer
+ * fc_rport_enter_logo() - Send Logout (LOGO) request to peer
  * @rport: Fibre Channel remote port to send LOGO to
  *
  * Locking Note: The rport lock is expected to be held before calling
@@ -835,20 +857,20 @@
 
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo));
 	if (!fp) {
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 		return;
 	}
 
 	if (!lport->tt.elsct_send(lport, rport, fp, ELS_LOGO,
 				  fc_rport_logo_resp, rport, lport->e_d_tov))
-		fc_rport_error(rport, fp);
+		fc_rport_error_retry(rport, fp);
 	else
 		get_device(&rport->dev);
 }
 
 
 /**
- * fc_rport_recv_req - Receive a request from a rport
+ * fc_rport_recv_req() - Receive a request from a rport
  * @sp: current sequence in the PLOGI exchange
  * @fp: response frame
  * @rp_arg: Fibre Channel remote port
@@ -909,7 +931,7 @@
 }
 
 /**
- * fc_rport_recv_plogi_req - Handle incoming Port Login (PLOGI) request
+ * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request
  * @rport: Fibre Channel remote port that initiated PLOGI
  * @sp: current sequence in the PLOGI exchange
  * @fp: PLOGI request frame
@@ -1031,7 +1053,7 @@
 }
 
 /**
- * fc_rport_recv_prli_req - Handle incoming Process Login (PRLI) request
+ * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request
  * @rport: Fibre Channel remote port that initiated PRLI
  * @sp: current sequence in the PRLI exchange
  * @fp: PRLI request frame
@@ -1182,7 +1204,7 @@
 }
 
 /**
- * fc_rport_recv_prlo_req - Handle incoming Process Logout (PRLO) request
+ * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request
  * @rport: Fibre Channel remote port that initiated PRLO
  * @sp: current sequence in the PRLO exchange
  * @fp: PRLO request frame
@@ -1213,7 +1235,7 @@
 }
 
 /**
- * fc_rport_recv_logo_req - Handle incoming Logout (LOGO) request
+ * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request
  * @rport: Fibre Channel remote port that initiated LOGO
  * @sp: current sequence in the LOGO exchange
  * @fp: LOGO request frame
@@ -1249,6 +1271,9 @@
 
 int fc_rport_init(struct fc_lport *lport)
 {
+	if (!lport->tt.rport_create)
+		lport->tt.rport_create = fc_rport_rogue_create;
+
 	if (!lport->tt.rport_login)
 		lport->tt.rport_login = fc_rport_login;
 
@@ -1285,7 +1310,7 @@
 	struct fc_rport_libfc_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 
-	lport->tt.exch_mgr_reset(lport->emp, 0, rport->port_id);
-	lport->tt.exch_mgr_reset(lport->emp, rport->port_id, 0);
+	lport->tt.exch_mgr_reset(lport, 0, rport->port_id);
+	lport->tt.exch_mgr_reset(lport, rport->port_id, 0);
 }
 EXPORT_SYMBOL(fc_rport_terminate_io);
diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c
index b264b49..b5fbfd6 100644
--- a/drivers/scsi/mvme16x_scsi.c
+++ b/drivers/scsi/mvme16x_scsi.c
@@ -34,7 +34,7 @@
 static struct platform_device *mvme16x_scsi_device;
 
 static __devinit int
-mvme16x_probe(struct device *dev)
+mvme16x_probe(struct platform_device *dev)
 {
 	struct Scsi_Host * host = NULL;
 	struct NCR_700_Host_Parameters *hostdata;
@@ -64,7 +64,8 @@
 	hostdata->ctest7_extra = CTEST7_TT1;
 
 	/* and register the chip */
-	host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, dev);
+	host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata,
+			      &dev->dev);
 	if (!host) {
 		printk(KERN_ERR "mvme16x-scsi: No host detected; "
 				"board configuration problem?\n");
@@ -88,7 +89,7 @@
 		out_be32(0xfff4202c, v);
 	}
 
-	dev_set_drvdata(dev, host);
+	platform_set_drvdata(dev, host);
 	scsi_scan_host(host);
 
 	return 0;
@@ -102,9 +103,9 @@
 }
 
 static __devexit int
-mvme16x_device_remove(struct device *dev)
+mvme16x_device_remove(struct platform_device *dev)
 {
-	struct Scsi_Host *host = dev_get_drvdata(dev);
+	struct Scsi_Host *host = platform_get_drvdata(dev);
 	struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
 
 	/* Disable scsi chip ints */
@@ -123,25 +124,27 @@
 	return 0;
 }
 
-static struct device_driver mvme16x_scsi_driver = {
-	.name	= "mvme16x-scsi",
-	.bus	= &platform_bus_type,
-	.probe	= mvme16x_probe,
-	.remove	= __devexit_p(mvme16x_device_remove),
+static struct platform_driver mvme16x_scsi_driver = {
+	.driver = {
+		.name           = "mvme16x-scsi",
+		.owner          = THIS_MODULE,
+	},
+	.probe          = mvme16x_probe,
+	.remove         = __devexit_p(mvme16x_device_remove),
 };
 
 static int __init mvme16x_scsi_init(void)
 {
 	int err;
 
-	err = driver_register(&mvme16x_scsi_driver);
+	err = platform_driver_register(&mvme16x_scsi_driver);
 	if (err)
 		return err;
 
 	mvme16x_scsi_device = platform_device_register_simple("mvme16x-scsi",
 							      -1, NULL, 0);
 	if (IS_ERR(mvme16x_scsi_device)) {
-		driver_unregister(&mvme16x_scsi_driver);
+		platform_driver_unregister(&mvme16x_scsi_driver);
 		return PTR_ERR(mvme16x_scsi_device);
 	}
 
@@ -151,7 +154,7 @@
 static void __exit mvme16x_scsi_exit(void)
 {
 	platform_device_unregister(mvme16x_scsi_device);
-	driver_unregister(&mvme16x_scsi_driver);
+	platform_driver_unregister(&mvme16x_scsi_driver);
 }
 
 module_init(mvme16x_scsi_init);
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index f4c5722..ee9d401 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -244,12 +244,6 @@
 		if (ha->optrom_state != QLA_SWAITING)
 			break;
 
-		if (start & 0xfff) {
-			qla_printk(KERN_WARNING, ha,
-			    "Invalid start region 0x%x/0x%x.\n", start, size);
-			return -EINVAL;
-		}
-
 		ha->optrom_region_start = start;
 		ha->optrom_region_size = start + size > ha->optrom_size ?
 		    ha->optrom_size - start : size;
@@ -303,8 +297,7 @@
 		else if (start == (ha->flt_region_boot * 4) ||
 		    start == (ha->flt_region_fw * 4))
 			valid = 1;
-		else if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) &&
-		    start == (ha->flt_region_vpd_nvram * 4))
+		else if (IS_QLA25XX(ha) || IS_QLA81XX(ha))
 		    valid = 1;
 		if (!valid) {
 			qla_printk(KERN_WARNING, ha,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 9865017..87f9abc 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1308,8 +1308,12 @@
 
 	DEBUG(printk("scsi(%ld): Issue init firmware.\n", vha->host_no));
 
-	if (ha->flags.npiv_supported)
+	if (ha->flags.npiv_supported) {
+		if (ha->operating_mode == LOOP)
+			ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1;
 		mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports);
+	}
+
 
 	mid_init_cb->options = __constant_cpu_to_le16(BIT_1);
 
@@ -2610,6 +2614,7 @@
 	port_id_t	wrap, nxt_d_id;
 	struct qla_hw_data *ha = vha->hw;
 	struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
+	struct scsi_qla_host *tvp;
 
 	rval = QLA_SUCCESS;
 
@@ -2709,7 +2714,7 @@
 		/* Bypass virtual ports of the same host. */
 		found = 0;
 		if (ha->num_vhosts) {
-			list_for_each_entry(vp, &ha->vp_list, list) {
+			list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
 				if (new_fcport->d_id.b24 == vp->d_id.b24) {
 					found = 1;
 					break;
@@ -2832,6 +2837,7 @@
 	uint16_t first_loop_id;
 	struct qla_hw_data *ha = vha->hw;
 	struct scsi_qla_host *vp;
+	struct scsi_qla_host *tvp;
 
 	rval = QLA_SUCCESS;
 
@@ -2856,7 +2862,7 @@
 		/* Check for loop ID being already in use. */
 		found = 0;
 		fcport = NULL;
-		list_for_each_entry(vp, &ha->vp_list, list) {
+		list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
 			list_for_each_entry(fcport, &vp->vp_fcports, list) {
 				if (fcport->loop_id == dev->loop_id &&
 								fcport != dev) {
@@ -3291,6 +3297,7 @@
 	uint8_t        status = 0;
 	struct qla_hw_data *ha = vha->hw;
 	struct scsi_qla_host *vp;
+	struct scsi_qla_host *tvp;
 	struct req_que *req = ha->req_q_map[0];
 
 	if (vha->flags.online) {
@@ -3306,7 +3313,7 @@
 		if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
 			atomic_set(&vha->loop_state, LOOP_DOWN);
 			qla2x00_mark_all_devices_lost(vha, 0);
-			list_for_each_entry(vp, &ha->vp_list, list)
+			list_for_each_entry_safe(vp, tvp, &ha->vp_list, list)
 			       qla2x00_mark_all_devices_lost(vp, 0);
 		} else {
 			if (!atomic_read(&vha->loop_down_timer))
@@ -3403,7 +3410,7 @@
 		DEBUG(printk(KERN_INFO
 				"qla2x00_abort_isp(%ld): succeeded.\n",
 				vha->host_no));
-		list_for_each_entry(vp, &ha->vp_list, list) {
+		list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
 			if (vp->vp_idx)
 				qla2x00_vp_abort_isp(vp);
 		}
@@ -3428,7 +3435,7 @@
 static int
 qla2x00_restart_isp(scsi_qla_host_t *vha)
 {
-	uint8_t		status = 0;
+	int status = 0;
 	uint32_t wait_time;
 	struct qla_hw_data *ha = vha->hw;
 	struct req_que *req = ha->req_q_map[0];
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 4c7504c..4aab7ac 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2685,6 +2685,7 @@
 	uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
 	struct qla_hw_data *ha = vha->hw;
 	scsi_qla_host_t *vp;
+	scsi_qla_host_t *tvp;
 
 	if (rptid_entry->entry_status != 0)
 		return;
@@ -2710,7 +2711,7 @@
 		if (MSB(stat) == 1)
 			return;
 
-		list_for_each_entry(vp, &ha->vp_list, list)
+		list_for_each_entry_safe(vp, tvp, &ha->vp_list, list)
 			if (vp_idx == vp->vp_idx)
 				break;
 		if (!vp)
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 3f23932..785c612 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -69,9 +69,10 @@
 qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name)
 {
 	scsi_qla_host_t *vha;
+	struct scsi_qla_host *tvha;
 
 	/* Locate matching device in database. */
-	list_for_each_entry(vha, &ha->vp_list, list) {
+	list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) {
 		if (!memcmp(port_name, vha->port_name, WWN_SIZE))
 			return vha;
 	}
@@ -194,11 +195,11 @@
 void
 qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
 {
-	scsi_qla_host_t *vha;
+	scsi_qla_host_t *vha, *tvha;
 	struct qla_hw_data *ha = rsp->hw;
 	int i = 0;
 
-	list_for_each_entry(vha, &ha->vp_list, list) {
+	list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) {
 		if (vha->vp_idx) {
 			switch (mb[0]) {
 			case MBA_LIP_OCCURRED:
@@ -300,6 +301,7 @@
 	int ret;
 	struct qla_hw_data *ha = vha->hw;
 	scsi_qla_host_t *vp;
+	struct scsi_qla_host *tvp;
 
 	if (vha->vp_idx)
 		return;
@@ -308,7 +310,7 @@
 
 	clear_bit(VP_DPC_NEEDED, &vha->dpc_flags);
 
-	list_for_each_entry(vp, &ha->vp_list, list) {
+	list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
 		if (vp->vp_idx)
 			ret = qla2x00_do_dpc_vp(vp);
 	}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2f5f725..3ddfa88 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2222,10 +2222,6 @@
 {
 	char	name[16];
 
-	ha->init_cb_size = sizeof(init_cb_t);
-	if (IS_QLA2XXX_MIDTYPE(ha))
-		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
-
 	ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
 		&ha->init_cb_dma, GFP_KERNEL);
 	if (!ha->init_cb)
@@ -2568,7 +2564,7 @@
 void qla2x00_relogin(struct scsi_qla_host *vha)
 {
 	fc_port_t       *fcport;
-	uint8_t         status;
+	int status;
 	uint16_t        next_loopid = 0;
 	struct qla_hw_data *ha = vha->hw;
 
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 79f7053..a772eab2 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.00-k3"
+#define QLA2XXX_VERSION      "8.03.00-k4"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	3
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 55310db..4970ae4 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1167,23 +1167,19 @@
 		/*
 		 * The device does not want the automatic start to be issued.
 		 */
-		if (sdkp->device->no_start_on_add) {
+		if (sdkp->device->no_start_on_add)
 			break;
-		}
 
-		/*
-		 * If manual intervention is required, or this is an
-		 * absent USB storage device, a spinup is meaningless.
-		 */
-		if (sense_valid &&
-		    sshdr.sense_key == NOT_READY &&
-		    sshdr.asc == 4 && sshdr.ascq == 3) {
-			break;		/* manual intervention required */
-
-		/*
-		 * Issue command to spin up drive when not ready
-		 */
-		} else if (sense_valid && sshdr.sense_key == NOT_READY) {
+		if (sense_valid && sshdr.sense_key == NOT_READY) {
+			if (sshdr.asc == 4 && sshdr.ascq == 3)
+				break;	/* manual intervention required */
+			if (sshdr.asc == 4 && sshdr.ascq == 0xb)
+				break;	/* standby */
+			if (sshdr.asc == 4 && sshdr.ascq == 0xc)
+				break;	/* unavailable */
+			/*
+			 * Issue command to spin up drive when not ready
+			 */
 			if (!spintime) {
 				sd_printk(KERN_NOTICE, sdkp, "Spinning up disk...");
 				cmd[0] = START_STOP;
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index a8d61a6..97f3158 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -137,7 +137,7 @@
 		goto fail;
 
 	if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) {
-	  dev_printk(KERN_ERR, dev, "irq problem with %d, detaching\n ",
+	  dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ",
 		     dev->irq);
 		goto fail;
 	}
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 557b54a..dbf5357 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -139,7 +139,7 @@
 	} while (!(status & SCxSR_TDxE(port)));
 
 	sci_in(port, SCxSR);            /* Dummy read */
-	sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+	sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
 	sci_out(port, SCxTDR, c);
 }
 #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
@@ -263,6 +263,7 @@
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
       defined(CONFIG_CPU_SUBTYPE_SH7780) || \
       defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7786) || \
       defined(CONFIG_CPU_SUBTYPE_SHX3)
 static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
 {
@@ -284,7 +285,8 @@
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
     defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785)
+    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7786)
 static inline int scif_txroom(struct uart_port *port)
 {
 	return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff);
@@ -1095,6 +1097,7 @@
 				 unsigned count)
 {
 	struct uart_port *port = &serial_console_port->port;
+	unsigned short bits;
 	int i;
 
 	for (i = 0; i < count; i++) {
@@ -1103,6 +1106,11 @@
 
 		sci_poll_put_char(port, *s++);
 	}
+
+	/* wait until fifo is empty and last bit has been transmitted */
+	bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
+	while ((sci_in(port, SCxSR) & bits) != bits)
+		cpu_relax();
 }
 
 static int __init serial_console_setup(struct console *co, char *options)
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 022e89f..d0aa82d 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -1,6 +1,6 @@
 #include <linux/serial_core.h>
 #include <asm/io.h>
-#include <asm/gpio.h>
+#include <linux/gpio.h>
 
 #if defined(CONFIG_H83007) || defined(CONFIG_H83068)
 #include <asm/regs306x.h>
@@ -126,7 +126,8 @@
 # define SCSPTR1	0xffe10024	/* 16 bit SCIF */
 # define SCIF_ORER	0x0001		/* Overrun error bit */
 # define SCSCR_INIT(port)	0x3a	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7785)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7786)
 # define SCSPTR0	0xffea0024	/* 16 bit SCIF */
 # define SCSPTR1	0xffeb0024	/* 16 bit SCIF */
 # define SCSPTR2	0xffec0024	/* 16 bit SCIF */
@@ -182,6 +183,7 @@
     defined(CONFIG_CPU_SUBTYPE_SH7763)  || \
     defined(CONFIG_CPU_SUBTYPE_SH7780)  || \
     defined(CONFIG_CPU_SUBTYPE_SH7785)  || \
+    defined(CONFIG_CPU_SUBTYPE_SH7786)  || \
     defined(CONFIG_CPU_SUBTYPE_SHX3)
 #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
 #else
@@ -413,7 +415,8 @@
 SCIF_FNS(SCFCR,                      0x0c,  8, 0x18, 16)
 #if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
     defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785)
+    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7786)
 SCIF_FNS(SCFDR,			     0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCTFDR,		     0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCRFDR,		     0x0e, 16, 0x20, 16)
@@ -644,7 +647,8 @@
 		return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
 	return 1;
 }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7785)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7786)
 static inline int sci_rxd_in(struct uart_port *port)
 {
 	if (port->mapbase == 0xffea0000)
@@ -746,7 +750,8 @@
  */
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785)
+    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7786)
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 45a299f..e09d3ce 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1438,12 +1438,12 @@
 	} else {
 		printk(KERN_INFO "%s: Keyboard at MMIO 0x%llx (irq = %d) "
 		       "is a %s\n",
-		       op->dev.bus_id,
+		       dev_name(&op->dev),
 		       (unsigned long long) up[0].port.mapbase,
 		       op->irqs[0], sunzilog_type(&up[0].port));
 		printk(KERN_INFO "%s: Mouse at MMIO 0x%llx (irq = %d) "
 		       "is a %s\n",
-		       op->dev.bus_id,
+		       dev_name(&op->dev),
 		       (unsigned long long) up[1].port.mapbase,
 		       op->irqs[0], sunzilog_type(&up[1].port));
 		kbm_inst++;
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 58d24c5..2269fbc 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -568,6 +568,10 @@
 	if (!data[0] && data[1])
 		primary = 1;
 
+	if (!data[0] && !data[1])
+		pr_warning("intc: missing unique irq mask for "
+			   "irq %d (vect 0x%04x)\n", irq, irq2evt(irq));
+
 	data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
 	data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);
 
@@ -641,6 +645,17 @@
 	return 0;
 }
 
+static unsigned char *intc_evt2irq_table;
+
+unsigned int intc_evt2irq(unsigned int vector)
+{
+	unsigned int irq = evt2irq(vector);
+
+	if (intc_evt2irq_table && intc_evt2irq_table[irq])
+		irq = intc_evt2irq_table[irq];
+
+	return irq;
+}
 
 void __init register_intc_controller(struct intc_desc *desc)
 {
@@ -705,8 +720,40 @@
 
 	BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
 
+	/* keep the first vector only if same enum is used multiple times */
 	for (i = 0; i < desc->nr_vectors; i++) {
 		struct intc_vect *vect = desc->vectors + i;
+		int first_irq = evt2irq(vect->vect);
+
+		if (!vect->enum_id)
+			continue;
+
+		for (k = i + 1; k < desc->nr_vectors; k++) {
+			struct intc_vect *vect2 = desc->vectors + k;
+
+			if (vect->enum_id != vect2->enum_id)
+				continue;
+
+			vect2->enum_id = 0;
+
+			if (!intc_evt2irq_table)
+				intc_evt2irq_table = alloc_bootmem(NR_IRQS);
+
+			if (!intc_evt2irq_table) {
+				pr_warning("intc: cannot allocate evt2irq!\n");
+				continue;
+			}
+
+			intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq;
+		}
+	}
+
+	/* register the vectors one by one */
+	for (i = 0; i < desc->nr_vectors; i++) {
+		struct intc_vect *vect = desc->vectors + i;
+
+		if (!vect->enum_id)
+			continue;
 
 		intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect));
 	}
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index 63f0de2..cab1ab7 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -1,16 +1,10 @@
 /*
  * Core maple bus functionality
  *
- *  Copyright (C) 2007, 2008 Adrian McMenamin
+ *  Copyright (C) 2007 - 2009 Adrian McMenamin
  *  Copyright (C) 2001 - 2008 Paul Mundt
- *
- * Based on 2.4 code by:
- *
- *  Copyright (C) 2000-2001 YAEGASHI Takeshi
+ *  Copyright (C) 2000 - 2001 YAEGASHI Takeshi
  *  Copyright (C) 2001 M. R. Brown
- *  Copyright (C) 2001 Paul Mundt
- *
- * and others.
  *
  * 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
@@ -32,7 +26,7 @@
 #include <mach/dma.h>
 #include <mach/sysasic.h>
 
-MODULE_AUTHOR("Yaegashi Takeshi, Paul Mundt, M. R. Brown, Adrian McMenamin");
+MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>");
 MODULE_DESCRIPTION("Maple bus driver for Dreamcast");
 MODULE_LICENSE("GPL v2");
 MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}");
@@ -49,7 +43,7 @@
 /* mutex to protect queue of waiting packets */
 static DEFINE_MUTEX(maple_wlist_lock);
 
-static struct maple_driver maple_dummy_driver;
+static struct maple_driver maple_unsupported_device;
 static struct device maple_bus;
 static int subdevice_map[MAPLE_PORTS];
 static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr;
@@ -62,8 +56,9 @@
 	int unit;
 };
 
-static bool checked[4];
-static struct maple_device *baseunits[4];
+static bool checked[MAPLE_PORTS];
+static bool empty[MAPLE_PORTS];
+static struct maple_device *baseunits[MAPLE_PORTS];
 
 /**
  * maple_driver_register - register a maple driver
@@ -97,12 +92,20 @@
 EXPORT_SYMBOL_GPL(maple_driver_unregister);
 
 /* set hardware registers to enable next round of dma */
-static void maplebus_dma_reset(void)
+static void maple_dma_reset(void)
 {
 	ctrl_outl(MAPLE_MAGIC, MAPLE_RESET);
 	/* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */
 	ctrl_outl(1, MAPLE_TRIGTYPE);
-	ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(50000), MAPLE_SPEED);
+	/*
+	* Maple system register
+	* bits 31 - 16	timeout in units of 20nsec
+	* bit 12	hard trigger - set 0 to keep responding to VBLANK
+	* bits 9 - 8	set 00 for 2 Mbps, 01 for 1 Mbps
+	* bits 3 - 0	delay (in 1.3ms) between VBLANK and start of DMA
+	* max delay is 11
+	*/
+	ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(0xFFFF), MAPLE_SPEED);
 	ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR);
 	ctrl_outl(1, MAPLE_ENABLE);
 }
@@ -134,21 +137,16 @@
 {
 	struct maple_device *mdev;
 	struct mapleq *mq;
-	if (!dev)
-		return;
+
 	mdev = to_maple_dev(dev);
 	mq = mdev->mq;
-	if (mq) {
-		if (mq->recvbufdcsp)
-			kmem_cache_free(maple_queue_cache, mq->recvbufdcsp);
-		kfree(mq);
-		mq = NULL;
-	}
+	kmem_cache_free(maple_queue_cache, mq->recvbuf);
+	kfree(mq);
 	kfree(mdev);
 }
 
 /**
- * maple_add_packet - add a single instruction to the queue
+ * maple_add_packet - add a single instruction to the maple bus queue
  * @mdev: maple device
  * @function: function on device being queried
  * @command: maple command to add
@@ -158,23 +156,12 @@
 int maple_add_packet(struct maple_device *mdev, u32 function, u32 command,
 	size_t length, void *data)
 {
-	int locking, ret = 0;
+	int ret = 0;
 	void *sendbuf = NULL;
 
-	mutex_lock(&maple_wlist_lock);
-	/* bounce if device already locked */
-	locking = mutex_is_locked(&mdev->mq->mutex);
-	if (locking) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	mutex_lock(&mdev->mq->mutex);
-
 	if (length) {
-		sendbuf = kmalloc(length * 4, GFP_KERNEL);
+		sendbuf = kzalloc(length * 4, GFP_KERNEL);
 		if (!sendbuf) {
-			mutex_unlock(&mdev->mq->mutex);
 			ret = -ENOMEM;
 			goto out;
 		}
@@ -187,84 +174,36 @@
 		memcpy(sendbuf + 4, data, (length - 1) * 4);
 	mdev->mq->sendbuf = sendbuf;
 
-	list_add(&mdev->mq->list, &maple_waitq);
-out:
+	mutex_lock(&maple_wlist_lock);
+	list_add_tail(&mdev->mq->list, &maple_waitq);
 	mutex_unlock(&maple_wlist_lock);
+out:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(maple_add_packet);
 
-/**
- * maple_add_packet_sleeps - add a single instruction to the queue
- * @mdev: maple device
- * @function: function on device being queried
- * @command: maple command to add
- * @length: length of command string (in 32 bit words)
- * @data: remainder of command string
- *
- * Same as maple_add_packet(), but waits for the lock to become free.
- */
-int maple_add_packet_sleeps(struct maple_device *mdev, u32 function,
-	u32 command, size_t length, void *data)
-{
-	int locking, ret = 0;
-	void *sendbuf = NULL;
-
-	locking = mutex_lock_interruptible(&mdev->mq->mutex);
-	if (locking) {
-		ret = -EIO;
-		goto out;
-	}
-
-	if (length) {
-		sendbuf = kmalloc(length * 4, GFP_KERNEL);
-		if (!sendbuf) {
-			mutex_unlock(&mdev->mq->mutex);
-			ret = -ENOMEM;
-			goto out;
-		}
-		((__be32 *)sendbuf)[0] = cpu_to_be32(function);
-	}
-
-	mdev->mq->command = command;
-	mdev->mq->length = length;
-	if (length > 1)
-		memcpy(sendbuf + 4, data, (length - 1) * 4);
-	mdev->mq->sendbuf = sendbuf;
-
-	mutex_lock(&maple_wlist_lock);
-	list_add(&mdev->mq->list, &maple_waitq);
-	mutex_unlock(&maple_wlist_lock);
-out:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(maple_add_packet_sleeps);
-
 static struct mapleq *maple_allocq(struct maple_device *mdev)
 {
 	struct mapleq *mq;
 
-	mq = kmalloc(sizeof(*mq), GFP_KERNEL);
+	mq = kzalloc(sizeof(*mq), GFP_KERNEL);
 	if (!mq)
 		goto failed_nomem;
 
+	INIT_LIST_HEAD(&mq->list);
 	mq->dev = mdev;
-	mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL);
-	mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp);
+	mq->recvbuf = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL);
 	if (!mq->recvbuf)
 		goto failed_p2;
-	/*
-	 * most devices do not need the mutex - but
-	 * anything that injects block reads or writes
-	 * will rely on it
-	 */
-	mutex_init(&mq->mutex);
+	mq->recvbuf->buf = &((mq->recvbuf->bufx)[0]);
 
 	return mq;
 
 failed_p2:
 	kfree(mq);
 failed_nomem:
+	dev_err(&mdev->dev, "could not allocate memory for device (%d, %d)\n",
+		mdev->port, mdev->unit);
 	return NULL;
 }
 
@@ -272,12 +211,16 @@
 {
 	struct maple_device *mdev;
 
+	/* zero this out to avoid kobj subsystem
+	* thinking it has already been registered */
+
 	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
 	if (!mdev)
 		return NULL;
 
 	mdev->port = port;
 	mdev->unit = unit;
+
 	mdev->mq = maple_allocq(mdev);
 
 	if (!mdev->mq) {
@@ -286,19 +229,14 @@
 	}
 	mdev->dev.bus = &maple_bus_type;
 	mdev->dev.parent = &maple_bus;
+	init_waitqueue_head(&mdev->maple_wait);
 	return mdev;
 }
 
 static void maple_free_dev(struct maple_device *mdev)
 {
-	if (!mdev)
-		return;
-	if (mdev->mq) {
-		if (mdev->mq->recvbufdcsp)
-			kmem_cache_free(maple_queue_cache,
-				mdev->mq->recvbufdcsp);
-		kfree(mdev->mq);
-	}
+	kmem_cache_free(maple_queue_cache, mdev->mq->recvbuf);
+	kfree(mdev->mq);
 	kfree(mdev);
 }
 
@@ -320,7 +258,7 @@
 	maple_lastptr = maple_sendptr;
 
 	*maple_sendptr++ = (port << 16) | len | 0x80000000;
-	*maple_sendptr++ = PHYSADDR(mq->recvbuf);
+	*maple_sendptr++ = PHYSADDR(mq->recvbuf->buf);
 	*maple_sendptr++ =
 	    mq->command | (to << 8) | (from << 16) | (len << 24);
 	while (len-- > 0)
@@ -333,20 +271,28 @@
 	int i, maple_packets = 0;
 	struct mapleq *mq, *nmq;
 
+	if (!maple_dma_done())
+		return;
+
+	/* disable DMA */
+	ctrl_outl(0, MAPLE_ENABLE);
+
 	if (!list_empty(&maple_sentq))
-		return;
+		goto finish;
+
 	mutex_lock(&maple_wlist_lock);
-	if (list_empty(&maple_waitq) || !maple_dma_done()) {
+	if (list_empty(&maple_waitq)) {
 		mutex_unlock(&maple_wlist_lock);
-		return;
+		goto finish;
 	}
-	mutex_unlock(&maple_wlist_lock);
+
 	maple_lastptr = maple_sendbuf;
 	maple_sendptr = maple_sendbuf;
-	mutex_lock(&maple_wlist_lock);
+
 	list_for_each_entry_safe(mq, nmq, &maple_waitq, list) {
 		maple_build_block(mq);
-		list_move(&mq->list, &maple_sentq);
+		list_del_init(&mq->list);
+		list_add_tail(&mq->list, &maple_sentq);
 		if (maple_packets++ > MAPLE_MAXPACKETS)
 			break;
 	}
@@ -356,10 +302,13 @@
 			dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE,
 				       PAGE_SIZE, DMA_BIDIRECTIONAL);
 	}
+
+finish:
+	maple_dma_reset();
 }
 
 /* check if there is a driver registered likely to match this device */
-static int check_matching_maple_driver(struct device_driver *driver,
+static int maple_check_matching_driver(struct device_driver *driver,
 					void *devptr)
 {
 	struct maple_driver *maple_drv;
@@ -374,10 +323,7 @@
 
 static void maple_detach_driver(struct maple_device *mdev)
 {
-	if (!mdev)
-		return;
 	device_unregister(&mdev->dev);
-	mdev = NULL;
 }
 
 /* process initial MAPLE_COMMAND_DEVINFO for each device or port */
@@ -385,9 +331,9 @@
 {
 	char *p, *recvbuf;
 	unsigned long function;
-	int matched, retval;
+	int matched, error;
 
-	recvbuf = mdev->mq->recvbuf;
+	recvbuf = mdev->mq->recvbuf->buf;
 	/* copy the data as individual elements in
 	* case of memory optimisation */
 	memcpy(&mdev->devinfo.function, recvbuf + 4, 4);
@@ -395,7 +341,6 @@
 	memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1);
 	memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1);
 	memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30);
-	memcpy(&mdev->devinfo.product_licence[0], recvbuf + 52, 60);
 	memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2);
 	memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2);
 	memcpy(mdev->product_name, mdev->devinfo.product_name, 30);
@@ -414,43 +359,39 @@
 		else
 			break;
 
-	printk(KERN_INFO "Maple device detected: %s\n",
-		mdev->product_name);
-	printk(KERN_INFO "Maple device: %s\n", mdev->product_licence);
-
 	function = be32_to_cpu(mdev->devinfo.function);
 
+	dev_info(&mdev->dev, "detected %s: function 0x%lX: at (%d, %d)\n",
+		mdev->product_name, function, mdev->port, mdev->unit);
+
 	if (function > 0x200) {
 		/* Do this silently - as not a real device */
 		function = 0;
-		mdev->driver = &maple_dummy_driver;
-		sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port);
+		mdev->driver = &maple_unsupported_device;
+		dev_set_name(&mdev->dev, "%d:0.port", mdev->port);
 	} else {
-		printk(KERN_INFO
-			"Maple bus at (%d, %d): Function 0x%lX\n",
-			mdev->port, mdev->unit, function);
-
 		matched =
 			bus_for_each_drv(&maple_bus_type, NULL, mdev,
-				check_matching_maple_driver);
+				maple_check_matching_driver);
 
 		if (matched == 0) {
 			/* Driver does not exist yet */
-			printk(KERN_INFO
-				"No maple driver found.\n");
-			mdev->driver = &maple_dummy_driver;
+			dev_info(&mdev->dev, "no driver found\n");
+			mdev->driver = &maple_unsupported_device;
 		}
-		sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port,
-			mdev->unit, function);
+		dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port,
+			     mdev->unit, function);
 	}
+
 	mdev->function = function;
 	mdev->dev.release = &maple_release_device;
-	retval = device_register(&mdev->dev);
-	if (retval) {
-		printk(KERN_INFO
-		"Maple bus: Attempt to register device"
-		" (%x, %x) failed.\n",
-		mdev->port, mdev->unit);
+
+	atomic_set(&mdev->busy, 0);
+	error = device_register(&mdev->dev);
+	if (error) {
+		dev_warn(&mdev->dev, "could not register device at"
+			" (%d, %d), with error 0x%X\n", mdev->unit,
+			mdev->port, error);
 		maple_free_dev(mdev);
 		mdev = NULL;
 		return;
@@ -462,7 +403,7 @@
  * port and unit then return 1 - allows identification
  * of which devices need to be attached or detached
  */
-static int detach_maple_device(struct device *device, void *portptr)
+static int check_maple_device(struct device *device, void *portptr)
 {
 	struct maple_device_specify *ds;
 	struct maple_device *mdev;
@@ -477,21 +418,25 @@
 static int setup_maple_commands(struct device *device, void *ignored)
 {
 	int add;
-	struct maple_device *maple_dev = to_maple_dev(device);
-
-	if ((maple_dev->interval > 0)
-	    && time_after(jiffies, maple_dev->when)) {
-		/* bounce if we cannot lock */
-		add = maple_add_packet(maple_dev,
-			be32_to_cpu(maple_dev->devinfo.function),
+	struct maple_device *mdev = to_maple_dev(device);
+	if (mdev->interval > 0 && atomic_read(&mdev->busy) == 0 &&
+		time_after(jiffies, mdev->when)) {
+		/* bounce if we cannot add */
+		add = maple_add_packet(mdev,
+			be32_to_cpu(mdev->devinfo.function),
 			MAPLE_COMMAND_GETCOND, 1, NULL);
 		if (!add)
-			maple_dev->when = jiffies + maple_dev->interval;
+			mdev->when = jiffies + mdev->interval;
 	} else {
 		if (time_after(jiffies, maple_pnp_time))
-			/* This will also bounce */
-			maple_add_packet(maple_dev, 0,
-				MAPLE_COMMAND_DEVINFO, 0, NULL);
+			/* Ensure we don't have block reads and devinfo
+			* calls interfering with one another - so flag the
+			* device as busy */
+			if (atomic_read(&mdev->busy) == 0) {
+				atomic_set(&mdev->busy, 1);
+				maple_add_packet(mdev, 0,
+					MAPLE_COMMAND_DEVINFO, 0, NULL);
+			}
 	}
 	return 0;
 }
@@ -499,29 +444,50 @@
 /* VBLANK bottom half - implemented via workqueue */
 static void maple_vblank_handler(struct work_struct *work)
 {
-	if (!list_empty(&maple_sentq) || !maple_dma_done())
+	int x, locking;
+	struct maple_device *mdev;
+
+	if (!maple_dma_done())
 		return;
 
 	ctrl_outl(0, MAPLE_ENABLE);
 
+	if (!list_empty(&maple_sentq))
+		goto finish;
+
+	/*
+	* Set up essential commands - to fetch data and
+	* check devices are still present
+	*/
 	bus_for_each_dev(&maple_bus_type, NULL, NULL,
-			 setup_maple_commands);
+		setup_maple_commands);
 
-	if (time_after(jiffies, maple_pnp_time))
+	if (time_after(jiffies, maple_pnp_time)) {
+		/*
+		* Scan the empty ports - bus is flakey and may have
+		* mis-reported emptyness
+		*/
+		for (x = 0; x < MAPLE_PORTS; x++) {
+			if (checked[x] && empty[x]) {
+				mdev = baseunits[x];
+				if (!mdev)
+					break;
+				atomic_set(&mdev->busy, 1);
+				locking = maple_add_packet(mdev, 0,
+					MAPLE_COMMAND_DEVINFO, 0, NULL);
+				if (!locking)
+					break;
+				}
+			}
+
 		maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL;
-
-	mutex_lock(&maple_wlist_lock);
-	if (!list_empty(&maple_waitq) && list_empty(&maple_sentq)) {
-		mutex_unlock(&maple_wlist_lock);
-		maple_send();
-	} else {
-		mutex_unlock(&maple_wlist_lock);
 	}
 
-	maplebus_dma_reset();
+finish:
+	maple_send();
 }
 
-/* handle devices added via hotplugs - placing them on queue for DEVINFO*/
+/* handle devices added via hotplugs - placing them on queue for DEVINFO */
 static void maple_map_subunits(struct maple_device *mdev, int submask)
 {
 	int retval, k, devcheck;
@@ -533,7 +499,7 @@
 		ds.unit = k + 1;
 		retval =
 		    bus_for_each_dev(&maple_bus_type, NULL, &ds,
-				     detach_maple_device);
+				     check_maple_device);
 		if (retval) {
 			submask = submask >> 1;
 			continue;
@@ -543,6 +509,7 @@
 			mdev_add = maple_alloc_dev(mdev->port, k + 1);
 			if (!mdev_add)
 				return;
+			atomic_set(&mdev_add->busy, 1);
 			maple_add_packet(mdev_add, 0, MAPLE_COMMAND_DEVINFO,
 				0, NULL);
 			/* mark that we are checking sub devices */
@@ -564,27 +531,45 @@
 }
 
 /* handle empty port or hotplug removal */
-static void maple_response_none(struct maple_device *mdev,
-				struct mapleq *mq)
+static void maple_response_none(struct maple_device *mdev)
 {
-	if (mdev->unit != 0) {
-		list_del(&mq->list);
-		maple_clean_submap(mdev);
-		printk(KERN_INFO
-		       "Maple bus device detaching at (%d, %d)\n",
-		       mdev->port, mdev->unit);
+	maple_clean_submap(mdev);
+
+	if (likely(mdev->unit != 0)) {
+		/*
+		* Block devices play up
+		* and give the impression they have
+		* been removed even when still in place or
+		* trip the mtd layer when they have
+		* really gone - this code traps that eventuality
+		* and ensures we aren't overloaded with useless
+		* error messages
+		*/
+		if (mdev->can_unload) {
+			if (!mdev->can_unload(mdev)) {
+				atomic_set(&mdev->busy, 2);
+				wake_up(&mdev->maple_wait);
+				return;
+			}
+		}
+
+		dev_info(&mdev->dev, "detaching device at (%d, %d)\n",
+			mdev->port, mdev->unit);
 		maple_detach_driver(mdev);
 		return;
-	}
-	if (!started || !fullscan) {
-		if (checked[mdev->port] == false) {
-			checked[mdev->port] = true;
-			printk(KERN_INFO "No maple devices attached"
-				" to port %d\n", mdev->port);
+	} else {
+		if (!started || !fullscan) {
+			if (checked[mdev->port] == false) {
+				checked[mdev->port] = true;
+				empty[mdev->port] = true;
+				dev_info(&mdev->dev, "no devices"
+					" to port %d\n", mdev->port);
+			}
+			return;
 		}
-		return;
 	}
-	maple_clean_submap(mdev);
+	/* Some hardware devices generate false detach messages on unit 0 */
+	atomic_set(&mdev->busy, 0);
 }
 
 /* preprocess hotplugs or scans */
@@ -599,8 +584,11 @@
 		} else {
 			if (mdev->unit != 0)
 				maple_attach_driver(mdev);
+			if (mdev->unit == 0) {
+				empty[mdev->port] = false;
+				maple_attach_driver(mdev);
+			}
 		}
-		return;
 	}
 	if (mdev->unit == 0) {
 		submask = recvbuf[2] & 0x1F;
@@ -611,6 +599,17 @@
 	}
 }
 
+static void maple_response_fileerr(struct maple_device *mdev, void *recvbuf)
+{
+	if (mdev->fileerr_handler) {
+		mdev->fileerr_handler(mdev, recvbuf);
+		return;
+	} else
+		dev_warn(&mdev->dev, "device at (%d, %d) reports"
+			"file error 0x%X\n", mdev->port, mdev->unit,
+			((int *)recvbuf)[1]);
+}
+
 static void maple_port_rescan(void)
 {
 	int i;
@@ -621,12 +620,6 @@
 		if (checked[i] == false) {
 			fullscan = 0;
 			mdev = baseunits[i];
-			/*
-			 *  test lock in case scan has failed
-			 *  but device is still locked
-			 */
-			if (mutex_is_locked(&mdev->mq->mutex))
-				mutex_unlock(&mdev->mq->mutex);
 			maple_add_packet(mdev, 0, MAPLE_COMMAND_DEVINFO,
 				0, NULL);
 		}
@@ -637,7 +630,7 @@
 static void maple_dma_handler(struct work_struct *work)
 {
 	struct mapleq *mq, *nmq;
-	struct maple_device *dev;
+	struct maple_device *mdev;
 	char *recvbuf;
 	enum maple_code code;
 
@@ -646,43 +639,56 @@
 	ctrl_outl(0, MAPLE_ENABLE);
 	if (!list_empty(&maple_sentq)) {
 		list_for_each_entry_safe(mq, nmq, &maple_sentq, list) {
-			recvbuf = mq->recvbuf;
+			mdev = mq->dev;
+			recvbuf = mq->recvbuf->buf;
+			dma_cache_sync(&mdev->dev, recvbuf, 0x400,
+				DMA_FROM_DEVICE);
 			code = recvbuf[0];
-			dev = mq->dev;
 			kfree(mq->sendbuf);
-			mutex_unlock(&mq->mutex);
 			list_del_init(&mq->list);
-
 			switch (code) {
 			case MAPLE_RESPONSE_NONE:
-				maple_response_none(dev, mq);
+				maple_response_none(mdev);
 				break;
 
 			case MAPLE_RESPONSE_DEVINFO:
-				maple_response_devinfo(dev, recvbuf);
+				maple_response_devinfo(mdev, recvbuf);
+				atomic_set(&mdev->busy, 0);
 				break;
 
 			case MAPLE_RESPONSE_DATATRF:
-				if (dev->callback)
-					dev->callback(mq);
+				if (mdev->callback)
+					mdev->callback(mq);
+				atomic_set(&mdev->busy, 0);
+				wake_up(&mdev->maple_wait);
 				break;
 
 			case MAPLE_RESPONSE_FILEERR:
+				maple_response_fileerr(mdev, recvbuf);
+				atomic_set(&mdev->busy, 0);
+				wake_up(&mdev->maple_wait);
+				break;
+
 			case MAPLE_RESPONSE_AGAIN:
 			case MAPLE_RESPONSE_BADCMD:
 			case MAPLE_RESPONSE_BADFUNC:
-				printk(KERN_DEBUG
-				       "Maple non-fatal error 0x%X\n",
-				       code);
+				dev_warn(&mdev->dev, "non-fatal error"
+					" 0x%X at (%d, %d)\n", code,
+					mdev->port, mdev->unit);
+				atomic_set(&mdev->busy, 0);
 				break;
 
 			case MAPLE_RESPONSE_ALLINFO:
-				printk(KERN_DEBUG
-				       "Maple - extended device information"
-					" not supported\n");
+				dev_notice(&mdev->dev, "extended"
+				" device information request for (%d, %d)"
+				" but call is not supported\n", mdev->port,
+				mdev->unit);
+				atomic_set(&mdev->busy, 0);
 				break;
 
 			case MAPLE_RESPONSE_OK:
+				atomic_set(&mdev->busy, 0);
+				wake_up(&mdev->maple_wait);
 				break;
 
 			default:
@@ -699,20 +705,19 @@
 		if (!fullscan)
 			maple_port_rescan();
 		/* mark that we have been through the first scan */
-		if (started == 0)
-			started = 1;
+		started = 1;
 	}
-	maplebus_dma_reset();
+	maple_send();
 }
 
-static irqreturn_t maplebus_dma_interrupt(int irq, void *dev_id)
+static irqreturn_t maple_dma_interrupt(int irq, void *dev_id)
 {
 	/* Load everything into the bottom half */
 	schedule_work(&maple_dma_process);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id)
+static irqreturn_t maple_vblank_interrupt(int irq, void *dev_id)
 {
 	schedule_work(&maple_vblank_process);
 	return IRQ_HANDLED;
@@ -720,14 +725,14 @@
 
 static int maple_set_dma_interrupt_handler(void)
 {
-	return request_irq(HW_EVENT_MAPLE_DMA, maplebus_dma_interrupt,
-		IRQF_SHARED, "maple bus DMA", &maple_dummy_driver);
+	return request_irq(HW_EVENT_MAPLE_DMA, maple_dma_interrupt,
+		IRQF_SHARED, "maple bus DMA", &maple_unsupported_device);
 }
 
 static int maple_set_vblank_interrupt_handler(void)
 {
-	return request_irq(HW_EVENT_VSYNC, maplebus_vblank_interrupt,
-		IRQF_SHARED, "maple bus VBLANK", &maple_dummy_driver);
+	return request_irq(HW_EVENT_VSYNC, maple_vblank_interrupt,
+		IRQF_SHARED, "maple bus VBLANK", &maple_unsupported_device);
 }
 
 static int maple_get_dma_buffer(void)
@@ -740,7 +745,7 @@
 	return 0;
 }
 
-static int match_maple_bus_driver(struct device *devptr,
+static int maple_match_bus_driver(struct device *devptr,
 				  struct device_driver *drvptr)
 {
 	struct maple_driver *maple_drv = to_maple_driver(drvptr);
@@ -765,22 +770,24 @@
 {
 }
 
-static struct maple_driver maple_dummy_driver = {
+static struct maple_driver maple_unsupported_device = {
 	.drv = {
-		.name = "maple_dummy_driver",
+		.name = "maple_unsupported_device",
 		.bus = &maple_bus_type,
 	},
 };
-
+/**
+ * maple_bus_type - core maple bus structure
+ */
 struct bus_type maple_bus_type = {
 	.name = "maple",
-	.match = match_maple_bus_driver,
+	.match = maple_match_bus_driver,
 	.uevent = maple_bus_uevent,
 };
 EXPORT_SYMBOL_GPL(maple_bus_type);
 
 static struct device maple_bus = {
-	.bus_id = "maple",
+	.init_name = "maple",
 	.release = maple_bus_release,
 };
 
@@ -788,7 +795,8 @@
 {
 	int retval, i;
 	struct maple_device *mdev[MAPLE_PORTS];
-	ctrl_outl(0, MAPLE_STATE);
+
+	ctrl_outl(0, MAPLE_ENABLE);
 
 	retval = device_register(&maple_bus);
 	if (retval)
@@ -798,36 +806,33 @@
 	if (retval)
 		goto cleanup_device;
 
-	retval = driver_register(&maple_dummy_driver.drv);
+	retval = driver_register(&maple_unsupported_device.drv);
 	if (retval)
 		goto cleanup_bus;
 
 	/* allocate memory for maple bus dma */
 	retval = maple_get_dma_buffer();
 	if (retval) {
-		printk(KERN_INFO
-		       "Maple bus: Failed to allocate Maple DMA buffers\n");
+		dev_err(&maple_bus, "failed to allocate DMA buffers\n");
 		goto cleanup_basic;
 	}
 
 	/* set up DMA interrupt handler */
 	retval = maple_set_dma_interrupt_handler();
 	if (retval) {
-		printk(KERN_INFO
-		       "Maple bus: Failed to grab maple DMA IRQ\n");
+		dev_err(&maple_bus, "bus failed to grab maple "
+			"DMA IRQ\n");
 		goto cleanup_dma;
 	}
 
 	/* set up VBLANK interrupt handler */
 	retval = maple_set_vblank_interrupt_handler();
 	if (retval) {
-		printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n");
+		dev_err(&maple_bus, "bus failed to grab VBLANK IRQ\n");
 		goto cleanup_irq;
 	}
 
-	maple_queue_cache =
-	    kmem_cache_create("maple_queue_cache", 0x400, 0,
-			      SLAB_HWCACHE_ALIGN, NULL);
+	maple_queue_cache = KMEM_CACHE(maple_buffer, SLAB_HWCACHE_ALIGN);
 
 	if (!maple_queue_cache)
 		goto cleanup_bothirqs;
@@ -838,23 +843,23 @@
 	/* setup maple ports */
 	for (i = 0; i < MAPLE_PORTS; i++) {
 		checked[i] = false;
+		empty[i] = false;
 		mdev[i] = maple_alloc_dev(i, 0);
-		baseunits[i] = mdev[i];
 		if (!mdev[i]) {
 			while (i-- > 0)
 				maple_free_dev(mdev[i]);
 			goto cleanup_cache;
 		}
+		baseunits[i] = mdev[i];
+		atomic_set(&mdev[i]->busy, 1);
 		maple_add_packet(mdev[i], 0, MAPLE_COMMAND_DEVINFO, 0, NULL);
 		subdevice_map[i] = 0;
 	}
 
-	/* setup maplebus hardware */
-	maplebus_dma_reset();
-	/* initial detection */
+	maple_pnp_time = jiffies + HZ;
+	/* prepare initial queue */
 	maple_send();
-	maple_pnp_time = jiffies;
-	printk(KERN_INFO "Maple bus core now registered.\n");
+	dev_info(&maple_bus, "bus core now registered\n");
 
 	return 0;
 
@@ -871,7 +876,7 @@
 	free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES);
 
 cleanup_basic:
-	driver_unregister(&maple_dummy_driver.drv);
+	driver_unregister(&maple_unsupported_device.drv);
 
 cleanup_bus:
 	bus_unregister(&maple_bus_type);
@@ -880,7 +885,7 @@
 	device_unregister(&maple_bus);
 
 cleanup:
-	printk(KERN_INFO "Maple bus registration failed\n");
+	printk(KERN_ERR "Maple bus registration failed\n");
 	return retval;
 }
 /* Push init to later to ensure hardware gets detected */
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index 4d0282b..2d9e7f3 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -22,7 +22,7 @@
 static int superhyway_devices;
 
 static struct device superhyway_bus_device = {
-	.bus_id = "superhyway",
+	.init_name = "superhyway",
 };
 
 static void superhyway_device_release(struct device *dev)
@@ -83,7 +83,7 @@
 	dev->id.id		= dev->vcr.mod_id;
 
 	sprintf(dev->name, "SuperHyway device %04x", dev->id.id);
-	sprintf(dev->dev.bus_id, "%02x", superhyway_devices);
+	dev_set_name(&dev->dev, "%02x", superhyway_devices);
 
 	superhyway_devices++;
 
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 56ff3e6..12e443c 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -322,7 +322,7 @@
 	spi = msg->spi;
 
 	dev_dbg(master->dev.parent, "start message %p for %s\n",
-			msg, spi->dev.bus_id);
+			msg, dev_name(&spi->dev));
 
 	/* select chip if it's not still active */
 	if (as->stay) {
@@ -627,7 +627,7 @@
 		if (!asd)
 			return -ENOMEM;
 
-		ret = gpio_request(npcs_pin, spi->dev.bus_id);
+		ret = gpio_request(npcs_pin, dev_name(&spi->dev));
 		if (ret) {
 			kfree(asd);
 			return ret;
@@ -668,7 +668,7 @@
 	as = spi_master_get_devdata(spi->master);
 
 	dev_dbg(controller, "new message %p submitted for %s\n",
-			msg, spi->dev.bus_id);
+			msg, dev_name(&spi->dev));
 
 	if (unlikely(list_empty(&msg->transfers)))
 		return -EINVAL;
@@ -803,7 +803,7 @@
 	as->clk = clk;
 
 	ret = request_irq(irq, atmel_spi_interrupt, 0,
-			pdev->dev.bus_id, master);
+			dev_name(&pdev->dev), master);
 	if (ret)
 		goto out_unmap_regs;
 
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 3b97803..68c77a9 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -429,7 +429,7 @@
 	INIT_LIST_HEAD(&mps->queue);
 
 	mps->workqueue = create_singlethread_workqueue(
-		master->dev.parent->bus_id);
+		dev_name(master->dev.parent));
 	if (mps->workqueue == NULL) {
 		ret = -EBUSY;
 		goto free_irq;
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 454a271..1c65e38 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -1003,7 +1003,7 @@
 		goto err1;
 	}
 	if (!request_mem_region(r->start, (r->end - r->start) + 1,
-			pdev->dev.bus_id)) {
+			dev_name(&pdev->dev))) {
 		status = -EBUSY;
 		goto err1;
 	}
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
index bab6ff0..60b5381 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/omap_uwire.c
@@ -245,7 +245,7 @@
 
 #ifdef	VERBOSE
 			pr_debug("%s: write-%d =%04x\n",
-					spi->dev.bus_id, bits, val);
+					dev_name(&spi->dev), bits, val);
 #endif
 			if (wait_uwire_csr_flag(CSRB, 0, 0))
 				goto eio;
@@ -305,7 +305,7 @@
 			status += bytes;
 #ifdef	VERBOSE
 			pr_debug("%s: read-%d =%04x\n",
-					spi->dev.bus_id, bits, val);
+					dev_name(&spi->dev), bits, val);
 #endif
 
 		}
@@ -331,7 +331,7 @@
 	uwire = spi_master_get_devdata(spi->master);
 
 	if (spi->chip_select > 3) {
-		pr_debug("%s: cs%d?\n", spi->dev.bus_id, spi->chip_select);
+		pr_debug("%s: cs%d?\n", dev_name(&spi->dev), spi->chip_select);
 		status = -ENODEV;
 		goto done;
 	}
@@ -343,7 +343,7 @@
 		bits = 8;
 
 	if (bits > 16) {
-		pr_debug("%s: wordsize %d?\n", spi->dev.bus_id, bits);
+		pr_debug("%s: wordsize %d?\n", dev_name(&spi->dev), bits);
 		status = -ENODEV;
 		goto done;
 	}
@@ -378,7 +378,7 @@
 		hz = t->speed_hz;
 
 	if (!hz) {
-		pr_debug("%s: zero speed?\n", spi->dev.bus_id);
+		pr_debug("%s: zero speed?\n", dev_name(&spi->dev));
 		status = -EINVAL;
 		goto done;
 	}
@@ -406,7 +406,7 @@
 	}
 	if (div1_idx == 4) {
 		pr_debug("%s: lowest clock %ld, need %d\n",
-			spi->dev.bus_id, rate / 10 / 8, hz);
+			dev_name(&spi->dev), rate / 10 / 8, hz);
 		status = -EDOM;
 		goto done;
 	}
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c
index 014becb..c8b0bab 100644
--- a/drivers/spi/orion_spi.c
+++ b/drivers/spi/orion_spi.c
@@ -496,7 +496,7 @@
 	}
 
 	if (!request_mem_region(r->start, (r->end - r->start) + 1,
-				pdev->dev.bus_id)) {
+				dev_name(&pdev->dev))) {
 		status = -EBUSY;
 		goto out;
 	}
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index d0fc4ca..ec24f2d 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1333,7 +1333,7 @@
 
 	INIT_WORK(&drv_data->pump_messages, pump_messages);
 	drv_data->workqueue = create_singlethread_workqueue(
-					drv_data->master->dev.parent->bus_id);
+				dev_name(drv_data->master->dev.parent));
 	if (drv_data->workqueue == NULL)
 		return -EBUSY;
 
@@ -1462,7 +1462,7 @@
 		drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
 	}
 
-	status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data);
+	status = request_irq(ssp->irq, ssp_int, 0, dev_name(dev), drv_data);
 	if (status < 0) {
 		dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
 		goto out_error_master_alloc;
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 7fea3cf..3410b0c 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1160,8 +1160,8 @@
 
 	/* init messages workqueue */
 	INIT_WORK(&drv_data->pump_messages, pump_messages);
-	drv_data->workqueue =
-	    create_singlethread_workqueue(drv_data->master->dev.parent->bus_id);
+	drv_data->workqueue = create_singlethread_workqueue(
+				dev_name(drv_data->master->dev.parent));
 	if (drv_data->workqueue == NULL)
 		return -EBUSY;
 
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c
index f5ed972..d2866c2 100644
--- a/drivers/spi/spi_gpio.c
+++ b/drivers/spi/spi_gpio.c
@@ -191,7 +191,7 @@
 		return -EINVAL;
 
 	if (!spi->controller_state) {
-		status = gpio_request(cs, spi->dev.bus_id);
+		status = gpio_request(cs, dev_name(&spi->dev));
 		if (status)
 			return status;
 		status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH);
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 269a55e..0480d8bb 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -1381,7 +1381,7 @@
 
 	INIT_WORK(&drv_data->work, pump_messages);
 	drv_data->workqueue = create_singlethread_workqueue(
-					drv_data->master->dev.parent->bus_id);
+				dev_name(drv_data->master->dev.parent));
 	if (drv_data->workqueue == NULL)
 		return -EBUSY;
 
@@ -1525,7 +1525,8 @@
 		status = -ENODEV;
 		goto err_no_irqres;
 	}
-	status = request_irq(irq, spi_int, IRQF_DISABLED, dev->bus_id, drv_data);
+	status = request_irq(irq, spi_int, IRQF_DISABLED,
+			     dev_name(dev), drv_data);
 	if (status < 0) {
 		dev_err(&pdev->dev, "probe - cannot get IRQ (%d)\n", status);
 		goto err_no_irqres;
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index ac0e3e4..44a2b46 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -637,7 +637,7 @@
 	INIT_LIST_HEAD(&mpc83xx_spi->queue);
 
 	mpc83xx_spi->workqueue = create_singlethread_workqueue(
-		master->dev.parent->bus_id);
+		dev_name(master->dev.parent));
 	if (mpc83xx_spi->workqueue == NULL) {
 		ret = -EBUSY;
 		goto free_irq;
@@ -649,7 +649,7 @@
 
 	printk(KERN_INFO
 	       "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n",
-	       dev->dev.bus_id, mpc83xx_spi->base, mpc83xx_spi->irq);
+	       dev_name(&dev->dev), mpc83xx_spi->base, mpc83xx_spi->irq);
 
 	return ret;
 
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
index 2296f37..29cbb06 100644
--- a/drivers/spi/spi_txx9.c
+++ b/drivers/spi/spi_txx9.c
@@ -404,7 +404,8 @@
 	if (ret)
 		goto exit;
 
-	c->workqueue = create_singlethread_workqueue(master->dev.parent->bus_id);
+	c->workqueue = create_singlethread_workqueue(
+				dev_name(master->dev.parent));
 	if (!c->workqueue)
 		goto exit_busy;
 	c->last_chipselect = -1;
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index ce6badd..211af86 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -73,8 +73,6 @@
 
 source "drivers/staging/rt2870/Kconfig"
 
-source "drivers/staging/benet/Kconfig"
-
 source "drivers/staging/comedi/Kconfig"
 
 source "drivers/staging/asus_oled/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 9ddcc2b..47a56f5 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -19,7 +19,6 @@
 obj-$(CONFIG_OTUS)		+= otus/
 obj-$(CONFIG_RT2860)		+= rt2860/
 obj-$(CONFIG_RT2870)		+= rt2870/
-obj-$(CONFIG_BENET)		+= benet/
 obj-$(CONFIG_COMEDI)		+= comedi/
 obj-$(CONFIG_ASUS_OLED)		+= asus_oled/
 obj-$(CONFIG_PANEL)		+= panel/
diff --git a/drivers/staging/benet/Kconfig b/drivers/staging/benet/Kconfig
deleted file mode 100644
index f680607..0000000
--- a/drivers/staging/benet/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config BENET
-	tristate "ServerEngines 10Gb NIC - BladeEngine"
-	depends on PCI && INET
-	select INET_LRO
-	help
-	  This driver implements the NIC functionality for ServerEngines
-	  10Gb network adapter BladeEngine (EC 3210).
diff --git a/drivers/staging/benet/MAINTAINERS b/drivers/staging/benet/MAINTAINERS
deleted file mode 100644
index d5ce340..0000000
--- a/drivers/staging/benet/MAINTAINERS
+++ /dev/null
@@ -1,6 +0,0 @@
-SERVER ENGINES 10Gbe NIC - BLADE-ENGINE
-P:	Subbu Seetharaman
-M:	subbus@serverengines.com
-L:	netdev@vger.kernel.org
-W:	http://www.serverengines.com
-S:	Supported
diff --git a/drivers/staging/benet/Makefile b/drivers/staging/benet/Makefile
deleted file mode 100644
index 460b923..0000000
--- a/drivers/staging/benet/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile to build the network driver for ServerEngine's BladeEngine
-#
-obj-$(CONFIG_BENET) += benet.o
-
-benet-y :=  be_init.o \
-			be_int.o \
-			be_netif.o \
-			be_ethtool.o \
-			funcobj.o \
-			cq.o \
-			eq.o \
-			mpu.o \
-			eth.o
diff --git a/drivers/staging/benet/TODO b/drivers/staging/benet/TODO
deleted file mode 100644
index a51dfb5..0000000
--- a/drivers/staging/benet/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-TODO:
-	- remove wrappers around common iowrite functions
-	- full netdev audit of common problems/issues
-
-Please send all patches and questions to Subbu Seetharaman
-<subbus@serverengines.com> and Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/benet/asyncmesg.h b/drivers/staging/benet/asyncmesg.h
deleted file mode 100644
index d1e779a..0000000
--- a/drivers/staging/benet/asyncmesg.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __asyncmesg_amap_h__
-#define __asyncmesg_amap_h__
-#include "fwcmd_common.h"
-
-/* --- ASYNC_EVENT_CODES --- */
-#define ASYNC_EVENT_CODE_LINK_STATE     (1)
-#define ASYNC_EVENT_CODE_ISCSI          (2)
-
-/* --- ASYNC_LINK_STATES --- */
-#define ASYNC_EVENT_LINK_DOWN           (0)	/* Link Down on a port */
-#define ASYNC_EVENT_LINK_UP             (1)	/* Link Up on a port */
-
-/*
- * The last 4 bytes of the async events have this common format.  It allows
- * the driver to distinguish [link]MCC_CQ_ENTRY[/link] structs from
- * asynchronous events.  Both arrive on the same completion queue.  This
- * structure also contains the common fields used to decode the async event.
- */
-struct BE_ASYNC_EVENT_TRAILER_AMAP {
-	u8 rsvd0[8];	/* DWORD 0 */
-	u8 event_code[8];	/* DWORD 0 */
-	u8 event_type[8];	/* DWORD 0 */
-	u8 rsvd1[6];	/* DWORD 0 */
-	u8 async_event;	/* DWORD 0 */
-	u8 valid;		/* DWORD 0 */
-} __packed;
-struct ASYNC_EVENT_TRAILER_AMAP {
-	u32 dw[1];
-};
-
-/*
- * Applicable in Initiator, Target and NIC modes.
- * A link state async event is seen by all device drivers as soon they
- * create an MCC ring. Thereafter, anytime the link status changes the
- * drivers will receive a link state async event. Notifications continue to
- * be sent until a driver destroys its MCC ring. A link down event is
- * reported when either port loses link. A link up event is reported
- * when either port regains link. When BE's failover mechanism is enabled, a
- * link down on the active port causes traffic to be diverted to the standby
- * port by the BE's ARM firmware (assuming the standby port has link). In
- * this case, the standy port assumes the active status. Note: when link is
- * restored on the failed port, traffic continues on the currently active
- * port. The ARM firmware does not attempt to 'fail back' traffic to
- * the restored port.
- */
-struct BE_ASYNC_EVENT_LINK_STATE_AMAP {
-	u8 port0_link_status[8];
-	u8 port1_link_status[8];
-	u8 active_port[8];
-	u8 rsvd0[8];	/* DWORD 0 */
-	u8 port0_duplex[8];
-	u8 port0_speed[8];
-	u8 port1_duplex[8];
-	u8 port1_speed[8];
-	u8 port0_fault[8];
-	u8 port1_fault[8];
-	u8 rsvd1[2][8];	/* DWORD 2 */
-	struct BE_ASYNC_EVENT_TRAILER_AMAP trailer;
-} __packed;
-struct ASYNC_EVENT_LINK_STATE_AMAP {
-	u32 dw[4];
-};
-#endif /* __asyncmesg_amap_h__ */
diff --git a/drivers/staging/benet/be_cm.h b/drivers/staging/benet/be_cm.h
deleted file mode 100644
index b7a1dfd..0000000
--- a/drivers/staging/benet/be_cm.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __be_cm_amap_h__
-#define __be_cm_amap_h__
-#include "be_common.h"
-#include "etx_context.h"
-#include "mpu_context.h"
-
-/*
- * --- CEV_WATERMARK_ENUM ---
- * CQ/EQ Watermark Encodings. Encoded as number of free entries in
- * Queue when Watermark is reached.
- */
-#define CEV_WMARK_0        (0)	/* Watermark when Queue full */
-#define CEV_WMARK_16       (1)	/* Watermark at 16 free entries */
-#define CEV_WMARK_32       (2)	/* Watermark at 32 free entries */
-#define CEV_WMARK_48       (3)	/* Watermark at 48 free entries */
-#define CEV_WMARK_64       (4)	/* Watermark at 64 free entries */
-#define CEV_WMARK_80       (5)	/* Watermark at 80 free entries */
-#define CEV_WMARK_96       (6)	/* Watermark at 96 free entries */
-#define CEV_WMARK_112      (7)	/* Watermark at 112 free entries */
-#define CEV_WMARK_128      (8)	/* Watermark at 128 free entries */
-#define CEV_WMARK_144      (9)	/* Watermark at 144 free entries */
-#define CEV_WMARK_160      (10)	/* Watermark at 160 free entries */
-#define CEV_WMARK_176      (11)	/* Watermark at 176 free entries */
-#define CEV_WMARK_192      (12)	/* Watermark at 192 free entries */
-#define CEV_WMARK_208      (13)	/* Watermark at 208 free entries */
-#define CEV_WMARK_224      (14)	/* Watermark at 224 free entries */
-#define CEV_WMARK_240      (15)	/* Watermark at 240 free entries */
-
-/*
- * --- CQ_CNT_ENUM ---
- * Completion Queue Count Encodings.
- */
-#define CEV_CQ_CNT_256                  (0)	/* CQ has 256 entries */
-#define CEV_CQ_CNT_512                  (1)	/* CQ has 512 entries */
-#define CEV_CQ_CNT_1024                 (2)	/* CQ has 1024 entries */
-
-/*
- * --- EQ_CNT_ENUM ---
- * Event Queue Count Encodings.
- */
-#define CEV_EQ_CNT_256     (0)	/* EQ has 256 entries (16-byte EQEs only) */
-#define CEV_EQ_CNT_512     (1)	/* EQ has 512 entries (16-byte EQEs only) */
-#define CEV_EQ_CNT_1024    (2)	/* EQ has 1024 entries (4-byte or */
-				/* 16-byte EQEs only) */
-#define CEV_EQ_CNT_2048    (3)	/* EQ has 2048 entries (4-byte or */
-				/* 16-byte EQEs only) */
-#define CEV_EQ_CNT_4096    (4)	/* EQ has 4096 entries (4-byte EQEs only) */
-
-/*
- * --- EQ_SIZE_ENUM ---
- * Event Queue Entry Size Encoding.
- */
-#define CEV_EQ_SIZE_4                   (0)	/* EQE is 4 bytes */
-#define CEV_EQ_SIZE_16                  (1)	/* EQE is 16 bytes */
-
-/*
- * Completion Queue Context Table Entry. Contains the state of a CQ.
- * Located in RAM within the CEV block.
- */
-struct BE_CQ_CONTEXT_AMAP {
-	u8 Cidx[11];	/* DWORD 0 */
-	u8 Watermark[4];	/* DWORD 0 */
-	u8 NoDelay;		/* DWORD 0 */
-	u8 EPIdx[11];	/* DWORD 0 */
-	u8 Count[2];	/* DWORD 0 */
-	u8 valid;		/* DWORD 0 */
-	u8 SolEvent;	/* DWORD 0 */
-	u8 Eventable;	/* DWORD 0 */
-	u8 Pidx[11];	/* DWORD 1 */
-	u8 PD[10];		/* DWORD 1 */
-	u8 EQID[7];		/* DWORD 1 */
-	u8 Func;		/* DWORD 1 */
-	u8 WME;		/* DWORD 1 */
-	u8 Stalled;		/* DWORD 1 */
-	u8 Armed;		/* DWORD 1 */
-} __packed;
-struct CQ_CONTEXT_AMAP {
-	u32 dw[2];
-};
-
-/*
- * Event Queue Context Table Entry. Contains the state of an EQ.
- * Located in RAM in the CEV block.
- */
-struct BE_EQ_CONTEXT_AMAP {
-	u8 Cidx[13];	/* DWORD 0 */
-	u8 rsvd0[2];	/* DWORD 0 */
-	u8 Func;		/* DWORD 0 */
-	u8 EPIdx[13];	/* DWORD 0 */
-	u8 valid;		/* DWORD 0 */
-	u8 rsvd1;		/* DWORD 0 */
-	u8 Size;		/* DWORD 0 */
-	u8 Pidx[13];	/* DWORD 1 */
-	u8 rsvd2[3];	/* DWORD 1 */
-	u8 PD[10];		/* DWORD 1 */
-	u8 Count[3];	/* DWORD 1 */
-	u8 SolEvent;	/* DWORD 1 */
-	u8 Stalled;		/* DWORD 1 */
-	u8 Armed;		/* DWORD 1 */
-	u8 Watermark[4];	/* DWORD 2 */
-	u8 WME;		/* DWORD 2 */
-	u8 rsvd3[3];	/* DWORD 2 */
-	u8 EventVect[6];	/* DWORD 2 */
-	u8 rsvd4[2];	/* DWORD 2 */
-	u8 Delay[8];	/* DWORD 2 */
-	u8 rsvd5[6];	/* DWORD 2 */
-	u8 TMR;		/* DWORD 2 */
-	u8 rsvd6;		/* DWORD 2 */
-	u8 rsvd7[32];	/* DWORD 3 */
-} __packed;
-struct EQ_CONTEXT_AMAP {
-	u32 dw[4];
-};
-
-#endif /* __be_cm_amap_h__ */
diff --git a/drivers/staging/benet/be_common.h b/drivers/staging/benet/be_common.h
deleted file mode 100644
index 7e63dc5..0000000
--- a/drivers/staging/benet/be_common.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __be_common_amap_h__
-#define __be_common_amap_h__
-
-/* Physical Address. */
-struct BE_PHYS_ADDR_AMAP {
-	u8 lo[32];		/* DWORD 0 */
-	u8 hi[32];		/* DWORD 1 */
-} __packed;
-struct PHYS_ADDR_AMAP {
-	u32 dw[2];
-};
-
-/* Virtual Address. */
-struct BE_VIRT_ADDR_AMAP {
-	u8 lo[32];		/* DWORD 0 */
-	u8 hi[32];		/* DWORD 1 */
-} __packed;
-struct VIRT_ADDR_AMAP {
-	u32 dw[2];
-};
-
-/* Scatter gather element. */
-struct BE_SGE_AMAP {
-	u8 addr_hi[32];	/* DWORD 0 */
-	u8 addr_lo[32];	/* DWORD 1 */
-	u8 rsvd0[32];	/* DWORD 2 */
-	u8 len[16];		/* DWORD 3 */
-	u8 rsvd1[16];	/* DWORD 3 */
-} __packed;
-struct SGE_AMAP {
-	u32 dw[4];
-};
-
-#endif /* __be_common_amap_h__ */
diff --git a/drivers/staging/benet/be_ethtool.c b/drivers/staging/benet/be_ethtool.c
deleted file mode 100644
index 027af85..0000000
--- a/drivers/staging/benet/be_ethtool.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * be_ethtool.c
- *
- * 	This file contains various functions that ethtool can use
- * 	to talk to the driver and the BE H/W.
- */
-
-#include "benet.h"
-
-#include <linux/ethtool.h>
-
-static const char benet_gstrings_stats[][ETH_GSTRING_LEN] = {
-/* net_device_stats */
-	"rx_packets",
-	"tx_packets",
-	"rx_bytes",
-	"tx_bytes",
-	"rx_errors",
-	"tx_errors",
-	"rx_dropped",
-	"tx_dropped",
-	"multicast",
-	"collisions",
-	"rx_length_errors",
-	"rx_over_errors",
-	"rx_crc_errors",
-	"rx_frame_errors",
-	"rx_fifo_errors",
-	"rx_missed_errors",
-	"tx_aborted_errors",
-	"tx_carrier_errors",
-	"tx_fifo_errors",
-	"tx_heartbeat_errors",
-	"tx_window_errors",
-	"rx_compressed",
-	"tc_compressed",
-/* BE driver Stats */
-	"bes_tx_reqs",
-	"bes_tx_fails",
-	"bes_fwd_reqs",
-	"bes_tx_wrbs",
-	"bes_interrupts",
-	"bes_events",
-	"bes_tx_events",
-	"bes_rx_events",
-	"bes_tx_compl",
-	"bes_rx_compl",
-	"bes_ethrx_post_fail",
-	"bes_802_3_dropped_frames",
-	"bes_802_3_malformed_frames",
-	"bes_rx_misc_pkts",
-	"bes_eth_tx_rate",
-	"bes_eth_rx_rate",
-	"Num Packets collected",
-	"Num Times Flushed",
-};
-
-#define NET_DEV_STATS_LEN \
-	(sizeof(struct net_device_stats)/sizeof(unsigned long))
-
-#define BENET_STATS_LEN  ARRAY_SIZE(benet_gstrings_stats)
-
-static void
-be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-
-	strncpy(drvinfo->driver, be_driver_name, 32);
-	strncpy(drvinfo->version, be_drvr_ver, 32);
-	strncpy(drvinfo->fw_version, be_fw_ver, 32);
-	strcpy(drvinfo->bus_info, pci_name(adapter->pdev));
-	drvinfo->testinfo_len = 0;
-	drvinfo->regdump_len = 0;
-	drvinfo->eedump_len = 0;
-}
-
-static int
-be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-
-	coalesce->rx_max_coalesced_frames = adapter->max_rx_coal;
-
-	coalesce->rx_coalesce_usecs = adapter->cur_eqd;
-	coalesce->rx_coalesce_usecs_high = adapter->max_eqd;
-	coalesce->rx_coalesce_usecs_low = adapter->min_eqd;
-
-	coalesce->tx_coalesce_usecs = adapter->cur_eqd;
-	coalesce->tx_coalesce_usecs_high = adapter->max_eqd;
-	coalesce->tx_coalesce_usecs_low = adapter->min_eqd;
-
-	coalesce->use_adaptive_rx_coalesce = adapter->enable_aic;
-	coalesce->use_adaptive_tx_coalesce = adapter->enable_aic;
-
-	return 0;
-}
-
-/*
- * This routine is used to set interrup coalescing delay *as well as*
- * the number of pkts to coalesce for LRO.
- */
-static int
-be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-	struct be_eq_object *eq_objectp;
-	u32 max, min, cur;
-	int status;
-
-	adapter->max_rx_coal = coalesce->rx_max_coalesced_frames;
-	if (adapter->max_rx_coal >= BE_LRO_MAX_PKTS)
-		adapter->max_rx_coal = BE_LRO_MAX_PKTS;
-
-	if (adapter->enable_aic == 0 &&
-		coalesce->use_adaptive_rx_coalesce == 1) {
-		/* if AIC is being turned on now, start with an EQD of 0 */
-		adapter->cur_eqd = 0;
-	}
-	adapter->enable_aic = coalesce->use_adaptive_rx_coalesce;
-
-	/* round off to nearest multiple of 8 */
-	max = (((coalesce->rx_coalesce_usecs_high + 4) >> 3) << 3);
-	min = (((coalesce->rx_coalesce_usecs_low + 4) >> 3) << 3);
-	cur = (((coalesce->rx_coalesce_usecs + 4) >> 3) << 3);
-
-	if (adapter->enable_aic) {
-		/* accept low and high if AIC is enabled */
-		if (max > MAX_EQD)
-			max = MAX_EQD;
-		if (min > max)
-			min = max;
-		adapter->max_eqd = max;
-		adapter->min_eqd = min;
-		if (adapter->cur_eqd > max)
-			adapter->cur_eqd = max;
-		if (adapter->cur_eqd < min)
-			adapter->cur_eqd = min;
-	} else {
-		/* accept specified coalesce_usecs only if AIC is disabled */
-		if (cur > MAX_EQD)
-			cur = MAX_EQD;
-		eq_objectp = &pnob->event_q_obj;
-		status =
-		    be_eq_modify_delay(&pnob->fn_obj, 1, &eq_objectp, &cur,
-				       NULL, NULL, NULL);
-		if (status == BE_SUCCESS)
-			adapter->cur_eqd = cur;
-	}
-	return 0;
-}
-
-static u32 be_get_rx_csum(struct net_device *netdev)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-	return adapter->rx_csum;
-}
-
-static int be_set_rx_csum(struct net_device *netdev, uint32_t data)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-
-	if (data)
-		adapter->rx_csum = 1;
-	else
-		adapter->rx_csum = 0;
-
-	return 0;
-}
-
-static void
-be_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
-{
-	switch (stringset) {
-	case ETH_SS_STATS:
-		memcpy(data, *benet_gstrings_stats,
-		       sizeof(benet_gstrings_stats));
-		break;
-	}
-}
-
-static int be_get_stats_count(struct net_device *netdev)
-{
-	return BENET_STATS_LEN;
-}
-
-static void
-be_get_ethtool_stats(struct net_device *netdev,
-		     struct ethtool_stats *stats, uint64_t *data)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-	int i;
-
-	benet_get_stats(netdev);
-
-	for (i = 0; i <= NET_DEV_STATS_LEN; i++)
-		data[i] = ((unsigned long *)&adapter->benet_stats)[i];
-
-	data[i] = adapter->be_stat.bes_tx_reqs;
-	data[i++] = adapter->be_stat.bes_tx_fails;
-	data[i++] = adapter->be_stat.bes_fwd_reqs;
-	data[i++] = adapter->be_stat.bes_tx_wrbs;
-
-	data[i++] = adapter->be_stat.bes_ints;
-	data[i++] = adapter->be_stat.bes_events;
-	data[i++] = adapter->be_stat.bes_tx_events;
-	data[i++] = adapter->be_stat.bes_rx_events;
-	data[i++] = adapter->be_stat.bes_tx_compl;
-	data[i++] = adapter->be_stat.bes_rx_compl;
-	data[i++] = adapter->be_stat.bes_ethrx_post_fail;
-	data[i++] = adapter->be_stat.bes_802_3_dropped_frames;
-	data[i++] = adapter->be_stat.bes_802_3_malformed_frames;
-	data[i++] = adapter->be_stat.bes_rx_misc_pkts;
-	data[i++] = adapter->be_stat.bes_eth_tx_rate;
-	data[i++] = adapter->be_stat.bes_eth_rx_rate;
-	data[i++] = adapter->be_stat.bes_rx_coal;
-	data[i++] = adapter->be_stat.bes_rx_flush;
-
-}
-
-static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
-{
-	ecmd->speed = SPEED_10000;
-	ecmd->duplex = DUPLEX_FULL;
-	ecmd->autoneg = AUTONEG_DISABLE;
-	return 0;
-}
-
-/* Get the Ring parameters from the pnob */
-static void
-be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-
-	/* Pre Set Maxims */
-	ring->rx_max_pending = pnob->rx_q_len;
-	ring->rx_mini_max_pending = ring->rx_mini_max_pending;
-	ring->rx_jumbo_max_pending = ring->rx_jumbo_max_pending;
-	ring->tx_max_pending = pnob->tx_q_len;
-
-	/* Current hardware Settings                */
-	ring->rx_pending = atomic_read(&pnob->rx_q_posted);
-	ring->rx_mini_pending = ring->rx_mini_pending;
-	ring->rx_jumbo_pending = ring->rx_jumbo_pending;
-	ring->tx_pending = atomic_read(&pnob->tx_q_used);
-
-}
-
-static void
-be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	bool rxfc, txfc;
-	int status;
-
-	status = be_eth_get_flow_control(&pnob->fn_obj, &txfc, &rxfc);
-	if (status != BE_SUCCESS) {
-		dev_info(&netdev->dev, "Unable to get pause frame settings\n");
-		/* return defaults */
-		ecmd->rx_pause = 1;
-		ecmd->tx_pause = 0;
-		ecmd->autoneg = AUTONEG_ENABLE;
-		return;
-	}
-
-	if (txfc == true)
-		ecmd->tx_pause = 1;
-	else
-		ecmd->tx_pause = 0;
-
-	if (rxfc == true)
-		ecmd->rx_pause = 1;
-	else
-		ecmd->rx_pause = 0;
-
-	ecmd->autoneg = AUTONEG_ENABLE;
-}
-
-static int
-be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	bool txfc, rxfc;
-	int status;
-
-	if (ecmd->autoneg != AUTONEG_ENABLE)
-		return -EINVAL;
-
-	if (ecmd->tx_pause)
-		txfc = true;
-	else
-		txfc = false;
-
-	if (ecmd->rx_pause)
-		rxfc = true;
-	else
-		rxfc = false;
-
-	status = be_eth_set_flow_control(&pnob->fn_obj, txfc, rxfc);
-	if (status != BE_SUCCESS) {
-		dev_info(&netdev->dev, "Unable to set pause frame settings\n");
-		return -1;
-	}
-	return 0;
-}
-
-struct ethtool_ops be_ethtool_ops = {
-	.get_settings = be_get_settings,
-	.get_drvinfo = be_get_drvinfo,
-	.get_link = ethtool_op_get_link,
-	.get_coalesce = be_get_coalesce,
-	.set_coalesce = be_set_coalesce,
-	.get_ringparam = be_get_ringparam,
-	.get_pauseparam = be_get_pauseparam,
-	.set_pauseparam = be_set_pauseparam,
-	.get_rx_csum = be_get_rx_csum,
-	.set_rx_csum = be_set_rx_csum,
-	.get_tx_csum = ethtool_op_get_tx_csum,
-	.set_tx_csum = ethtool_op_set_tx_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 = be_get_strings,
-	.get_stats_count = be_get_stats_count,
-	.get_ethtool_stats = be_get_ethtool_stats,
-};
diff --git a/drivers/staging/benet/be_init.c b/drivers/staging/benet/be_init.c
deleted file mode 100644
index 12a026c..0000000
--- a/drivers/staging/benet/be_init.c
+++ /dev/null
@@ -1,1382 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#include <linux/etherdevice.h>
-#include "benet.h"
-
-#define  DRVR_VERSION  "1.0.728"
-
-static const struct pci_device_id be_device_id_table[] = {
-	{PCI_DEVICE(0x19a2, 0x0201)},
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, be_device_id_table);
-
-MODULE_VERSION(DRVR_VERSION);
-
-#define DRV_DESCRIPTION "ServerEngines BladeEngine Network Driver Version "
-
-MODULE_DESCRIPTION(DRV_DESCRIPTION DRVR_VERSION);
-MODULE_AUTHOR("ServerEngines");
-MODULE_LICENSE("GPL");
-
-static unsigned int msix = 1;
-module_param(msix, uint, S_IRUGO);
-MODULE_PARM_DESC(msix, "Use MSI-x interrupts");
-
-static unsigned int rxbuf_size = 2048;	/* Default RX frag size */
-module_param(rxbuf_size, uint, S_IRUGO);
-MODULE_PARM_DESC(rxbuf_size, "Size of buffers to hold Rx data");
-
-const char be_drvr_ver[] = DRVR_VERSION;
-char be_fw_ver[32];		/* F/W version filled in by be_probe */
-char be_driver_name[] = "benet";
-
-/*
- * Number of entries in each queue.
- */
-#define EVENT_Q_LEN		1024
-#define ETH_TXQ_LEN		2048
-#define ETH_TXCQ_LEN		1024
-#define ETH_RXQ_LEN		1024	/* Does not support any other value */
-#define ETH_UC_RXCQ_LEN		1024
-#define ETH_BC_RXCQ_LEN		256
-#define MCC_Q_LEN               64	/* total size not to exceed 8 pages */
-#define MCC_CQ_LEN              256
-
-/* Bit mask describing events of interest to be traced */
-unsigned int trace_level;
-
-static int
-init_pci_be_function(struct be_adapter *adapter, struct pci_dev *pdev)
-{
-	u64 pa;
-
-	/* CSR */
-	pa = pci_resource_start(pdev, 2);
-	adapter->csr_va = ioremap_nocache(pa, pci_resource_len(pdev, 2));
-	if (adapter->csr_va == NULL)
-		return -ENOMEM;
-
-	/* Door Bell */
-	pa = pci_resource_start(pdev, 4);
-	adapter->db_va = ioremap_nocache(pa, (128 * 1024));
-	if (adapter->db_va == NULL) {
-		iounmap(adapter->csr_va);
-		return -ENOMEM;
-	}
-
-	/* PCI */
-	pa = pci_resource_start(pdev, 1);
-	adapter->pci_va = ioremap_nocache(pa, pci_resource_len(pdev, 1));
-	if (adapter->pci_va == NULL) {
-		iounmap(adapter->csr_va);
-		iounmap(adapter->db_va);
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-/*
-   This function enables the interrupt corresponding to the Event
-   queue ID for the given NetObject
-*/
-void be_enable_eq_intr(struct be_net_object *pnob)
-{
-	struct CQ_DB_AMAP cqdb;
-	cqdb.dw[0] = 0;
-	AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1);
-	AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 1);
-	AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0);
-	AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id);
-	PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]);
-}
-
-/*
-   This function disables the interrupt corresponding to the Event
-   queue ID for the given NetObject
-*/
-void be_disable_eq_intr(struct be_net_object *pnob)
-{
-	struct CQ_DB_AMAP cqdb;
-	cqdb.dw[0] = 0;
-	AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1);
-	AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 0);
-	AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0);
-	AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id);
-	PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]);
-}
-
-/*
-    This function enables the interrupt from the  network function
-    of the BladeEngine. Use the function be_disable_eq_intr()
-    to enable the interrupt from the event queue of only one specific
-    NetObject
-*/
-void be_enable_intr(struct be_net_object *pnob)
-{
-	struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl;
-	u32 host_intr;
-
-	ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl);
-	host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR,
-							hostintr, ctrl.dw);
-	if (!host_intr) {
-		AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR,
-			hostintr, ctrl.dw, 1);
-		PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl,
-			ctrl.dw[0]);
-	}
-}
-
-/*
-   This function disables the interrupt from the network function of
-   the BladeEngine.  Use the function be_disable_eq_intr() to
-   disable the interrupt from the event queue of only one specific NetObject
-*/
-void be_disable_intr(struct be_net_object *pnob)
-{
-
-	struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl;
-	u32 host_intr;
-	ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl);
-	host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR,
-							hostintr, ctrl.dw);
-	if (host_intr) {
-		AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, hostintr,
-			ctrl.dw, 0);
-		PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl,
-			ctrl.dw[0]);
-	}
-}
-
-static int be_enable_msix(struct be_adapter *adapter)
-{
-	int i, ret;
-
-	if (!msix)
-		return -1;
-
-	for (i = 0; i < BE_MAX_REQ_MSIX_VECTORS; i++)
-		adapter->msix_entries[i].entry = i;
-
-	ret = pci_enable_msix(adapter->pdev, adapter->msix_entries,
-		BE_MAX_REQ_MSIX_VECTORS);
-
-	if (ret == 0)
-		adapter->msix_enabled = 1;
-	return ret;
-}
-
-static int be_register_isr(struct be_adapter *adapter,
-		struct be_net_object *pnob)
-{
-	struct net_device *netdev = pnob->netdev;
-	int intx = 0, r;
-
-	netdev->irq = adapter->pdev->irq;
-	r = be_enable_msix(adapter);
-
-	if (r == 0) {
-		r = request_irq(adapter->msix_entries[0].vector,
-				be_int, IRQF_SHARED, netdev->name, netdev);
-		if (r) {
-			printk(KERN_WARNING
-				"MSIX Request IRQ failed - Errno %d\n", r);
-			intx = 1;
-			pci_disable_msix(adapter->pdev);
-			adapter->msix_enabled = 0;
-		}
-	} else {
-		intx = 1;
-	}
-
-	if (intx) {
-		r = request_irq(netdev->irq, be_int, IRQF_SHARED,
-				netdev->name, netdev);
-		if (r) {
-			printk(KERN_WARNING
-				"INTx Request IRQ failed - Errno %d\n", r);
-			return -1;
-		}
-	}
-	adapter->isr_registered = 1;
-	return 0;
-}
-
-static void be_unregister_isr(struct be_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdevp;
-	if (adapter->isr_registered) {
-		if (adapter->msix_enabled) {
-			free_irq(adapter->msix_entries[0].vector, netdev);
-			pci_disable_msix(adapter->pdev);
-			adapter->msix_enabled = 0;
-		} else {
-			free_irq(netdev->irq, netdev);
-		}
-		adapter->isr_registered = 0;
-	}
-}
-
-/*
-    This function processes the Flush Completions that are issued by the
-    ARM F/W, when a Recv Ring is destroyed.  A flush completion is
-    identified when a Rx COmpl descriptor has the tcpcksum and udpcksum
-    set and the pktsize is 32.  These completions are received on the
-    Rx Completion Queue.
-*/
-static u32 be_process_rx_flush_cmpl(struct be_net_object *pnob)
-{
-	struct ETH_RX_COMPL_AMAP *rxcp;
-	unsigned int i = 0;
-	while ((rxcp = be_get_rx_cmpl(pnob)) != NULL) {
-		be_notify_cmpl(pnob, 1, pnob->rx_cq_id, 1);
-		i++;
-	}
-	return i;
-}
-
-static void be_tx_q_clean(struct be_net_object *pnob)
-{
-	while (atomic_read(&pnob->tx_q_used))
-		process_one_tx_compl(pnob, tx_compl_lastwrb_idx_get(pnob));
-}
-
-static void be_rx_q_clean(struct be_net_object *pnob)
-{
-	if (pnob->rx_ctxt) {
-		int i;
-		struct be_rx_page_info *rx_page_info;
-		for (i = 0; i < pnob->rx_q_len; i++) {
-			rx_page_info = &(pnob->rx_page_info[i]);
-			if (!pnob->rx_pg_shared || rx_page_info->page_offset) {
-				pci_unmap_page(pnob->adapter->pdev,
-				       pci_unmap_addr(rx_page_info, bus),
-					       pnob->rx_buf_size,
-					       PCI_DMA_FROMDEVICE);
-			}
-			if (rx_page_info->page)
-				put_page(rx_page_info->page);
-			memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
-		}
-		pnob->rx_pg_info_hd = 0;
-	}
-}
-
-static void be_destroy_netobj(struct be_net_object *pnob)
-{
-	int status;
-
-	if (pnob->tx_q_created) {
-		status = be_eth_sq_destroy(&pnob->tx_q_obj);
-		pnob->tx_q_created = 0;
-	}
-
-	if (pnob->rx_q_created) {
-		status = be_eth_rq_destroy(&pnob->rx_q_obj);
-		if (status != 0) {
-			status = be_eth_rq_destroy_options(&pnob->rx_q_obj, 0,
-						      NULL, NULL);
-			BUG_ON(status);
-		}
-		pnob->rx_q_created = 0;
-	}
-
-	be_process_rx_flush_cmpl(pnob);
-
-	if (pnob->tx_cq_created) {
-		status = be_cq_destroy(&pnob->tx_cq_obj);
-		pnob->tx_cq_created = 0;
-	}
-
-	if (pnob->rx_cq_created) {
-		status = be_cq_destroy(&pnob->rx_cq_obj);
-		pnob->rx_cq_created = 0;
-	}
-
-	if (pnob->mcc_q_created) {
-		status = be_mcc_ring_destroy(&pnob->mcc_q_obj);
-		pnob->mcc_q_created = 0;
-	}
-	if (pnob->mcc_cq_created) {
-		status = be_cq_destroy(&pnob->mcc_cq_obj);
-		pnob->mcc_cq_created = 0;
-	}
-
-	if (pnob->event_q_created) {
-		status = be_eq_destroy(&pnob->event_q_obj);
-		pnob->event_q_created = 0;
-	}
-	be_function_cleanup(&pnob->fn_obj);
-}
-
-/*
- * free all resources associated with a pnob
- * Called at the time of module cleanup as well a any error during
- * module init.  Some resources may be partially allocated in a NetObj.
- */
-static void netobject_cleanup(struct be_adapter *adapter,
-			struct be_net_object *pnob)
-{
-	struct net_device *netdev = adapter->netdevp;
-
-	if (netif_running(netdev)) {
-		netif_stop_queue(netdev);
-		be_wait_nic_tx_cmplx_cmpl(pnob);
-		be_disable_eq_intr(pnob);
-	}
-
-	be_unregister_isr(adapter);
-
-	if (adapter->tasklet_started) {
-		tasklet_kill(&(adapter->sts_handler));
-		adapter->tasklet_started = 0;
-	}
-	if (pnob->fn_obj_created)
-		be_disable_intr(pnob);
-
-	if (adapter->dev_state != BE_DEV_STATE_NONE)
-		unregister_netdev(netdev);
-
-	if (pnob->fn_obj_created)
-		be_destroy_netobj(pnob);
-
-	adapter->net_obj = NULL;
-	adapter->netdevp = NULL;
-
-	be_rx_q_clean(pnob);
-	if (pnob->rx_ctxt) {
-		kfree(pnob->rx_page_info);
-		kfree(pnob->rx_ctxt);
-	}
-
-	be_tx_q_clean(pnob);
-	kfree(pnob->tx_ctxt);
-
-	if (pnob->mcc_q)
-		pci_free_consistent(adapter->pdev, pnob->mcc_q_size,
-			pnob->mcc_q, pnob->mcc_q_bus);
-
-	if (pnob->mcc_wrb_ctxt)
-		free_pages((unsigned long)pnob->mcc_wrb_ctxt,
-			   get_order(pnob->mcc_wrb_ctxt_size));
-
-	if (pnob->mcc_cq)
-		pci_free_consistent(adapter->pdev, pnob->mcc_cq_size,
-			pnob->mcc_cq, pnob->mcc_cq_bus);
-
-	if (pnob->event_q)
-		pci_free_consistent(adapter->pdev, pnob->event_q_size,
-			pnob->event_q, pnob->event_q_bus);
-
-	if (pnob->tx_cq)
-		pci_free_consistent(adapter->pdev, pnob->tx_cq_size,
-			pnob->tx_cq, pnob->tx_cq_bus);
-
-	if (pnob->tx_q)
-		pci_free_consistent(adapter->pdev, pnob->tx_q_size,
-			pnob->tx_q, pnob->tx_q_bus);
-
-	if (pnob->rx_q)
-		pci_free_consistent(adapter->pdev, pnob->rx_q_size,
-			pnob->rx_q, pnob->rx_q_bus);
-
-	if (pnob->rx_cq)
-		pci_free_consistent(adapter->pdev, pnob->rx_cq_size,
-			pnob->rx_cq, pnob->rx_cq_bus);
-
-
-	if (pnob->mb_ptr)
-		pci_free_consistent(adapter->pdev, pnob->mb_size, pnob->mb_ptr,
-			pnob->mb_bus);
-
-	free_netdev(netdev);
-}
-
-
-static int be_nob_ring_alloc(struct be_adapter *adapter,
-	struct be_net_object *pnob)
-{
-	u32 size;
-
-	/* Mail box rd; mailbox pointer needs to be 16 byte aligned */
-	pnob->mb_size = sizeof(struct MCC_MAILBOX_AMAP) + 16;
-	pnob->mb_ptr = pci_alloc_consistent(adapter->pdev, pnob->mb_size,
-				&pnob->mb_bus);
-	if (!pnob->mb_bus)
-		return -1;
-	memset(pnob->mb_ptr, 0, pnob->mb_size);
-	pnob->mb_rd.va = PTR_ALIGN(pnob->mb_ptr, 16);
-	pnob->mb_rd.pa = PTR_ALIGN(pnob->mb_bus, 16);
-	pnob->mb_rd.length = sizeof(struct MCC_MAILBOX_AMAP);
-	/*
-	 * Event queue
-	 */
-	pnob->event_q_len = EVENT_Q_LEN;
-	pnob->event_q_size = pnob->event_q_len * sizeof(struct EQ_ENTRY_AMAP);
-	pnob->event_q = pci_alloc_consistent(adapter->pdev, pnob->event_q_size,
-				&pnob->event_q_bus);
-	if (!pnob->event_q_bus)
-		return -1;
-	memset(pnob->event_q, 0, pnob->event_q_size);
-	/*
-	 * Eth TX queue
-	 */
-	pnob->tx_q_len = ETH_TXQ_LEN;
-	pnob->tx_q_port = 0;
-	pnob->tx_q_size =  pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP);
-	pnob->tx_q = pci_alloc_consistent(adapter->pdev, pnob->tx_q_size,
-				&pnob->tx_q_bus);
-	if (!pnob->tx_q_bus)
-		return -1;
-	memset(pnob->tx_q, 0, pnob->tx_q_size);
-	/*
-	 * Eth TX Compl queue
-	 */
-	pnob->txcq_len = ETH_TXCQ_LEN;
-	pnob->tx_cq_size = pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP);
-	pnob->tx_cq = pci_alloc_consistent(adapter->pdev, pnob->tx_cq_size,
-				&pnob->tx_cq_bus);
-	if (!pnob->tx_cq_bus)
-		return -1;
-	memset(pnob->tx_cq, 0, pnob->tx_cq_size);
-	/*
-	 * Eth RX queue
-	 */
-	pnob->rx_q_len = ETH_RXQ_LEN;
-	pnob->rx_q_size =  pnob->rx_q_len * sizeof(struct ETH_RX_D_AMAP);
-	pnob->rx_q = pci_alloc_consistent(adapter->pdev, pnob->rx_q_size,
-				&pnob->rx_q_bus);
-	if (!pnob->rx_q_bus)
-		return -1;
-	memset(pnob->rx_q, 0, pnob->rx_q_size);
-	/*
-	 * Eth Unicast RX Compl queue
-	 */
-	pnob->rx_cq_len = ETH_UC_RXCQ_LEN;
-	pnob->rx_cq_size =  pnob->rx_cq_len *
-			sizeof(struct ETH_RX_COMPL_AMAP);
-	pnob->rx_cq = pci_alloc_consistent(adapter->pdev, pnob->rx_cq_size,
-				&pnob->rx_cq_bus);
-	if (!pnob->rx_cq_bus)
-		return -1;
-	memset(pnob->rx_cq, 0, pnob->rx_cq_size);
-
-	/* TX resources */
-	size = pnob->tx_q_len * sizeof(void **);
-	pnob->tx_ctxt = kzalloc(size, GFP_KERNEL);
-	if (pnob->tx_ctxt == NULL)
-		return -1;
-
-	/* RX resources */
-	size = pnob->rx_q_len * sizeof(void *);
-	pnob->rx_ctxt = kzalloc(size, GFP_KERNEL);
-	if (pnob->rx_ctxt == NULL)
-		return -1;
-
-	size = (pnob->rx_q_len * sizeof(struct be_rx_page_info));
-	pnob->rx_page_info = kzalloc(size, GFP_KERNEL);
-	if (pnob->rx_page_info == NULL)
-		return -1;
-
-	adapter->eth_statsp = kzalloc(sizeof(struct FWCMD_ETH_GET_STATISTICS),
-				GFP_KERNEL);
-	if (adapter->eth_statsp == NULL)
-		return -1;
-	pnob->rx_buf_size = rxbuf_size;
-	return 0;
-}
-
-/*
-    This function initializes the be_net_object for subsequent
-    network operations.
-
-    Before calling this function, the driver  must have allocated
-    space for the NetObject structure, initialized the structure,
-    allocated DMAable memory for all the network queues that form
-    part of the NetObject and populated the start address (virtual)
-    and number of entries allocated for each queue in the NetObject structure.
-
-    The driver must also have allocated memory to hold the
-    mailbox structure (MCC_MAILBOX) and post the physical address,
-    virtual addresses and the size of the mailbox memory in the
-    NetObj.mb_rd.  This structure is used by BECLIB for
-    initial communication with the embedded MCC processor. BECLIB
-    uses the mailbox until MCC rings are created for  more  efficient
-    communication with the MCC processor.
-
-    If the driver wants to create multiple network interface for more
-    than one protection domain, it can call be_create_netobj()
-    multiple times  once for each protection domain.  A Maximum of
-    32 protection domains are supported.
-
-*/
-static int
-be_create_netobj(struct be_net_object *pnob, u8 __iomem *csr_va,
-	u8 __iomem *db_va, u8 __iomem *pci_va)
-{
-	int status = 0;
-	bool  eventable = false, tx_no_delay = false, rx_no_delay = false;
-	struct be_eq_object *eq_objectp = NULL;
-	struct be_function_object *pfob = &pnob->fn_obj;
-	struct ring_desc rd;
-	u32 set_rxbuf_size;
-	u32 tx_cmpl_wm = CEV_WMARK_96;	/* 0xffffffff to disable */
-	u32 rx_cmpl_wm = CEV_WMARK_160;	/* 0xffffffff to disable */
-	u32 eq_delay = 0; /* delay in 8usec units. 0xffffffff to disable */
-
-	memset(&rd, 0, sizeof(struct ring_desc));
-
-	status = be_function_object_create(csr_va, db_va, pci_va,
-			BE_FUNCTION_TYPE_NETWORK, &pnob->mb_rd, pfob);
-	if (status != BE_SUCCESS)
-		return status;
-	pnob->fn_obj_created = true;
-
-	if (tx_cmpl_wm == 0xffffffff)
-		tx_no_delay = true;
-	if (rx_cmpl_wm == 0xffffffff)
-		rx_no_delay = true;
-	/*
-	 * now create the necessary rings
-	 * Event Queue first.
-	 */
-	if (pnob->event_q_len) {
-		rd.va = pnob->event_q;
-		rd.pa = pnob->event_q_bus;
-		rd.length = pnob->event_q_size;
-
-		status = be_eq_create(pfob, &rd, 4, pnob->event_q_len,
-				(u32) -1,	/* CEV_WMARK_* or -1 */
-				eq_delay,	/* in 8us units, or -1 */
-				&pnob->event_q_obj);
-		if (status != BE_SUCCESS)
-			goto error_ret;
-		pnob->event_q_id = pnob->event_q_obj.eq_id;
-		pnob->event_q_created = 1;
-		eventable = true;
-		eq_objectp = &pnob->event_q_obj;
-	}
-	/*
-	 * Now Eth Tx Compl. queue.
-	 */
-	if (pnob->txcq_len) {
-		rd.va = pnob->tx_cq;
-		rd.pa = pnob->tx_cq_bus;
-		rd.length = pnob->tx_cq_size;
-
-		status = be_cq_create(pfob, &rd,
-			pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP),
-			false,	/* solicted events,  */
-			tx_no_delay,	/* nodelay  */
-			tx_cmpl_wm,	/* Watermark encodings */
-			eq_objectp, &pnob->tx_cq_obj);
-		if (status != BE_SUCCESS)
-			goto error_ret;
-
-		pnob->tx_cq_id = pnob->tx_cq_obj.cq_id;
-		pnob->tx_cq_created = 1;
-	}
-	/*
-	 * Eth Tx queue
-	 */
-	if (pnob->tx_q_len) {
-		struct be_eth_sq_parameters ex_params = { 0 };
-		u32 type;
-
-		if (pnob->tx_q_port) {
-			/* TXQ to be bound to a specific port */
-			type = BE_ETH_TX_RING_TYPE_BOUND;
-			ex_params.port = pnob->tx_q_port - 1;
-		} else
-			type = BE_ETH_TX_RING_TYPE_STANDARD;
-
-		rd.va = pnob->tx_q;
-		rd.pa = pnob->tx_q_bus;
-		rd.length = pnob->tx_q_size;
-
-		status = be_eth_sq_create_ex(pfob, &rd,
-				pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP),
-				type, 2, &pnob->tx_cq_obj,
-				&ex_params, &pnob->tx_q_obj);
-
-		if (status != BE_SUCCESS)
-			goto error_ret;
-
-		pnob->tx_q_id = pnob->tx_q_obj.bid;
-		pnob->tx_q_created = 1;
-	}
-	/*
-	 * Now Eth Rx compl. queue.  Always needed.
-	 */
-	rd.va = pnob->rx_cq;
-	rd.pa = pnob->rx_cq_bus;
-	rd.length = pnob->rx_cq_size;
-
-	status = be_cq_create(pfob, &rd,
-			pnob->rx_cq_len * sizeof(struct ETH_RX_COMPL_AMAP),
-			false,	/* solicted events,  */
-			rx_no_delay,	/* nodelay  */
-			rx_cmpl_wm,	/* Watermark encodings */
-			eq_objectp, &pnob->rx_cq_obj);
-	if (status != BE_SUCCESS)
-		goto error_ret;
-
-	pnob->rx_cq_id = pnob->rx_cq_obj.cq_id;
-	pnob->rx_cq_created = 1;
-
-	status = be_eth_rq_set_frag_size(pfob, pnob->rx_buf_size,
-			(u32 *) &set_rxbuf_size);
-	if (status != BE_SUCCESS) {
-		be_eth_rq_get_frag_size(pfob, (u32 *) &pnob->rx_buf_size);
-		if ((pnob->rx_buf_size != 2048) && (pnob->rx_buf_size != 4096)
-		    && (pnob->rx_buf_size != 8192))
-			goto error_ret;
-	} else {
-		if (pnob->rx_buf_size != set_rxbuf_size)
-			pnob->rx_buf_size = set_rxbuf_size;
-	}
-	/*
-	 * Eth RX queue. be_eth_rq_create() always assumes 2 pages size
-	 */
-	rd.va = pnob->rx_q;
-	rd.pa = pnob->rx_q_bus;
-	rd.length = pnob->rx_q_size;
-
-	status = be_eth_rq_create(pfob, &rd, &pnob->rx_cq_obj,
-			     &pnob->rx_cq_obj, &pnob->rx_q_obj);
-
-	if (status != BE_SUCCESS)
-		goto error_ret;
-
-	pnob->rx_q_id = pnob->rx_q_obj.rid;
-	pnob->rx_q_created = 1;
-
-	return BE_SUCCESS;	/* All required queues created. */
-
-error_ret:
-	be_destroy_netobj(pnob);
-	return status;
-}
-
-static int be_nob_ring_init(struct be_adapter *adapter,
-				struct be_net_object *pnob)
-{
-	int status;
-
-	pnob->event_q_tl = 0;
-
-	pnob->tx_q_hd = 0;
-	pnob->tx_q_tl = 0;
-
-	pnob->tx_cq_tl = 0;
-
-	pnob->rx_cq_tl = 0;
-
-	memset(pnob->event_q, 0, pnob->event_q_size);
-	memset(pnob->tx_cq, 0, pnob->tx_cq_size);
-	memset(pnob->tx_ctxt, 0, pnob->tx_q_len * sizeof(void **));
-	memset(pnob->rx_ctxt, 0, pnob->rx_q_len * sizeof(void *));
-	pnob->rx_pg_info_hd = 0;
-	pnob->rx_q_hd = 0;
-	atomic_set(&pnob->rx_q_posted, 0);
-
-	status = be_create_netobj(pnob, adapter->csr_va, adapter->db_va,
-				adapter->pci_va);
-	if (status != BE_SUCCESS)
-		return -1;
-
-	be_post_eth_rx_buffs(pnob);
-	return 0;
-}
-
-/* This function handles async callback for link status */
-static void
-be_link_status_async_callback(void *context, u32 event_code, void *event)
-{
-	struct ASYNC_EVENT_LINK_STATE_AMAP *link_status = event;
-	struct be_adapter *adapter = context;
-	bool link_enable = false;
-	struct be_net_object *pnob;
-	struct ASYNC_EVENT_TRAILER_AMAP *async_trailer;
-	struct net_device *netdev;
-	u32 async_event_code, async_event_type, active_port;
-	u32 port0_link_status, port1_link_status, port0_duplex, port1_duplex;
-	u32 port0_speed, port1_speed;
-
-	if (event_code != ASYNC_EVENT_CODE_LINK_STATE) {
-		/* Not our event to handle */
-		return;
-	}
-	async_trailer = (struct ASYNC_EVENT_TRAILER_AMAP *)
-	    ((u8 *) event + sizeof(struct MCC_CQ_ENTRY_AMAP) -
-	     sizeof(struct ASYNC_EVENT_TRAILER_AMAP));
-
-	async_event_code = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_code,
-					     async_trailer);
-	BUG_ON(async_event_code != ASYNC_EVENT_CODE_LINK_STATE);
-
-	pnob = adapter->net_obj;
-	netdev = pnob->netdev;
-
-	/* Determine if this event is a switch VLD or a physical link event */
-	async_event_type = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_type,
-					     async_trailer);
-	active_port = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
-					active_port, link_status);
-	port0_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
-					      port0_link_status, link_status);
-	port1_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
-					      port1_link_status, link_status);
-	port0_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
-					 port0_duplex, link_status);
-	port1_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
-					 port1_duplex, link_status);
-	port0_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
-					port0_speed, link_status);
-	port1_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
-					port1_speed, link_status);
-	if (async_event_type == NTWK_LINK_TYPE_VIRTUAL) {
-		adapter->be_stat.bes_link_change_virtual++;
-		if (adapter->be_link_sts->active_port != active_port) {
-			dev_notice(&netdev->dev,
-			       "Active port changed due to VLD on switch\n");
-		} else {
-			dev_notice(&netdev->dev, "Link status update\n");
-		}
-
-	} else {
-		adapter->be_stat.bes_link_change_physical++;
-		if (adapter->be_link_sts->active_port != active_port) {
-			dev_notice(&netdev->dev,
-			       "Active port changed due to port link"
-			       " status change\n");
-		} else {
-			dev_notice(&netdev->dev, "Link status update\n");
-		}
-	}
-
-	memset(adapter->be_link_sts, 0, sizeof(adapter->be_link_sts));
-
-	if ((port0_link_status == ASYNC_EVENT_LINK_UP) ||
-	    (port1_link_status == ASYNC_EVENT_LINK_UP)) {
-		if ((adapter->port0_link_sts == BE_PORT_LINK_DOWN) &&
-		    (adapter->port1_link_sts == BE_PORT_LINK_DOWN)) {
-			/* Earlier both the ports are down So link is up */
-			link_enable = true;
-		}
-
-		if (port0_link_status == ASYNC_EVENT_LINK_UP) {
-			adapter->port0_link_sts = BE_PORT_LINK_UP;
-			adapter->be_link_sts->mac0_duplex = port0_duplex;
-			adapter->be_link_sts->mac0_speed = port0_speed;
-			if (active_port == NTWK_PORT_A)
-				adapter->be_link_sts->active_port = 0;
-		} else
-			adapter->port0_link_sts = BE_PORT_LINK_DOWN;
-
-		if (port1_link_status == ASYNC_EVENT_LINK_UP) {
-			adapter->port1_link_sts = BE_PORT_LINK_UP;
-			adapter->be_link_sts->mac1_duplex = port1_duplex;
-			adapter->be_link_sts->mac1_speed = port1_speed;
-			if (active_port == NTWK_PORT_B)
-				adapter->be_link_sts->active_port = 1;
-		} else
-			adapter->port1_link_sts = BE_PORT_LINK_DOWN;
-
-		printk(KERN_INFO "Link Properties for %s:\n", netdev->name);
-		dev_info(&netdev->dev, "Link Properties:\n");
-		be_print_link_info(adapter->be_link_sts);
-
-		if (!link_enable)
-			return;
-		/*
-		 * Both ports were down previously, but atleast one of
-		 * them has come up if this netdevice's carrier is not up,
-		 * then indicate to stack
-		 */
-		if (!netif_carrier_ok(netdev)) {
-			netif_start_queue(netdev);
-			netif_carrier_on(netdev);
-		}
-		return;
-	}
-
-	/* Now both the ports are down. Tell the stack about it */
-	dev_info(&netdev->dev, "Both ports are down\n");
-	adapter->port0_link_sts = BE_PORT_LINK_DOWN;
-	adapter->port1_link_sts = BE_PORT_LINK_DOWN;
-	if (netif_carrier_ok(netdev)) {
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-	}
-	return;
-}
-
-static int be_mcc_create(struct be_adapter *adapter)
-{
-	struct be_net_object *pnob;
-
-	pnob = adapter->net_obj;
-	/*
-	 * Create the MCC ring so that all further communication with
-	 * MCC can go thru the ring. we do this at the end since
-	 * we do not want to be dealing with interrupts until the
-	 * initialization is complete.
-	 */
-	pnob->mcc_q_len = MCC_Q_LEN;
-	pnob->mcc_q_size = pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP);
-	pnob->mcc_q =  pci_alloc_consistent(adapter->pdev, pnob->mcc_q_size,
-				&pnob->mcc_q_bus);
-	if (!pnob->mcc_q_bus)
-		return -1;
-	/*
-	 * space for MCC WRB context
-	 */
-	pnob->mcc_wrb_ctxtLen = MCC_Q_LEN;
-	pnob->mcc_wrb_ctxt_size =  pnob->mcc_wrb_ctxtLen *
-		sizeof(struct be_mcc_wrb_context);
-	pnob->mcc_wrb_ctxt = (void *)__get_free_pages(GFP_KERNEL,
-		get_order(pnob->mcc_wrb_ctxt_size));
-	if (pnob->mcc_wrb_ctxt == NULL)
-		return -1;
-	/*
-	 * Space for MCC compl. ring
-	 */
-	pnob->mcc_cq_len = MCC_CQ_LEN;
-	pnob->mcc_cq_size = pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP);
-	pnob->mcc_cq = pci_alloc_consistent(adapter->pdev, pnob->mcc_cq_size,
-				&pnob->mcc_cq_bus);
-	if (!pnob->mcc_cq_bus)
-		return -1;
-	return 0;
-}
-
-/*
-    This function creates the MCC request and completion ring required
-    for communicating with the ARM processor.  The caller must have
-    allocated required amount of memory for the MCC ring and MCC
-    completion ring and posted the virtual address and number of
-    entries in the corresponding members (mcc_q and mcc_cq) in the
-    NetObject struture.
-
-    When this call is completed, all further communication with
-    ARM will switch from mailbox to this ring.
-
-    pnob	- Pointer to the NetObject structure. This NetObject should
-		  have been created using a previous call to be_create_netobj()
-*/
-int be_create_mcc_rings(struct be_net_object *pnob)
-{
-	int status = 0;
-	struct ring_desc rd;
-	struct be_function_object *pfob = &pnob->fn_obj;
-
-	memset(&rd, 0, sizeof(struct ring_desc));
-	if (pnob->mcc_cq_len) {
-		rd.va = pnob->mcc_cq;
-		rd.pa = pnob->mcc_cq_bus;
-		rd.length = pnob->mcc_cq_size;
-
-		status = be_cq_create(pfob, &rd,
-			pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP),
-			false,	/* solicted events,  */
-			true,	/* nodelay  */
-			0,	/* 0 Watermark since Nodelay is true */
-			&pnob->event_q_obj,
-			&pnob->mcc_cq_obj);
-
-		if (status != BE_SUCCESS)
-			return status;
-
-		pnob->mcc_cq_id = pnob->mcc_cq_obj.cq_id;
-		pnob->mcc_cq_created = 1;
-	}
-	if (pnob->mcc_q_len) {
-		rd.va = pnob->mcc_q;
-		rd.pa = pnob->mcc_q_bus;
-		rd.length = pnob->mcc_q_size;
-
-		status = be_mcc_ring_create(pfob, &rd,
-				pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP),
-				pnob->mcc_wrb_ctxt, pnob->mcc_wrb_ctxtLen,
-				&pnob->mcc_cq_obj, &pnob->mcc_q_obj);
-
-		if (status != BE_SUCCESS)
-			return status;
-
-		pnob->mcc_q_created = 1;
-	}
-	return BE_SUCCESS;
-}
-
-static int be_mcc_init(struct be_adapter *adapter)
-{
-	u32 r;
-	struct be_net_object *pnob;
-
-	pnob = adapter->net_obj;
-	memset(pnob->mcc_q, 0, pnob->mcc_q_size);
-	pnob->mcc_q_hd = 0;
-
-	memset(pnob->mcc_wrb_ctxt, 0, pnob->mcc_wrb_ctxt_size);
-
-	memset(pnob->mcc_cq, 0, pnob->mcc_cq_size);
-	pnob->mcc_cq_tl = 0;
-
-	r = be_create_mcc_rings(adapter->net_obj);
-	if (r != BE_SUCCESS)
-		return -1;
-
-	return 0;
-}
-
-static void be_remove(struct pci_dev *pdev)
-{
-	struct be_net_object *pnob;
-	struct be_adapter *adapter;
-
-	adapter = pci_get_drvdata(pdev);
-	if (!adapter)
-		return;
-
-	pci_set_drvdata(pdev, NULL);
-	pnob = (struct be_net_object *)adapter->net_obj;
-
-	flush_scheduled_work();
-
-	if (pnob) {
-		/* Unregister async callback function for link status updates */
-		if (pnob->mcc_q_created)
-			be_mcc_add_async_event_callback(&pnob->mcc_q_obj,
-								NULL, NULL);
-		netobject_cleanup(adapter, pnob);
-	}
-
-	if (adapter->csr_va)
-		iounmap(adapter->csr_va);
-	if (adapter->db_va)
-		iounmap(adapter->db_va);
-	if (adapter->pci_va)
-		iounmap(adapter->pci_va);
-
-	pci_release_regions(adapter->pdev);
-	pci_disable_device(adapter->pdev);
-
-	kfree(adapter->be_link_sts);
-	kfree(adapter->eth_statsp);
-
-	if (adapter->timer_ctxt.get_stats_timer.function)
-		del_timer_sync(&adapter->timer_ctxt.get_stats_timer);
-	kfree(adapter);
-}
-
-/*
- * This function is called by the PCI sub-system when it finds a PCI
- * device with dev/vendor IDs that match with one of our devices.
- * All of the driver initialization is done in this function.
- */
-static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
-{
-	int status = 0;
-	struct be_adapter *adapter;
-	struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD get_fwv;
-	struct be_net_object *pnob;
-	struct net_device *netdev;
-
-	status = pci_enable_device(pdev);
-	if (status)
-		goto error;
-
-	status = pci_request_regions(pdev, be_driver_name);
-	if (status)
-		goto error_pci_req;
-
-	pci_set_master(pdev);
-	adapter = kzalloc(sizeof(struct be_adapter), GFP_KERNEL);
-	if (adapter == NULL) {
-		status = -ENOMEM;
-		goto error_adapter;
-	}
-	adapter->dev_state = BE_DEV_STATE_NONE;
-	adapter->pdev = pdev;
-	pci_set_drvdata(pdev, adapter);
-
-	adapter->enable_aic = 1;
-	adapter->max_eqd = MAX_EQD;
-	adapter->min_eqd = 0;
-	adapter->cur_eqd = 0;
-
-	status = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
-	if (!status) {
-		adapter->dma_64bit_cap = true;
-	} else {
-		adapter->dma_64bit_cap = false;
-		status = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-		if (status != 0) {
-			printk(KERN_ERR "Could not set PCI DMA Mask\n");
-			goto cleanup;
-		}
-	}
-
-	status = init_pci_be_function(adapter, pdev);
-	if (status != 0) {
-		printk(KERN_ERR "Failed to map PCI BARS\n");
-		status = -ENOMEM;
-		goto cleanup;
-	}
-
-	be_trace_set_level(DL_ALWAYS | DL_ERR);
-
-	adapter->be_link_sts = kmalloc(sizeof(struct BE_LINK_STATUS),
-					GFP_KERNEL);
-	if (adapter->be_link_sts == NULL) {
-		printk(KERN_ERR "Memory allocation for link status "
-		       "buffer failed\n");
-		goto cleanup;
-	}
-	spin_lock_init(&adapter->txq_lock);
-
-	netdev = alloc_etherdev(sizeof(struct be_net_object));
-	if (netdev == NULL) {
-		status = -ENOMEM;
-		goto cleanup;
-	}
-	pnob = netdev_priv(netdev);
-	adapter->net_obj = pnob;
-	adapter->netdevp = netdev;
-	pnob->adapter = adapter;
-	pnob->netdev = netdev;
-
-	status = be_nob_ring_alloc(adapter, pnob);
-	if (status != 0)
-		goto cleanup;
-
-	status = be_nob_ring_init(adapter, pnob);
-	if (status != 0)
-		goto cleanup;
-
-	be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, false,
-		false, false, netdev->dev_addr, NULL, NULL);
-
-	netdev->init = &benet_init;
-	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
-
-	SET_NETDEV_DEV(netdev, &(adapter->pdev->dev));
-
-	netif_napi_add(netdev, &pnob->napi, be_poll, 64);
-
-	/* if the rx_frag size if 2K, one page is shared as two RX frags */
-	pnob->rx_pg_shared =
-		(pnob->rx_buf_size <= PAGE_SIZE / 2) ? true : false;
-	if (pnob->rx_buf_size != rxbuf_size) {
-		printk(KERN_WARNING
-		       "Could not set Rx buffer size to %d. Using %d\n",
-				       rxbuf_size, pnob->rx_buf_size);
-		rxbuf_size = pnob->rx_buf_size;
-	}
-
-	tasklet_init(&(adapter->sts_handler), be_process_intr,
-		     (unsigned long)adapter);
-	adapter->tasklet_started = 1;
-	spin_lock_init(&(adapter->int_lock));
-
-	status = be_register_isr(adapter, pnob);
-	if (status != 0)
-		goto cleanup;
-
-	adapter->rx_csum = 1;
-	adapter->max_rx_coal = BE_LRO_MAX_PKTS;
-
-	memset(&get_fwv, 0,
-	       sizeof(struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD));
-	printk(KERN_INFO "BladeEngine Driver version:%s. "
-	       "Copyright ServerEngines, Corporation 2005 - 2008\n",
-			       be_drvr_ver);
-	status = be_function_get_fw_version(&pnob->fn_obj, &get_fwv, NULL,
-					    NULL);
-	if (status == BE_SUCCESS) {
-		strncpy(be_fw_ver, get_fwv.firmware_version_string, 32);
-		printk(KERN_INFO "BladeEngine Firmware Version:%s\n",
-		       get_fwv.firmware_version_string);
-	} else {
-		printk(KERN_WARNING "Unable to get BE Firmware Version\n");
-	}
-
-	sema_init(&adapter->get_eth_stat_sem, 0);
-	init_timer(&adapter->timer_ctxt.get_stats_timer);
-	atomic_set(&adapter->timer_ctxt.get_stat_flag, 0);
-	adapter->timer_ctxt.get_stats_timer.function =
-	    &be_get_stats_timer_handler;
-
-	status = be_mcc_create(adapter);
-	if (status < 0)
-		goto cleanup;
-	status = be_mcc_init(adapter);
-	if (status < 0)
-		goto cleanup;
-
-
-	status = be_mcc_add_async_event_callback(&adapter->net_obj->mcc_q_obj,
-			 be_link_status_async_callback, (void *)adapter);
-	if (status != BE_SUCCESS) {
-		printk(KERN_WARNING "add_async_event_callback failed");
-		printk(KERN_WARNING
-		       "Link status changes may not be reflected\n");
-	}
-
-	status = register_netdev(netdev);
-	if (status != 0)
-		goto cleanup;
-	be_update_link_status(adapter);
-	adapter->dev_state = BE_DEV_STATE_INIT;
-	return 0;
-
-cleanup:
-	be_remove(pdev);
-	return status;
-error_adapter:
-	pci_release_regions(pdev);
-error_pci_req:
-	pci_disable_device(pdev);
-error:
-	printk(KERN_ERR "BladeEngine initalization failed\n");
-	return status;
-}
-
-/*
- * Get the current link status and print the status on console
- */
-void be_update_link_status(struct be_adapter *adapter)
-{
-	int status;
-	struct be_net_object *pnob = adapter->net_obj;
-
-	status = be_rxf_link_status(&pnob->fn_obj, adapter->be_link_sts, NULL,
-			NULL, NULL);
-	if (status == BE_SUCCESS) {
-		if (adapter->be_link_sts->mac0_speed &&
-		    adapter->be_link_sts->mac0_duplex)
-			adapter->port0_link_sts = BE_PORT_LINK_UP;
-		else
-			adapter->port0_link_sts = BE_PORT_LINK_DOWN;
-
-		if (adapter->be_link_sts->mac1_speed &&
-		    adapter->be_link_sts->mac1_duplex)
-			adapter->port1_link_sts = BE_PORT_LINK_UP;
-		else
-			adapter->port1_link_sts = BE_PORT_LINK_DOWN;
-
-		dev_info(&pnob->netdev->dev, "Link Properties:\n");
-		be_print_link_info(adapter->be_link_sts);
-		return;
-	}
-	dev_info(&pnob->netdev->dev, "Could not get link status\n");
-	return;
-}
-
-
-#ifdef CONFIG_PM
-static void
-be_pm_cleanup(struct be_adapter *adapter,
-	      struct be_net_object *pnob, struct net_device *netdev)
-{
-	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
-
-	be_wait_nic_tx_cmplx_cmpl(pnob);
-	be_disable_eq_intr(pnob);
-
-	if (adapter->tasklet_started) {
-		tasklet_kill(&adapter->sts_handler);
-		adapter->tasklet_started = 0;
-	}
-
-	be_unregister_isr(adapter);
-	be_disable_intr(pnob);
-
-	be_tx_q_clean(pnob);
-	be_rx_q_clean(pnob);
-
-	be_destroy_netobj(pnob);
-}
-
-static int be_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct be_adapter *adapter = pci_get_drvdata(pdev);
-	struct net_device *netdev =  adapter->netdevp;
-	struct be_net_object *pnob = netdev_priv(netdev);
-
-	adapter->dev_pm_state = adapter->dev_state;
-	adapter->dev_state = BE_DEV_STATE_SUSPEND;
-
-	netif_device_detach(netdev);
-	if (netif_running(netdev))
-		be_pm_cleanup(adapter, pnob, netdev);
-
-	pci_enable_wake(pdev, 3, 1);
-	pci_enable_wake(pdev, 4, 1);	/* D3 Cold = 4 */
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-	return 0;
-}
-
-static void be_up(struct be_adapter *adapter)
-{
-	struct be_net_object *pnob = adapter->net_obj;
-
-	if (pnob->num_vlans != 0)
-		be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans,
-			pnob->vlan_tag, NULL, NULL, NULL);
-
-}
-
-static int be_resume(struct pci_dev *pdev)
-{
-	int status = 0;
-	struct be_adapter *adapter = pci_get_drvdata(pdev);
-	struct net_device *netdev =  adapter->netdevp;
-	struct be_net_object *pnob = netdev_priv(netdev);
-
-	netif_device_detach(netdev);
-
-	status = pci_enable_device(pdev);
-	if (status)
-		return status;
-
-	pci_set_power_state(pdev, 0);
-	pci_restore_state(pdev);
-	pci_enable_wake(pdev, 3, 0);
-	pci_enable_wake(pdev, 4, 0);	/* 4 is D3 cold */
-
-	netif_carrier_on(netdev);
-	netif_start_queue(netdev);
-
-	if (netif_running(netdev)) {
-		be_rxf_mac_address_read_write(&pnob->fn_obj, false, false,
-			false, true, false, netdev->dev_addr, NULL, NULL);
-
-		status = be_nob_ring_init(adapter, pnob);
-		if (status < 0)
-			return status;
-
-		tasklet_init(&(adapter->sts_handler), be_process_intr,
-			     (unsigned long)adapter);
-		adapter->tasklet_started = 1;
-
-		if (be_register_isr(adapter, pnob) != 0) {
-			printk(KERN_ERR "be_register_isr failed\n");
-			return status;
-		}
-
-
-		status = be_mcc_init(adapter);
-		if (status < 0) {
-			printk(KERN_ERR "be_mcc_init failed\n");
-			return status;
-		}
-		be_update_link_status(adapter);
-		/*
-		 * Register async call back function to handle link
-		 * status updates
-		 */
-		status = be_mcc_add_async_event_callback(
-				&adapter->net_obj->mcc_q_obj,
-				be_link_status_async_callback, (void *)adapter);
-		if (status != BE_SUCCESS) {
-			printk(KERN_WARNING "add_async_event_callback failed");
-			printk(KERN_WARNING
-			       "Link status changes may not be reflected\n");
-		}
-		be_enable_intr(pnob);
-		be_enable_eq_intr(pnob);
-		be_up(adapter);
-	}
-	netif_device_attach(netdev);
-	adapter->dev_state = adapter->dev_pm_state;
-	return 0;
-
-}
-
-#endif
-
-/* Wait until no more pending transmits  */
-void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *pnob)
-{
-	int i;
-
-	/* Wait for 20us * 50000 (= 1s) and no more */
-	i = 0;
-	while ((pnob->tx_q_tl != pnob->tx_q_hd) && (i < 50000)) {
-		++i;
-		udelay(20);
-	}
-
-	/* Check for no more pending transmits */
-	if (i >= 50000) {
-		printk(KERN_WARNING
-		       "Did not receive completions for all TX requests\n");
-	}
-}
-
-static struct pci_driver be_driver = {
-	.name = be_driver_name,
-	.id_table = be_device_id_table,
-	.probe = be_probe,
-#ifdef CONFIG_PM
-	.suspend = be_suspend,
-	.resume = be_resume,
-#endif
-	.remove = be_remove
-};
-
-/*
- * Module init entry point. Registers our our device and return.
- * Our probe will be called if the device is found.
- */
-static int __init be_init_module(void)
-{
-	int ret;
-
-	if (rxbuf_size != 8192 && rxbuf_size != 4096 && rxbuf_size != 2048) {
-		printk(KERN_WARNING
-		       "Unsupported receive buffer size (%d) requested\n",
-		       rxbuf_size);
-		printk(KERN_WARNING
-		       "Must be 2048, 4096 or 8192. Defaulting to 2048\n");
-		rxbuf_size = 2048;
-	}
-
-	ret = pci_register_driver(&be_driver);
-
-	return ret;
-}
-
-module_init(be_init_module);
-
-/*
- * be_exit_module - Driver Exit Cleanup Routine
- */
-static void __exit be_exit_module(void)
-{
-	pci_unregister_driver(&be_driver);
-}
-
-module_exit(be_exit_module);
diff --git a/drivers/staging/benet/be_int.c b/drivers/staging/benet/be_int.c
deleted file mode 100644
index cba95d0..0000000
--- a/drivers/staging/benet/be_int.c
+++ /dev/null
@@ -1,863 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#include <linux/if_vlan.h>
-#include <linux/inet_lro.h>
-
-#include "benet.h"
-
-/* number of bytes of RX frame that are copied to skb->data */
-#define BE_HDR_LEN 64
-
-#define NETIF_RX(skb) netif_receive_skb(skb)
-#define VLAN_ACCEL_RX(skb, pnob, vt) \
-		vlan_hwaccel_rx(skb, pnob->vlan_grp, vt)
-
-/*
-    This function notifies BladeEngine of the number of completion
-    entries processed from the specified completion queue by writing
-    the number of popped entries to the door bell.
-
-    pnob	- Pointer to the NetObject structure
-    n		- Number of completion entries processed
-    cq_id	- Queue ID of the completion queue for which notification
-			is being done.
-    re_arm	- 1  - rearm the completion ring to generate an event.
-		- 0  - dont rearm the completion ring to generate an event
-*/
-void be_notify_cmpl(struct be_net_object *pnob, int n, int cq_id, int re_arm)
-{
-	struct CQ_DB_AMAP cqdb;
-
-	cqdb.dw[0] = 0;
-	AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, cq_id);
-	AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, re_arm);
-	AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, n);
-	PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]);
-}
-
-/*
- * adds additional receive frags indicated by BE starting from given
- * frag index (fi) to specified skb's frag list
- */
-static void
-add_skb_frags(struct be_net_object *pnob, struct sk_buff *skb,
-	      u32 nresid, u32 fi)
-{
-	struct be_adapter *adapter = pnob->adapter;
-	u32 sk_frag_idx, n;
-	struct be_rx_page_info *rx_page_info;
-	u32 frag_sz = pnob->rx_buf_size;
-
-	sk_frag_idx = skb_shinfo(skb)->nr_frags;
-	while (nresid) {
-		index_inc(&fi, pnob->rx_q_len);
-
-		rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi];
-		pnob->rx_ctxt[fi] = NULL;
-		if ((rx_page_info->page_offset) ||
-		    (pnob->rx_pg_shared == false)) {
-			pci_unmap_page(adapter->pdev,
-				       pci_unmap_addr(rx_page_info, bus),
-				       frag_sz, PCI_DMA_FROMDEVICE);
-		}
-
-		n = min(nresid, frag_sz);
-		skb_shinfo(skb)->frags[sk_frag_idx].page = rx_page_info->page;
-		skb_shinfo(skb)->frags[sk_frag_idx].page_offset
-		    = rx_page_info->page_offset;
-		skb_shinfo(skb)->frags[sk_frag_idx].size = n;
-
-		sk_frag_idx++;
-		skb->len += n;
-		skb->data_len += n;
-		skb_shinfo(skb)->nr_frags++;
-		nresid -= n;
-
-		memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
-		atomic_dec(&pnob->rx_q_posted);
-	}
-}
-
-/*
- * This function processes incoming nic packets over various Rx queues.
- * This function takes the adapter, the current Rx status descriptor
- * entry and the Rx completion queue ID as argument.
- */
-static inline int process_nic_rx_completion(struct be_net_object *pnob,
-					    struct ETH_RX_COMPL_AMAP *rxcp)
-{
-	struct be_adapter *adapter = pnob->adapter;
-	struct sk_buff *skb;
-	int udpcksm, tcpcksm;
-	int n;
-	u32 nresid, fi;
-	u32 frag_sz = pnob->rx_buf_size;
-	u8 *va;
-	struct be_rx_page_info *rx_page_info;
-	u32 numfrags, vtp, vtm, vlan_tag, pktsize;
-
-	fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp);
-	BUG_ON(fi >= (int)pnob->rx_q_len);
-	BUG_ON(fi < 0);
-
-	rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi];
-	BUG_ON(!rx_page_info->page);
-	pnob->rx_ctxt[fi] = NULL;
-
-	/*
-	 * If one page is used per fragment or if this is the second half of
-	 *  of the page, unmap the page here
-	 */
-	if ((rx_page_info->page_offset) || (pnob->rx_pg_shared == false)) {
-		pci_unmap_page(adapter->pdev,
-			       pci_unmap_addr(rx_page_info, bus), frag_sz,
-			       PCI_DMA_FROMDEVICE);
-	}
-
-	atomic_dec(&pnob->rx_q_posted);
-	udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp);
-	tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp);
-	pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp);
-	/*
-	 * get rid of RX flush completions first.
-	 */
-	if ((tcpcksm) && (udpcksm) && (pktsize == 32)) {
-		put_page(rx_page_info->page);
-		memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
-		return 0;
-	}
-	skb = netdev_alloc_skb(pnob->netdev, BE_HDR_LEN + NET_IP_ALIGN);
-	if (skb == NULL) {
-		dev_info(&pnob->netdev->dev, "alloc_skb() failed\n");
-		put_page(rx_page_info->page);
-		memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
-		goto free_frags;
-	}
-	skb_reserve(skb, NET_IP_ALIGN);
-
-	skb->dev = pnob->netdev;
-
-	n = min(pktsize, frag_sz);
-
-	va = page_address(rx_page_info->page) + rx_page_info->page_offset;
-	prefetch(va);
-
-	skb->len = n;
-	skb->data_len = n;
-	if (n <= BE_HDR_LEN) {
-		memcpy(skb->data, va, n);
-		put_page(rx_page_info->page);
-		skb->data_len -= n;
-		skb->tail += n;
-	} else {
-
-		/* Setup the SKB with page buffer information */
-		skb_shinfo(skb)->frags[0].page = rx_page_info->page;
-		skb_shinfo(skb)->nr_frags++;
-
-		/* Copy the header into the skb_data */
-		memcpy(skb->data, va, BE_HDR_LEN);
-		skb_shinfo(skb)->frags[0].page_offset =
-		    rx_page_info->page_offset + BE_HDR_LEN;
-		skb_shinfo(skb)->frags[0].size = n - BE_HDR_LEN;
-		skb->data_len -= BE_HDR_LEN;
-		skb->tail += BE_HDR_LEN;
-	}
-	memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
-	nresid = pktsize - n;
-
-	skb->protocol = eth_type_trans(skb, pnob->netdev);
-
-	if ((tcpcksm || udpcksm) && adapter->rx_csum)
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	else
-		skb->ip_summed = CHECKSUM_NONE;
-	/*
-	 * if we have more bytes left, the frame has been
-	 * given to us in multiple fragments.  This happens
-	 * with Jumbo frames. Add the remaining fragments to
-	 * skb->frags[] array.
-	 */
-	if (nresid)
-		add_skb_frags(pnob, skb, nresid, fi);
-
-	/* update the the true size of the skb. */
-	skb->truesize = skb->len + sizeof(struct sk_buff);
-
-	/*
-	 * If a 802.3 frame or 802.2 LLC frame
-	 * (i.e) contains length field in MAC Hdr
-	 * and frame len is greater than 64 bytes
-	 */
-	if (((skb->protocol == ntohs(ETH_P_802_2)) ||
-	     (skb->protocol == ntohs(ETH_P_802_3)))
-	    && (pktsize > BE_HDR_LEN)) {
-		/*
-		 * If the length given in Mac Hdr is less than frame size
-		 * Erraneous frame, Drop it
-		 */
-		if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) < pktsize) {
-			/* Increment Non Ether type II frames dropped */
-			adapter->be_stat.bes_802_3_dropped_frames++;
-
-			kfree_skb(skb);
-			return 0;
-		}
-		/*
-		 * else if the length given in Mac Hdr is greater than
-		 * frame size, should not be seeing this sort of frames
-		 * dump the pkt and pass to stack
-		 */
-		else if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) > pktsize) {
-			/* Increment Non Ether type II frames malformed */
-			adapter->be_stat.bes_802_3_malformed_frames++;
-		}
-	}
-
-	vtp = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp);
-	vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp);
-	if (vtp && vtm) {
-		/* Vlan tag present in pkt and BE found
-		 * that the tag matched an entry in VLAN table
-		 */
-		if (!pnob->vlan_grp || pnob->num_vlans == 0) {
-			/* But we have no VLANs configured.
-			 * This should never happen.  Drop the packet.
-			 */
-			dev_info(&pnob->netdev->dev,
-			       "BladeEngine: Unexpected vlan tagged packet\n");
-			kfree_skb(skb);
-			return 0;
-		}
-		/* pass the VLAN packet to stack */
-		vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp);
-		VLAN_ACCEL_RX(skb, pnob, be16_to_cpu(vlan_tag));
-
-	} else {
-		NETIF_RX(skb);
-	}
-	return 0;
-
-free_frags:
-	/* free all frags associated with the current rxcp */
-	numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp);
-	while (numfrags-- > 1) {
-		index_inc(&fi, pnob->rx_q_len);
-
-		rx_page_info = (struct be_rx_page_info *)
-		    pnob->rx_ctxt[fi];
-		pnob->rx_ctxt[fi] = (void *)NULL;
-		if (rx_page_info->page_offset || !pnob->rx_pg_shared) {
-			pci_unmap_page(adapter->pdev,
-				       pci_unmap_addr(rx_page_info, bus),
-				       frag_sz, PCI_DMA_FROMDEVICE);
-		}
-
-		put_page(rx_page_info->page);
-		memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
-		atomic_dec(&pnob->rx_q_posted);
-	}
-	return -ENOMEM;
-}
-
-static void process_nic_rx_completion_lro(struct be_net_object *pnob,
-					  struct ETH_RX_COMPL_AMAP *rxcp)
-{
-	struct be_adapter *adapter = pnob->adapter;
-	struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME];
-	unsigned int udpcksm, tcpcksm;
-	u32 numfrags, vlanf, vtm, vlan_tag, nresid;
-	u16 vlant;
-	unsigned int fi, idx, n;
-	struct be_rx_page_info *rx_page_info;
-	u32 frag_sz = pnob->rx_buf_size, pktsize;
-	bool rx_coal = (adapter->max_rx_coal <= 1) ? 0 : 1;
-	u8 err, *va;
-	__wsum csum = 0;
-
-	if (AMAP_GET_BITS_PTR(ETH_RX_COMPL, ipsec, rxcp)) {
-		/*  Drop the pkt and move to the next completion.  */
-		adapter->be_stat.bes_rx_misc_pkts++;
-		return;
-	}
-	err = AMAP_GET_BITS_PTR(ETH_RX_COMPL, err, rxcp);
-	if (err || !rx_coal) {
-		/* We won't coalesce Rx pkts if the err bit set.
-		 * take the path of normal completion processing */
-		process_nic_rx_completion(pnob, rxcp);
-		return;
-	}
-
-	fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp);
-	BUG_ON(fi >= (int)pnob->rx_q_len);
-	BUG_ON(fi < 0);
-	rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi];
-	BUG_ON(!rx_page_info->page);
-	pnob->rx_ctxt[fi] = (void *)NULL;
-	/*  If one page is used per fragment or if this is the
-	 * second half of the page, unmap the page here
-	 */
-	if (rx_page_info->page_offset || !pnob->rx_pg_shared) {
-		pci_unmap_page(adapter->pdev,
-			       pci_unmap_addr(rx_page_info, bus),
-			       frag_sz, PCI_DMA_FROMDEVICE);
-	}
-
-	numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp);
-	udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp);
-	tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp);
-	vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp);
-	vlant = be16_to_cpu(vlan_tag);
-	vlanf = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp);
-	vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp);
-	pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp);
-
-	atomic_dec(&pnob->rx_q_posted);
-
-	if (tcpcksm && udpcksm && pktsize == 32) {
-		/* flush completion entries */
-		put_page(rx_page_info->page);
-		memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
-		return;
-	}
-	/* Only one of udpcksum and tcpcksum can be set */
-	BUG_ON(udpcksm && tcpcksm);
-
-	/* jumbo frames could come in multiple fragments */
-	BUG_ON(numfrags != ((pktsize + (frag_sz - 1)) / frag_sz));
-	n = min(pktsize, frag_sz);
-	nresid = pktsize - n;	/* will be useful for jumbo pkts */
-	idx = 0;
-
-	va = page_address(rx_page_info->page) + rx_page_info->page_offset;
-	prefetch(va);
-	rx_frags[idx].page = rx_page_info->page;
-	rx_frags[idx].page_offset = (rx_page_info->page_offset);
-	rx_frags[idx].size = n;
-	memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
-
-	/* If we got multiple fragments, we have more data. */
-	while (nresid) {
-		idx++;
-		index_inc(&fi, pnob->rx_q_len);
-
-		rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi];
-		pnob->rx_ctxt[fi] = (void *)NULL;
-		if (rx_page_info->page_offset || !pnob->rx_pg_shared) {
-			pci_unmap_page(adapter->pdev,
-				       pci_unmap_addr(rx_page_info, bus),
-				       frag_sz, PCI_DMA_FROMDEVICE);
-		}
-
-		n = min(nresid, frag_sz);
-		rx_frags[idx].page = rx_page_info->page;
-		rx_frags[idx].page_offset = (rx_page_info->page_offset);
-		rx_frags[idx].size = n;
-
-		nresid -= n;
-		memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
-		atomic_dec(&pnob->rx_q_posted);
-	}
-
-	if (likely(!(vlanf && vtm))) {
-		lro_receive_frags(&pnob->lro_mgr, rx_frags,
-				  pktsize, pktsize,
-				  (void *)(unsigned long)csum, csum);
-	} else {
-		/* Vlan tag present in pkt and BE found
-		 * that the tag matched an entry in VLAN table
-		 */
-		if (unlikely(!pnob->vlan_grp || pnob->num_vlans == 0)) {
-			/* But we have no VLANs configured.
-			 * This should never happen.  Drop the packet.
-			 */
-			dev_info(&pnob->netdev->dev,
-			       "BladeEngine: Unexpected vlan tagged packet\n");
-			return;
-		}
-		/* pass the VLAN packet to stack */
-		lro_vlan_hwaccel_receive_frags(&pnob->lro_mgr,
-					       rx_frags, pktsize, pktsize,
-					       pnob->vlan_grp, vlant,
-					       (void *)(unsigned long)csum,
-					       csum);
-	}
-
-	adapter->be_stat.bes_rx_coal++;
-}
-
-struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *pnob)
-{
-	struct ETH_RX_COMPL_AMAP *rxcp = &pnob->rx_cq[pnob->rx_cq_tl];
-	u32 valid, ct;
-
-	valid = AMAP_GET_BITS_PTR(ETH_RX_COMPL, valid, rxcp);
-	if (valid == 0)
-		return NULL;
-
-	ct = AMAP_GET_BITS_PTR(ETH_RX_COMPL, ct, rxcp);
-	if (ct != 0) {
-		/* Invalid chute #. treat as error */
-		AMAP_SET_BITS_PTR(ETH_RX_COMPL, err, rxcp, 1);
-	}
-
-	be_adv_rxcq_tl(pnob);
-	AMAP_SET_BITS_PTR(ETH_RX_COMPL, valid, rxcp, 0);
-	return rxcp;
-}
-
-static void update_rx_rate(struct be_adapter *adapter)
-{
-	/* update the rate once in two seconds */
-	if ((jiffies - adapter->eth_rx_jiffies) > 2 * (HZ)) {
-		u32 r;
-		r = adapter->eth_rx_bytes /
-		    ((jiffies - adapter->eth_rx_jiffies) / (HZ));
-		r = (r / 1000000);	/* MB/Sec */
-
-		/* Mega Bits/Sec */
-		adapter->be_stat.bes_eth_rx_rate = (r * 8);
-		adapter->eth_rx_jiffies = jiffies;
-		adapter->eth_rx_bytes = 0;
-	}
-}
-
-static int process_rx_completions(struct be_net_object *pnob, int max_work)
-{
-	struct be_adapter *adapter = pnob->adapter;
-	struct ETH_RX_COMPL_AMAP *rxcp;
-	u32 nc = 0;
-	unsigned int pktsize;
-
-	while (max_work && (rxcp = be_get_rx_cmpl(pnob))) {
-		prefetch(rxcp);
-		pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp);
-		process_nic_rx_completion_lro(pnob, rxcp);
-		adapter->eth_rx_bytes += pktsize;
-		update_rx_rate(adapter);
-		nc++;
-		max_work--;
-		adapter->be_stat.bes_rx_compl++;
-	}
-	if (likely(adapter->max_rx_coal > 1)) {
-		adapter->be_stat.bes_rx_flush++;
-		lro_flush_all(&pnob->lro_mgr);
-	}
-
-	/* Refill the queue */
-	if (atomic_read(&pnob->rx_q_posted) < 900)
-		be_post_eth_rx_buffs(pnob);
-
-	return nc;
-}
-
-static struct ETH_TX_COMPL_AMAP *be_get_tx_cmpl(struct be_net_object *pnob)
-{
-	struct ETH_TX_COMPL_AMAP *txcp = &pnob->tx_cq[pnob->tx_cq_tl];
-	u32 valid;
-
-	valid = AMAP_GET_BITS_PTR(ETH_TX_COMPL, valid, txcp);
-	if (valid == 0)
-		return NULL;
-
-	AMAP_SET_BITS_PTR(ETH_TX_COMPL, valid, txcp, 0);
-	be_adv_txcq_tl(pnob);
-	return txcp;
-
-}
-
-void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx)
-{
-	struct be_adapter *adapter = pnob->adapter;
-	int cur_index, tx_wrbs_completed = 0;
-	struct sk_buff *skb;
-	u64 busaddr, pa, pa_lo, pa_hi;
-	struct ETH_WRB_AMAP *wrb;
-	u32 frag_len, last_index, j;
-
-	last_index = tx_compl_lastwrb_idx_get(pnob);
-	BUG_ON(last_index != end_idx);
-	pnob->tx_ctxt[pnob->tx_q_tl] = NULL;
-	do {
-		cur_index = pnob->tx_q_tl;
-		wrb = &pnob->tx_q[cur_index];
-		pa_hi = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb);
-		pa_lo = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb);
-		frag_len = AMAP_GET_BITS_PTR(ETH_WRB, frag_len, wrb);
-		busaddr = (pa_hi << 32) | pa_lo;
-		if (busaddr != 0) {
-			pa = le64_to_cpu(busaddr);
-			pci_unmap_single(adapter->pdev, pa,
-					 frag_len, PCI_DMA_TODEVICE);
-		}
-		if (cur_index == last_index) {
-			skb = (struct sk_buff *)pnob->tx_ctxt[cur_index];
-			BUG_ON(!skb);
-			for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) {
-				struct skb_frag_struct *frag;
-				frag = &skb_shinfo(skb)->frags[j];
-				pci_unmap_page(adapter->pdev,
-					       (ulong) frag->page, frag->size,
-					       PCI_DMA_TODEVICE);
-			}
-			kfree_skb(skb);
-			pnob->tx_ctxt[cur_index] = NULL;
-		} else {
-			BUG_ON(pnob->tx_ctxt[cur_index]);
-		}
-		tx_wrbs_completed++;
-		be_adv_txq_tl(pnob);
-	} while (cur_index != last_index);
-	atomic_sub(tx_wrbs_completed, &pnob->tx_q_used);
-}
-
-/* there is no need to take an SMP lock here since currently
- * we have only one instance of the tasklet that does completion
- * processing.
- */
-static void process_nic_tx_completions(struct be_net_object *pnob)
-{
-	struct be_adapter *adapter = pnob->adapter;
-	struct ETH_TX_COMPL_AMAP *txcp;
-	struct net_device *netdev = pnob->netdev;
-	u32 end_idx, num_processed = 0;
-
-	adapter->be_stat.bes_tx_events++;
-
-	while ((txcp = be_get_tx_cmpl(pnob))) {
-		end_idx = AMAP_GET_BITS_PTR(ETH_TX_COMPL, wrb_index, txcp);
-		process_one_tx_compl(pnob, end_idx);
-		num_processed++;
-		adapter->be_stat.bes_tx_compl++;
-	}
-	be_notify_cmpl(pnob, num_processed, pnob->tx_cq_id, 1);
-	/*
-	 * We got Tx completions and have usable WRBs.
-	 * If the netdev's queue has been stopped
-	 * because we had run out of WRBs, wake it now.
-	 */
-	spin_lock(&adapter->txq_lock);
-	if (netif_queue_stopped(netdev)
-	    && atomic_read(&pnob->tx_q_used) < pnob->tx_q_len / 2) {
-		netif_wake_queue(netdev);
-	}
-	spin_unlock(&adapter->txq_lock);
-}
-
-static u32 post_rx_buffs(struct be_net_object *pnob, struct list_head *rxbl)
-{
-	u32 nposted = 0;
-	struct ETH_RX_D_AMAP *rxd = NULL;
-	struct be_recv_buffer *rxbp;
-	void **rx_ctxp;
-	struct RQ_DB_AMAP rqdb;
-
-	rx_ctxp = pnob->rx_ctxt;
-
-	while (!list_empty(rxbl) &&
-	       (rx_ctxp[pnob->rx_q_hd] == NULL) && nposted < 255) {
-
-		rxbp = list_first_entry(rxbl, struct be_recv_buffer, rxb_list);
-		list_del(&rxbp->rxb_list);
-		rxd = pnob->rx_q + pnob->rx_q_hd;
-		AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_lo, rxd, rxbp->rxb_pa_lo);
-		AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_hi, rxd, rxbp->rxb_pa_hi);
-
-		rx_ctxp[pnob->rx_q_hd] = rxbp->rxb_ctxt;
-		be_adv_rxq_hd(pnob);
-		nposted++;
-	}
-
-	if (nposted) {
-		/* Now press the door bell to notify BladeEngine. */
-		rqdb.dw[0] = 0;
-		AMAP_SET_BITS_PTR(RQ_DB, numPosted, &rqdb, nposted);
-		AMAP_SET_BITS_PTR(RQ_DB, rq, &rqdb, pnob->rx_q_id);
-		PD_WRITE(&pnob->fn_obj, erx_rq_db, rqdb.dw[0]);
-	}
-	atomic_add(nposted, &pnob->rx_q_posted);
-	return nposted;
-}
-
-void be_post_eth_rx_buffs(struct be_net_object *pnob)
-{
-	struct be_adapter *adapter = pnob->adapter;
-	u32 num_bufs, r;
-	u64 busaddr = 0, tmp_pa;
-	u32 max_bufs, pg_hd;
-	u32 frag_size;
-	struct be_recv_buffer *rxbp;
-	struct list_head rxbl;
-	struct be_rx_page_info *rx_page_info;
-	struct page *page = NULL;
-	u32 page_order = 0;
-	gfp_t alloc_flags = GFP_ATOMIC;
-
-	BUG_ON(!adapter);
-
-	max_bufs = 64;		/* should be even # <= 255. */
-
-	frag_size = pnob->rx_buf_size;
-	page_order = get_order(frag_size);
-
-	if (frag_size == 8192)
-		alloc_flags |= (gfp_t) __GFP_COMP;
-	/*
-	 * Form a linked list of RECV_BUFFFER structure to be be posted.
-	 * We will post even number of buffer so that pages can be
-	 * shared.
-	 */
-	INIT_LIST_HEAD(&rxbl);
-
-	for (num_bufs = 0; num_bufs < max_bufs &&
-		!pnob->rx_page_info[pnob->rx_pg_info_hd].page; ++num_bufs) {
-
-		rxbp = &pnob->eth_rx_bufs[num_bufs];
-		pg_hd = pnob->rx_pg_info_hd;
-		rx_page_info = &pnob->rx_page_info[pg_hd];
-
-		if (!page) {
-			page = alloc_pages(alloc_flags, page_order);
-			if (unlikely(page == NULL)) {
-				adapter->be_stat.bes_ethrx_post_fail++;
-				pnob->rxbuf_post_fail++;
-				break;
-			}
-			pnob->rxbuf_post_fail = 0;
-			busaddr = pci_map_page(adapter->pdev, page, 0,
-					       frag_size, PCI_DMA_FROMDEVICE);
-			rx_page_info->page_offset = 0;
-			rx_page_info->page = page;
-			/*
-			 * If we are sharing a page among two skbs,
-			 * alloc a new one on the next iteration
-			 */
-			if (pnob->rx_pg_shared == false)
-				page = NULL;
-		} else {
-			get_page(page);
-			rx_page_info->page_offset += frag_size;
-			rx_page_info->page = page;
-			/*
-			 * We are finished with the alloced page,
-			 * Alloc a new one on the next iteration
-			 */
-			page = NULL;
-		}
-		rxbp->rxb_ctxt = (void *)rx_page_info;
-		index_inc(&pnob->rx_pg_info_hd, pnob->rx_q_len);
-
-		pci_unmap_addr_set(rx_page_info, bus, busaddr);
-		tmp_pa = busaddr + rx_page_info->page_offset;
-		rxbp->rxb_pa_lo = (tmp_pa & 0xFFFFFFFF);
-		rxbp->rxb_pa_hi = (tmp_pa >> 32);
-		rxbp->rxb_len = frag_size;
-		list_add_tail(&rxbp->rxb_list, &rxbl);
-	}			/* End of for */
-
-	r = post_rx_buffs(pnob, &rxbl);
-	BUG_ON(r != num_bufs);
-	return;
-}
-
-/*
- * Interrupt service for network function.  We just schedule the
- * tasklet which does all completion processing.
- */
-irqreturn_t be_int(int irq, void *dev)
-{
-	struct net_device *netdev = dev;
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-	u32 isr;
-
-	isr = CSR_READ(&pnob->fn_obj, cev.isr1);
-	if (unlikely(!isr))
-		return IRQ_NONE;
-
-	spin_lock(&adapter->int_lock);
-	adapter->isr |= isr;
-	spin_unlock(&adapter->int_lock);
-
-	adapter->be_stat.bes_ints++;
-
-	tasklet_schedule(&adapter->sts_handler);
-	return IRQ_HANDLED;
-}
-
-/*
- * Poll function called by NAPI with a work budget.
- * We process as many UC. BC and MC receive completions
- * as the budget allows and return the actual number of
- * RX ststutses processed.
- */
-int be_poll(struct napi_struct *napi, int budget)
-{
-	struct be_net_object *pnob =
-			container_of(napi, struct be_net_object, napi);
-	u32 work_done;
-
-	pnob->adapter->be_stat.bes_polls++;
-	work_done = process_rx_completions(pnob, budget);
-	BUG_ON(work_done > budget);
-
-	/* All consumed */
-	if (work_done < budget) {
-		netif_rx_complete(napi);
-		/* enable intr */
-		be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 1);
-	} else {
-		/* More to be consumed; continue with interrupts disabled */
-		be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 0);
-	}
-	return work_done;
-}
-
-static struct EQ_ENTRY_AMAP *get_event(struct be_net_object *pnob)
-{
-	struct EQ_ENTRY_AMAP *eqp = &(pnob->event_q[pnob->event_q_tl]);
-	if (!AMAP_GET_BITS_PTR(EQ_ENTRY, Valid, eqp))
-		return NULL;
-	be_adv_eq_tl(pnob);
-	return eqp;
-}
-
-/*
- * Processes all valid events in the event ring associated with given
- * NetObject.  Also, notifies BE the number of events processed.
- */
-static inline u32 process_events(struct be_net_object *pnob)
-{
-	struct be_adapter *adapter = pnob->adapter;
-	struct EQ_ENTRY_AMAP *eqp;
-	u32 rid, num_events = 0;
-	struct net_device *netdev = pnob->netdev;
-
-	while ((eqp = get_event(pnob)) != NULL) {
-		adapter->be_stat.bes_events++;
-		rid = AMAP_GET_BITS_PTR(EQ_ENTRY, ResourceID, eqp);
-		if (rid == pnob->rx_cq_id) {
-			adapter->be_stat.bes_rx_events++;
-			netif_rx_schedule(&pnob->napi);
-		} else if (rid == pnob->tx_cq_id) {
-			process_nic_tx_completions(pnob);
-		} else if (rid == pnob->mcc_cq_id) {
-			be_mcc_process_cq(&pnob->mcc_q_obj, 1);
-		} else {
-			dev_info(&netdev->dev,
-					"Invalid EQ ResourceID %d\n", rid);
-		}
-		AMAP_SET_BITS_PTR(EQ_ENTRY, Valid, eqp, 0);
-		AMAP_SET_BITS_PTR(EQ_ENTRY, ResourceID, eqp, 0);
-		num_events++;
-	}
-	return num_events;
-}
-
-static void update_eqd(struct be_adapter *adapter, struct be_net_object *pnob)
-{
-	int status;
-	struct be_eq_object *eq_objectp;
-
-	/* update once a second */
-	if ((jiffies - adapter->ips_jiffies) > 1 * (HZ)) {
-		/* One second elapsed since last update  */
-		u32 r, new_eqd = -1;
-		r = adapter->be_stat.bes_ints - adapter->be_stat.bes_prev_ints;
-		r = r / ((jiffies - adapter->ips_jiffies) / (HZ));
-		adapter->be_stat.bes_ips = r;
-		adapter->ips_jiffies = jiffies;
-		adapter->be_stat.bes_prev_ints = adapter->be_stat.bes_ints;
-		if (r > IPS_HI_WM && adapter->cur_eqd < adapter->max_eqd)
-			new_eqd = (adapter->cur_eqd + 8);
-		if (r < IPS_LO_WM && adapter->cur_eqd > adapter->min_eqd)
-			new_eqd = (adapter->cur_eqd - 8);
-		if (adapter->enable_aic && new_eqd != -1) {
-			eq_objectp = &pnob->event_q_obj;
-			status = be_eq_modify_delay(&pnob->fn_obj, 1,
-						    &eq_objectp, &new_eqd, NULL,
-						    NULL, NULL);
-			if (status == BE_SUCCESS)
-				adapter->cur_eqd = new_eqd;
-		}
-	}
-}
-
-/*
-    This function notifies BladeEngine of how many events were processed
-    from the event queue by ringing the corresponding door bell and
-    optionally re-arms the event queue.
-    n		- number of events processed
-    re_arm	- 1 - re-arm the EQ, 0 - do not re-arm the EQ
-
-*/
-static void be_notify_event(struct be_net_object *pnob, int n, int re_arm)
-{
-	struct CQ_DB_AMAP eqdb;
-	eqdb.dw[0] = 0;
-
-	AMAP_SET_BITS_PTR(CQ_DB, qid, &eqdb, pnob->event_q_id);
-	AMAP_SET_BITS_PTR(CQ_DB, rearm, &eqdb, re_arm);
-	AMAP_SET_BITS_PTR(CQ_DB, event, &eqdb, 1);
-	AMAP_SET_BITS_PTR(CQ_DB, num_popped, &eqdb, n);
-	/*
-	 * Under some situations we see an interrupt and no valid
-	 * EQ entry.  To keep going, we need to ring the DB even if
-	 * numPOsted is 0.
-	 */
-	PD_WRITE(&pnob->fn_obj, cq_db, eqdb.dw[0]);
-	return;
-}
-
-/*
- * Called from the tasklet scheduled by ISR.  All real interrupt processing
- * is done here.
- */
-void be_process_intr(unsigned long context)
-{
-	struct be_adapter *adapter = (struct be_adapter *)context;
-	struct be_net_object *pnob = adapter->net_obj;
-	u32 isr, n;
-	ulong flags = 0;
-
-	isr = adapter->isr;
-
-	/*
-	 * we create only one NIC event queue in Linux. Event is
-	 * expected only in the first event queue
-	 */
-	BUG_ON(isr & 0xfffffffe);
-	if ((isr & 1) == 0)
-		return;		/* not our interrupt */
-	n = process_events(pnob);
-	/*
-	 * Clear the event bit. adapter->isr is  set by
-	 * hard interrupt.  Prevent race with lock.
-	 */
-	spin_lock_irqsave(&adapter->int_lock, flags);
-	adapter->isr &= ~1;
-	spin_unlock_irqrestore(&adapter->int_lock, flags);
-	be_notify_event(pnob, n, 1);
-	/*
-	 * If previous allocation attempts had failed and
-	 * BE has used up all posted buffers, post RX buffers here
-	 */
-	if (pnob->rxbuf_post_fail && atomic_read(&pnob->rx_q_posted) == 0)
-		be_post_eth_rx_buffs(pnob);
-	update_eqd(adapter, pnob);
-	return;
-}
diff --git a/drivers/staging/benet/be_netif.c b/drivers/staging/benet/be_netif.c
deleted file mode 100644
index 2b8daf6..0000000
--- a/drivers/staging/benet/be_netif.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * be_netif.c
- *
- * This file contains various entry points of drivers seen by tcp/ip stack.
- */
-
-#include <linux/if_vlan.h>
-#include <linux/in.h>
-#include "benet.h"
-#include <linux/ip.h>
-#include <linux/inet_lro.h>
-
-/* Strings to print Link properties */
-static const char *link_speed[] = {
-	"Invalid link Speed Value",
-	"10 Mbps",
-	"100 Mbps",
-	"1 Gbps",
-	"10 Gbps"
-};
-
-static const char *link_duplex[] = {
-	"Invalid Duplex Value",
-	"Half Duplex",
-	"Full Duplex"
-};
-
-static const char *link_state[] = {
-	"",
-	"(active)"
-};
-
-void be_print_link_info(struct BE_LINK_STATUS *lnk_status)
-{
-	u16 si, di, ai;
-
-	/* Port 0 */
-	if (lnk_status->mac0_speed && lnk_status->mac0_duplex) {
-		/* Port is up and running */
-		si = (lnk_status->mac0_speed < 5) ? lnk_status->mac0_speed : 0;
-		di = (lnk_status->mac0_duplex < 3) ?
-		    lnk_status->mac0_duplex : 0;
-		ai = (lnk_status->active_port == 0) ? 1 : 0;
-		printk(KERN_INFO "PortNo. 0: Speed - %s %s %s\n",
-		       link_speed[si], link_duplex[di], link_state[ai]);
-	} else
-		printk(KERN_INFO "PortNo. 0: Down\n");
-
-	/* Port 1 */
-	if (lnk_status->mac1_speed && lnk_status->mac1_duplex) {
-		/* Port is up and running */
-		si = (lnk_status->mac1_speed < 5) ? lnk_status->mac1_speed : 0;
-		di = (lnk_status->mac1_duplex < 3) ?
-		    lnk_status->mac1_duplex : 0;
-		ai = (lnk_status->active_port == 0) ? 1 : 0;
-		printk(KERN_INFO "PortNo. 1: Speed - %s %s %s\n",
-		       link_speed[si], link_duplex[di], link_state[ai]);
-	} else
-		printk(KERN_INFO "PortNo. 1: Down\n");
-
-	return;
-}
-
-static int
-be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
-		   void **ip_hdr, void **tcpudp_hdr,
-		   u64 *hdr_flags, void *priv)
-{
-	struct ethhdr *eh;
-	struct vlan_ethhdr *veh;
-	struct iphdr *iph;
-	u8 *va = page_address(frag->page) + frag->page_offset;
-	unsigned long ll_hlen;
-
-	/* find the mac header, abort if not IPv4 */
-
-	prefetch(va);
-	eh = (struct ethhdr *)va;
-	*mac_hdr = eh;
-	ll_hlen = ETH_HLEN;
-	if (eh->h_proto != htons(ETH_P_IP)) {
-		if (eh->h_proto == htons(ETH_P_8021Q)) {
-			veh = (struct vlan_ethhdr *)va;
-			if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
-				return -1;
-
-			ll_hlen += VLAN_HLEN;
-
-		} else {
-			return -1;
-		}
-	}
-	*hdr_flags = LRO_IPV4;
-
-	iph = (struct iphdr *)(va + ll_hlen);
-	*ip_hdr = iph;
-	if (iph->protocol != IPPROTO_TCP)
-		return -1;
-	*hdr_flags |= LRO_TCP;
-	*tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
-
-	return 0;
-}
-
-static int benet_open(struct net_device *netdev)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-	struct net_lro_mgr *lro_mgr;
-
-	if (adapter->dev_state < BE_DEV_STATE_INIT)
-		return -EAGAIN;
-
-	lro_mgr = &pnob->lro_mgr;
-	lro_mgr->dev = netdev;
-
-	lro_mgr->features = LRO_F_NAPI;
-	lro_mgr->ip_summed = CHECKSUM_UNNECESSARY;
-	lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
-	lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS;
-	lro_mgr->lro_arr = pnob->lro_desc;
-	lro_mgr->get_frag_header = be_get_frag_header;
-	lro_mgr->max_aggr = adapter->max_rx_coal;
-	lro_mgr->frag_align_pad = 2;
-	if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
-		lro_mgr->max_aggr = MAX_SKB_FRAGS;
-
-	adapter->max_rx_coal = BE_LRO_MAX_PKTS;
-
-	be_update_link_status(adapter);
-
-	/*
-	 * Set carrier on only if Physical Link up
-	 * Either of the port link status up signifies this
-	 */
-	if ((adapter->port0_link_sts == BE_PORT_LINK_UP) ||
-	    (adapter->port1_link_sts == BE_PORT_LINK_UP)) {
-		netif_start_queue(netdev);
-		netif_carrier_on(netdev);
-	}
-
-	adapter->dev_state = BE_DEV_STATE_OPEN;
-	napi_enable(&pnob->napi);
-	be_enable_intr(pnob);
-	be_enable_eq_intr(pnob);
-	/*
-	 * RX completion queue may be in dis-armed state. Arm it.
-	 */
-	be_notify_cmpl(pnob, 0, pnob->rx_cq_id, 1);
-
-	return 0;
-}
-
-static int benet_close(struct net_device *netdev)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-
-	netif_stop_queue(netdev);
-	synchronize_irq(netdev->irq);
-
-	be_wait_nic_tx_cmplx_cmpl(pnob);
-	adapter->dev_state = BE_DEV_STATE_INIT;
-	netif_carrier_off(netdev);
-
-	adapter->port0_link_sts = BE_PORT_LINK_DOWN;
-	adapter->port1_link_sts = BE_PORT_LINK_DOWN;
-	be_disable_intr(pnob);
-	be_disable_eq_intr(pnob);
-	napi_disable(&pnob->napi);
-
-	return 0;
-}
-
-/*
- * Setting a Mac Address for BE
- * Takes netdev and a void pointer as arguments.
- * The pointer holds the new addres to be used.
- */
-static int benet_set_mac_addr(struct net_device *netdev, void *p)
-{
-	struct sockaddr *addr = p;
-	struct be_net_object *pnob = netdev_priv(netdev);
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	be_rxf_mac_address_read_write(&pnob->fn_obj, 0, 0, false, true, false,
-				netdev->dev_addr, NULL, NULL);
-	/*
-	 * Since we are doing Active-Passive failover, both
-	 * ports should have matching MAC addresses everytime.
-	 */
-	be_rxf_mac_address_read_write(&pnob->fn_obj, 1, 0, false, true, false,
-				      netdev->dev_addr, NULL, NULL);
-
-	return 0;
-}
-
-void be_get_stats_timer_handler(unsigned long context)
-{
-	struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context;
-
-	if (atomic_read(&ctxt->get_stat_flag)) {
-		atomic_dec(&ctxt->get_stat_flag);
-		up((void *)ctxt->get_stat_sem_addr);
-	}
-	del_timer(&ctxt->get_stats_timer);
-	return;
-}
-
-void be_get_stat_cb(void *context, int status,
-		    struct MCC_WRB_AMAP *optional_wrb)
-{
-	struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context;
-	/*
-	 * just up the semaphore if the get_stat_flag
-	 * reads 1. so that the waiter can continue.
-	 * If it is 0, then it was handled by the timer handler.
-	 */
-	del_timer(&ctxt->get_stats_timer);
-	if (atomic_read(&ctxt->get_stat_flag)) {
-		atomic_dec(&ctxt->get_stat_flag);
-		up((void *)ctxt->get_stat_sem_addr);
-	}
-}
-
-struct net_device_stats *benet_get_stats(struct net_device *dev)
-{
-	struct be_net_object *pnob = netdev_priv(dev);
-	struct be_adapter *adapter = pnob->adapter;
-	u64 pa;
-	struct be_timer_ctxt *ctxt = &adapter->timer_ctxt;
-
-	if (adapter->dev_state != BE_DEV_STATE_OPEN) {
-		/* Return previously read stats */
-		return &(adapter->benet_stats);
-	}
-	/* Get Physical Addr */
-	pa = pci_map_single(adapter->pdev, adapter->eth_statsp,
-			    sizeof(struct FWCMD_ETH_GET_STATISTICS),
-			    PCI_DMA_FROMDEVICE);
-	ctxt->get_stat_sem_addr = (unsigned long)&adapter->get_eth_stat_sem;
-	atomic_inc(&ctxt->get_stat_flag);
-
-	be_rxf_query_eth_statistics(&pnob->fn_obj, adapter->eth_statsp,
-				    cpu_to_le64(pa), be_get_stat_cb, ctxt,
-				    NULL);
-
-	ctxt->get_stats_timer.data = (unsigned long)ctxt;
-	mod_timer(&ctxt->get_stats_timer, (jiffies + (HZ * 2)));
-	down((void *)ctxt->get_stat_sem_addr);	/* callback will unblock us */
-
-	/* Adding port0 and port1 stats. */
-	adapter->benet_stats.rx_packets =
-	    adapter->eth_statsp->params.response.p0recvdtotalframes +
-	    adapter->eth_statsp->params.response.p1recvdtotalframes;
-	adapter->benet_stats.tx_packets =
-	    adapter->eth_statsp->params.response.p0xmitunicastframes +
-	    adapter->eth_statsp->params.response.p1xmitunicastframes;
-	adapter->benet_stats.tx_bytes =
-	    adapter->eth_statsp->params.response.p0xmitbyteslsd +
-	    adapter->eth_statsp->params.response.p1xmitbyteslsd;
-	adapter->benet_stats.rx_errors =
-	    adapter->eth_statsp->params.response.p0crcerrors +
-	    adapter->eth_statsp->params.response.p1crcerrors;
-	adapter->benet_stats.rx_errors +=
-	    adapter->eth_statsp->params.response.p0alignmentsymerrs +
-	    adapter->eth_statsp->params.response.p1alignmentsymerrs;
-	adapter->benet_stats.rx_errors +=
-	    adapter->eth_statsp->params.response.p0inrangelenerrors +
-	    adapter->eth_statsp->params.response.p1inrangelenerrors;
-	adapter->benet_stats.rx_bytes =
-	    adapter->eth_statsp->params.response.p0recvdtotalbytesLSD +
-	    adapter->eth_statsp->params.response.p1recvdtotalbytesLSD;
-	adapter->benet_stats.rx_crc_errors =
-	    adapter->eth_statsp->params.response.p0crcerrors +
-	    adapter->eth_statsp->params.response.p1crcerrors;
-
-	adapter->benet_stats.tx_packets +=
-	    adapter->eth_statsp->params.response.p0xmitmulticastframes +
-	    adapter->eth_statsp->params.response.p1xmitmulticastframes;
-	adapter->benet_stats.tx_packets +=
-	    adapter->eth_statsp->params.response.p0xmitbroadcastframes +
-	    adapter->eth_statsp->params.response.p1xmitbroadcastframes;
-	adapter->benet_stats.tx_errors = 0;
-
-	adapter->benet_stats.multicast =
-	    adapter->eth_statsp->params.response.p0xmitmulticastframes +
-	    adapter->eth_statsp->params.response.p1xmitmulticastframes;
-
-	adapter->benet_stats.rx_fifo_errors =
-	    adapter->eth_statsp->params.response.p0rxfifooverflowdropped +
-	    adapter->eth_statsp->params.response.p1rxfifooverflowdropped;
-	adapter->benet_stats.rx_frame_errors =
-	    adapter->eth_statsp->params.response.p0alignmentsymerrs +
-	    adapter->eth_statsp->params.response.p1alignmentsymerrs;
-	adapter->benet_stats.rx_length_errors =
-	    adapter->eth_statsp->params.response.p0inrangelenerrors +
-	    adapter->eth_statsp->params.response.p1inrangelenerrors;
-	adapter->benet_stats.rx_length_errors +=
-	    adapter->eth_statsp->params.response.p0outrangeerrors +
-	    adapter->eth_statsp->params.response.p1outrangeerrors;
-	adapter->benet_stats.rx_length_errors +=
-	    adapter->eth_statsp->params.response.p0frametoolongerrors +
-	    adapter->eth_statsp->params.response.p1frametoolongerrors;
-
-	pci_unmap_single(adapter->pdev, (ulong) adapter->eth_statsp,
-			 sizeof(struct FWCMD_ETH_GET_STATISTICS),
-			 PCI_DMA_FROMDEVICE);
-	return &(adapter->benet_stats);
-
-}
-
-static void be_start_tx(struct be_net_object *pnob, u32 nposted)
-{
-#define CSR_ETH_MAX_SQPOSTS 255
-	struct SQ_DB_AMAP sqdb;
-
-	sqdb.dw[0] = 0;
-
-	AMAP_SET_BITS_PTR(SQ_DB, cid, &sqdb, pnob->tx_q_id);
-	while (nposted) {
-		if (nposted > CSR_ETH_MAX_SQPOSTS) {
-			AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb,
-					  CSR_ETH_MAX_SQPOSTS);
-			nposted -= CSR_ETH_MAX_SQPOSTS;
-		} else {
-			AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, nposted);
-			nposted = 0;
-		}
-		PD_WRITE(&pnob->fn_obj, etx_sq_db, sqdb.dw[0]);
-	}
-
-	return;
-}
-
-static void update_tx_rate(struct be_adapter *adapter)
-{
-	/* update the rate once in two seconds */
-	if ((jiffies - adapter->eth_tx_jiffies) > 2 * (HZ)) {
-		u32 r;
-		r = adapter->eth_tx_bytes /
-		    ((jiffies - adapter->eth_tx_jiffies) / (HZ));
-		r = (r / 1000000);	/* M bytes/s */
-		adapter->be_stat.bes_eth_tx_rate = (r * 8); /* M bits/s */
-		adapter->eth_tx_jiffies = jiffies;
-		adapter->eth_tx_bytes = 0;
-	}
-}
-
-static int wrb_cnt_in_skb(struct sk_buff *skb)
-{
-	int cnt = 0;
-	while (skb) {
-		if (skb->len > skb->data_len)
-			cnt++;
-		cnt += skb_shinfo(skb)->nr_frags;
-		skb = skb_shinfo(skb)->frag_list;
-	}
-	BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT);
-	return cnt;
-}
-
-static void wrb_fill(struct ETH_WRB_AMAP *wrb, u64 addr, int len)
-{
-	AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb, addr >> 32);
-	AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb, addr & 0xFFFFFFFF);
-	AMAP_SET_BITS_PTR(ETH_WRB, frag_len, wrb, len);
-}
-
-static void wrb_fill_extra(struct ETH_WRB_AMAP *wrb, struct sk_buff *skb,
-			   struct be_net_object *pnob)
-{
-	wrb->dw[2] = 0;
-	wrb->dw[3] = 0;
-	AMAP_SET_BITS_PTR(ETH_WRB, crc, wrb, 1);
-	if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) {
-		AMAP_SET_BITS_PTR(ETH_WRB, lso, wrb, 1);
-		AMAP_SET_BITS_PTR(ETH_WRB, lso_mss, wrb,
-				  skb_shinfo(skb)->gso_size);
-	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		u8 proto = ((struct iphdr *)ip_hdr(skb))->protocol;
-		if (proto == IPPROTO_TCP)
-			AMAP_SET_BITS_PTR(ETH_WRB, tcpcs, wrb, 1);
-		else if (proto == IPPROTO_UDP)
-			AMAP_SET_BITS_PTR(ETH_WRB, udpcs, wrb, 1);
-	}
-	if (pnob->vlan_grp && vlan_tx_tag_present(skb)) {
-		AMAP_SET_BITS_PTR(ETH_WRB, vlan, wrb, 1);
-		AMAP_SET_BITS_PTR(ETH_WRB, vlan_tag, wrb, vlan_tx_tag_get(skb));
-	}
-}
-
-static inline void wrb_copy_extra(struct ETH_WRB_AMAP *to,
-				  struct ETH_WRB_AMAP *from)
-{
-
-	to->dw[2] = from->dw[2];
-	to->dw[3] = from->dw[3];
-}
-
-/* Returns the actual count of wrbs used including a possible dummy */
-static int copy_skb_to_txq(struct be_net_object *pnob, struct sk_buff *skb,
-			   u32 wrb_cnt, u32 *copied)
-{
-	u64 busaddr;
-	struct ETH_WRB_AMAP *wrb = NULL, *first = NULL;
-	u32 i;
-	bool dummy = true;
-	struct pci_dev *pdev = pnob->adapter->pdev;
-
-	if (wrb_cnt & 1)
-		wrb_cnt++;
-	else
-		dummy = false;
-
-	atomic_add(wrb_cnt, &pnob->tx_q_used);
-
-	while (skb) {
-		if (skb->len > skb->data_len) {
-			int len = skb->len - skb->data_len;
-			busaddr = pci_map_single(pdev, skb->data, len,
-						 PCI_DMA_TODEVICE);
-			busaddr = cpu_to_le64(busaddr);
-			wrb = &pnob->tx_q[pnob->tx_q_hd];
-			if (first == NULL) {
-				wrb_fill_extra(wrb, skb, pnob);
-				first = wrb;
-			} else {
-				wrb_copy_extra(wrb, first);
-			}
-			wrb_fill(wrb, busaddr, len);
-			be_adv_txq_hd(pnob);
-			*copied += len;
-		}
-
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			struct skb_frag_struct *frag =
-			    &skb_shinfo(skb)->frags[i];
-			busaddr = pci_map_page(pdev, frag->page,
-					       frag->page_offset, frag->size,
-					       PCI_DMA_TODEVICE);
-			busaddr = cpu_to_le64(busaddr);
-			wrb = &pnob->tx_q[pnob->tx_q_hd];
-			if (first == NULL) {
-				wrb_fill_extra(wrb, skb, pnob);
-				first = wrb;
-			} else {
-				wrb_copy_extra(wrb, first);
-			}
-			wrb_fill(wrb, busaddr, frag->size);
-			be_adv_txq_hd(pnob);
-			*copied += frag->size;
-		}
-		skb = skb_shinfo(skb)->frag_list;
-	}
-
-	if (dummy) {
-		wrb = &pnob->tx_q[pnob->tx_q_hd];
-		BUG_ON(first == NULL);
-		wrb_copy_extra(wrb, first);
-		wrb_fill(wrb, 0, 0);
-		be_adv_txq_hd(pnob);
-	}
-	AMAP_SET_BITS_PTR(ETH_WRB, complete, wrb, 1);
-	AMAP_SET_BITS_PTR(ETH_WRB, last, wrb, 1);
-	return wrb_cnt;
-}
-
-/* For each skb transmitted, tx_ctxt stores the num of wrbs in the
- * start index and skb pointer in the end index
- */
-static inline void be_tx_wrb_info_remember(struct be_net_object *pnob,
-					   struct sk_buff *skb, int wrb_cnt,
-					   u32 start)
-{
-	*(u32 *) (&pnob->tx_ctxt[start]) = wrb_cnt;
-	index_adv(&start, wrb_cnt - 1, pnob->tx_q_len);
-	pnob->tx_ctxt[start] = skb;
-}
-
-static int benet_xmit(struct sk_buff *skb, struct net_device *netdev)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-	u32 wrb_cnt, copied = 0;
-	u32 start = pnob->tx_q_hd;
-
-	adapter->be_stat.bes_tx_reqs++;
-
-	wrb_cnt = wrb_cnt_in_skb(skb);
-	spin_lock_bh(&adapter->txq_lock);
-	if ((pnob->tx_q_len - 2 - atomic_read(&pnob->tx_q_used)) <= wrb_cnt) {
-		netif_stop_queue(pnob->netdev);
-		spin_unlock_bh(&adapter->txq_lock);
-		adapter->be_stat.bes_tx_fails++;
-		return NETDEV_TX_BUSY;
-	}
-	spin_unlock_bh(&adapter->txq_lock);
-
-	wrb_cnt = copy_skb_to_txq(pnob, skb, wrb_cnt, &copied);
-	be_tx_wrb_info_remember(pnob, skb, wrb_cnt, start);
-
-	be_start_tx(pnob, wrb_cnt);
-
-	adapter->eth_tx_bytes += copied;
-	adapter->be_stat.bes_tx_wrbs += wrb_cnt;
-	update_tx_rate(adapter);
-	netdev->trans_start = jiffies;
-
-	return NETDEV_TX_OK;
-}
-
-/*
- * This is the driver entry point to change the mtu of the device
- * Returns 0 for success and errno for failure.
- */
-static int benet_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	/*
-	 * BE supports jumbo frame size upto 9000 bytes including the link layer
-	 * header. Considering the different variants of frame formats possible
-	 * like VLAN, SNAP/LLC, the maximum possible value for MTU is 8974 bytes
-	 */
-
-	if (new_mtu < (ETH_ZLEN + ETH_FCS_LEN) || (new_mtu > BE_MAX_MTU)) {
-		dev_info(&netdev->dev, "Invalid MTU requested. "
-			       "Must be between %d and %d bytes\n",
-				       (ETH_ZLEN + ETH_FCS_LEN), BE_MAX_MTU);
-		return -EINVAL;
-	}
-	dev_info(&netdev->dev, "MTU changed from %d to %d\n",
-						netdev->mtu, new_mtu);
-	netdev->mtu = new_mtu;
-	return 0;
-}
-
-/*
- * This is the driver entry point to register a vlan with the device
- */
-static void benet_vlan_register(struct net_device *netdev,
-				struct vlan_group *grp)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-
-	be_disable_eq_intr(pnob);
-	pnob->vlan_grp = grp;
-	pnob->num_vlans = 0;
-	be_enable_eq_intr(pnob);
-}
-
-/*
- * This is the driver entry point to add a vlan vlan_id
- * with the device netdev
- */
-static void benet_vlan_add_vid(struct net_device *netdev, u16 vlan_id)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-
-	if (pnob->num_vlans == (BE_NUM_VLAN_SUPPORTED - 1)) {
-		/* no  way to return an error */
-		dev_info(&netdev->dev,
-		       "BladeEngine: Cannot configure more than %d Vlans\n",
-			       BE_NUM_VLAN_SUPPORTED);
-		return;
-	}
-	/* The new vlan tag will be in the slot indicated by num_vlans. */
-	pnob->vlan_tag[pnob->num_vlans++] = vlan_id;
-	be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans,
-			   pnob->vlan_tag, NULL, NULL, NULL);
-}
-
-/*
- * This is the driver entry point to remove a vlan vlan_id
- * with the device netdev
- */
-static void benet_vlan_rem_vid(struct net_device *netdev, u16 vlan_id)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-
-	u32 i, value;
-
-	/*
-	 * In Blade Engine, we support 32 vlan tag filters across both ports.
-	 * To program a vlan tag, the RXF_RTPR_CSR register is used.
-	 * Each 32-bit value of RXF_RTDR_CSR can address 2 vlan tag entries.
-	 * The Vlan table is of depth 16. thus we support 32 tags.
-	 */
-
-	value = vlan_id | VLAN_VALID_BIT;
-	for (i = 0; i < BE_NUM_VLAN_SUPPORTED; i++) {
-		if (pnob->vlan_tag[i] == vlan_id)
-			break;
-	}
-
-	if (i == BE_NUM_VLAN_SUPPORTED)
-		return;
-	/* Now compact the vlan tag array by removing hole created. */
-	while ((i + 1) < BE_NUM_VLAN_SUPPORTED) {
-		pnob->vlan_tag[i] = pnob->vlan_tag[i + 1];
-		i++;
-	}
-	if ((i + 1) == BE_NUM_VLAN_SUPPORTED)
-		pnob->vlan_tag[i] = (u16) 0x0;
-	pnob->num_vlans--;
-	be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans,
-			   pnob->vlan_tag, NULL, NULL, NULL);
-}
-
-/*
- * This function is called to program multicast
- * address in the multicast filter of the ASIC.
- */
-static void be_set_multicast_filter(struct net_device *netdev)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct dev_mc_list *mc_ptr;
-	u8 mac_addr[32][ETH_ALEN];
-	int i;
-
-	if (netdev->flags & IFF_ALLMULTI) {
-		/* set BE in Multicast promiscuous */
-		be_rxf_multicast_config(&pnob->fn_obj, true, 0, NULL, NULL,
-					NULL, NULL);
-		return;
-	}
-
-	for (mc_ptr = netdev->mc_list, i = 0; mc_ptr;
-	     mc_ptr = mc_ptr->next, i++) {
-		memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN);
-	}
-
-	/* reset the promiscuous mode also. */
-	be_rxf_multicast_config(&pnob->fn_obj, false, i,
-				&mac_addr[0][0], NULL, NULL, NULL);
-}
-
-/*
- * This is the driver entry point to set multicast list
- * with the device netdev. This function will be used to
- * set promiscuous mode or multicast promiscuous mode
- * or multicast mode....
- */
-static void benet_set_multicast_list(struct net_device *netdev)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-
-	if (netdev->flags & IFF_PROMISC) {
-		be_rxf_promiscuous(&pnob->fn_obj, 1, 1, NULL, NULL, NULL);
-	} else {
-		be_rxf_promiscuous(&pnob->fn_obj, 0, 0, NULL, NULL, NULL);
-		be_set_multicast_filter(netdev);
-	}
-}
-
-int benet_init(struct net_device *netdev)
-{
-	struct be_net_object *pnob = netdev_priv(netdev);
-	struct be_adapter *adapter = pnob->adapter;
-
-	ether_setup(netdev);
-
-	netdev->open = &benet_open;
-	netdev->stop = &benet_close;
-	netdev->hard_start_xmit = &benet_xmit;
-
-	netdev->get_stats = &benet_get_stats;
-
-	netdev->set_multicast_list = &benet_set_multicast_list;
-
-	netdev->change_mtu = &benet_change_mtu;
-	netdev->set_mac_address = &benet_set_mac_addr;
-
-	netdev->vlan_rx_register = benet_vlan_register;
-	netdev->vlan_rx_add_vid = benet_vlan_add_vid;
-	netdev->vlan_rx_kill_vid = benet_vlan_rem_vid;
-
-	netdev->features =
-	    NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
-	    NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM;
-
-	netdev->flags |= IFF_MULTICAST;
-
-	/* If device is DAC Capable, set the HIGHDMA flag for netdevice. */
-	if (adapter->dma_64bit_cap)
-		netdev->features |= NETIF_F_HIGHDMA;
-
-	SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
-	return 0;
-}
diff --git a/drivers/staging/benet/benet.h b/drivers/staging/benet/benet.h
deleted file mode 100644
index 09a1f08..0000000
--- a/drivers/staging/benet/benet.h
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#ifndef _BENET_H_
-#define _BENET_H_
-
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/inet_lro.h>
-#include "hwlib.h"
-
-#define _SA_MODULE_NAME "net-driver"
-
-#define VLAN_VALID_BIT		0x8000
-#define BE_NUM_VLAN_SUPPORTED	32
-#define BE_PORT_LINK_DOWN       0000
-#define BE_PORT_LINK_UP         0001
-#define	BE_MAX_TX_FRAG_COUNT		(30)
-
-/* Flag bits for send operation */
-#define IPCS            (1 << 0)	/* Enable IP checksum offload */
-#define UDPCS           (1 << 1)	/* Enable UDP checksum offload */
-#define TCPCS           (1 << 2)	/* Enable TCP checksum offload */
-#define LSO             (1 << 3)	/* Enable Large Segment  offload */
-#define ETHVLAN         (1 << 4)	/* Enable VLAN insert */
-#define ETHEVENT        (1 << 5)	/* Generate  event on completion */
-#define ETHCOMPLETE     (1 << 6)	/* Generate completion when done */
-#define IPSEC           (1 << 7)	/* Enable IPSEC */
-#define FORWARD         (1 << 8)	/* Send the packet in forwarding path */
-#define FIN             (1 << 9)	/* Issue FIN segment */
-
-#define BE_MAX_MTU	8974
-
-#define BE_MAX_LRO_DESCRIPTORS			8
-#define BE_LRO_MAX_PKTS				64
-#define BE_MAX_FRAGS_PER_FRAME			6
-
-extern const char be_drvr_ver[];
-extern char be_fw_ver[];
-extern char be_driver_name[];
-
-extern struct ethtool_ops be_ethtool_ops;
-
-#define BE_DEV_STATE_NONE 0
-#define BE_DEV_STATE_INIT 1
-#define BE_DEV_STATE_OPEN 2
-#define BE_DEV_STATE_SUSPEND 3
-
-/* This structure is used to describe physical fragments to use
- * for DMAing data from NIC.
- */
-struct be_recv_buffer {
-	struct list_head rxb_list;	/* for maintaining a linked list */
-	void *rxb_va;		/* buffer virtual address */
-	u32 rxb_pa_lo;		/* low part of physical address */
-	u32 rxb_pa_hi;		/* high part of physical address */
-	u32 rxb_len;		/* length of recv buffer */
-	void *rxb_ctxt;		/* context for OSM driver to use */
-};
-
-/*
- * fragment list to describe scattered data.
- */
-struct be_tx_frag_list {
-	u32 txb_len;		/* Size of this fragment */
-	u32 txb_pa_lo;		/* Lower 32 bits of 64 bit physical addr */
-	u32 txb_pa_hi;		/* Higher 32 bits of 64 bit physical addr */
-};
-
-struct be_rx_page_info {
-	struct page *page;
-	dma_addr_t bus;
-	u16 page_offset;
-};
-
-/*
- *  This structure is the main tracking structure for a NIC interface.
- */
-struct be_net_object {
-	/* MCC Ring - used to send fwcmds to embedded ARM processor */
-	struct MCC_WRB_AMAP *mcc_q;	/* VA of the start of the ring */
-	u32 mcc_q_len;			/* # of WRB entries in this ring */
-	u32 mcc_q_size;
-	u32 mcc_q_hd;			/* MCC ring head */
-	u8 mcc_q_created;		/* flag to help cleanup */
-	struct be_mcc_object mcc_q_obj;	/* BECLIB's MCC ring Object */
-	dma_addr_t mcc_q_bus;		/* DMA'ble bus address */
-
-	/* MCC Completion Ring - FW responses to fwcmds sent from MCC ring */
-	struct MCC_CQ_ENTRY_AMAP *mcc_cq; /* VA of the start of the ring */
-	u32 mcc_cq_len;			/* # of compl. entries in this ring */
-	u32 mcc_cq_size;
-	u32 mcc_cq_tl;			/* compl. ring tail */
-	u8 mcc_cq_created;		/* flag to help cleanup */
-	struct be_cq_object mcc_cq_obj;	/* BECLIB's MCC compl. ring object */
-	u32 mcc_cq_id;			/* MCC ring ID */
-	dma_addr_t mcc_cq_bus;		/* DMA'ble bus address */
-
-	struct ring_desc mb_rd;		/* RD for MCC_MAIL_BOX */
-	void *mb_ptr;			/* mailbox ptr to be freed  */
-	dma_addr_t mb_bus;		/* DMA'ble bus address */
-	u32 mb_size;
-
-	/* BEClib uses an array of context objects to track outstanding
-	 * requests to the MCC.  We need allocate the same number of
-	 * conext entries as the number of entries in the MCC WRB ring
-	 */
-	u32 mcc_wrb_ctxt_size;
-	void *mcc_wrb_ctxt;		/* pointer to the context area */
-	u32 mcc_wrb_ctxtLen;		/* Number of entries in the context */
-	/*
-	 * NIC send request ring - used for xmitting raw ether frames.
-	 */
-	struct ETH_WRB_AMAP *tx_q;	/* VA of the start of the ring */
-	u32 tx_q_len;			/* # if entries in the send ring */
-	u32 tx_q_size;
-	u32 tx_q_hd;			/* Head index. Next req. goes here */
-	u32 tx_q_tl;			/* Tail indx. oldest outstanding req. */
-	u8 tx_q_created;		/* flag to help cleanup */
-	struct be_ethsq_object tx_q_obj;/* BECLIB's send Q handle */
-	dma_addr_t tx_q_bus;		/* DMA'ble bus address */
-	u32 tx_q_id;			/* send queue ring ID */
-	u32 tx_q_port;			/* 0 no binding, 1 port A,  2 port B */
-	atomic_t tx_q_used;		/* # of WRBs used */
-	/* ptr to an array in which we store context info for each send req. */
-	void **tx_ctxt;
-	/*
-	 * NIC Send compl. ring - completion status for all NIC frames xmitted.
-	 */
-	struct ETH_TX_COMPL_AMAP *tx_cq;/* VA of start of the ring */
-	u32 txcq_len;			/* # of entries in the ring */
-	u32 tx_cq_size;
-	/*
-	 * index into compl ring where the host expects next completion entry
-	 */
-	u32 tx_cq_tl;
-	u32 tx_cq_id;			/* completion queue id */
-	u8 tx_cq_created;		/* flag to help cleanup */
-	struct be_cq_object tx_cq_obj;
-	dma_addr_t tx_cq_bus;		/* DMA'ble bus address */
-	/*
-	 * Event Queue - all completion entries post events here.
-	 */
-	struct EQ_ENTRY_AMAP *event_q;	/* VA of start of event queue */
-	u32 event_q_len;		/* # of entries */
-	u32 event_q_size;
-	u32 event_q_tl;			/* Tail of the event queue */
-	u32 event_q_id;			/* Event queue ID */
-	u8 event_q_created;		/* flag to help cleanup */
-	struct be_eq_object event_q_obj; /* Queue handle */
-	dma_addr_t event_q_bus;		/* DMA'ble bus address */
-	/*
-	 * NIC receive queue - Data buffers to be used for receiving unicast,
-	 * broadcast and multi-cast frames  are posted here.
-	 */
-	struct ETH_RX_D_AMAP *rx_q;	/* VA of start of the queue */
-	u32 rx_q_len;			/* # of entries */
-	u32 rx_q_size;
-	u32 rx_q_hd;			/* Head of the queue */
-	atomic_t rx_q_posted;		/* number of posted buffers */
-	u32 rx_q_id;			/* queue ID */
-	u8 rx_q_created;		/* flag to help cleanup */
-	struct be_ethrq_object rx_q_obj;	/* NIC RX queue handle */
-	dma_addr_t rx_q_bus;		/* DMA'ble bus address */
-	/*
-	 * Pointer to an array of opaque context object for use by OSM driver
-	 */
-	void **rx_ctxt;
-	/*
-	 * NIC unicast RX completion queue - all unicast ether frame completion
-	 * statuses from BE come here.
-	 */
-	struct ETH_RX_COMPL_AMAP *rx_cq;	/* VA of start of the queue */
-	u32 rx_cq_len;		/* # of entries */
-	u32 rx_cq_size;
-	u32 rx_cq_tl;			/* Tail of the queue */
-	u32 rx_cq_id;			/* queue ID */
-	u8 rx_cq_created;		/* flag to help cleanup */
-	struct be_cq_object rx_cq_obj;	/* queue handle */
-	dma_addr_t rx_cq_bus;		/* DMA'ble bus address */
-	struct be_function_object fn_obj;	/* function object   */
-	bool	fn_obj_created;
-	u32 rx_buf_size;		/* Size of the RX buffers */
-
-	struct net_device *netdev;
-	struct be_recv_buffer eth_rx_bufs[256];	/* to pass Rx buffer
-							   addresses */
-	struct be_adapter *adapter;	/* Pointer to OSM adapter */
-	u32 devno;		/* OSM, network dev no. */
-	u32 use_port;		/* Current active port */
-	struct be_rx_page_info *rx_page_info;	/* Array of Rx buf pages */
-	u32 rx_pg_info_hd;	/* Head of queue */
-	int rxbuf_post_fail;	/* RxBuff posting fail count */
-	bool rx_pg_shared;	/* Is an allocsted page shared as two frags ? */
-	struct vlan_group *vlan_grp;
-	u32 num_vlans;		/* Number of vlans in BE's filter */
-	u16 vlan_tag[BE_NUM_VLAN_SUPPORTED]; /* vlans currently configured */
-	struct napi_struct napi;
-	struct net_lro_mgr lro_mgr;
-	struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS];
-};
-
-#define NET_FH(np)       (&(np)->fn_obj)
-
-/*
- * BE driver statistics.
- */
-struct be_drvr_stat {
-	u32 bes_tx_reqs;	/* number of TX requests initiated */
-	u32 bes_tx_fails;	/* number of TX requests that failed */
-	u32 bes_fwd_reqs;	/* number of send reqs through forwarding i/f */
-	u32 bes_tx_wrbs;	/* number of tx WRBs used */
-
-	u32 bes_ints;		/* number of interrupts */
-	u32 bes_polls;		/* number of times NAPI called poll function */
-	u32 bes_events;		/* total evet entries processed */
-	u32 bes_tx_events;	/* number of tx completion events  */
-	u32 bes_rx_events;	/* number of ucast rx completion events  */
-	u32 bes_tx_compl;	/* number of tx completion entries processed */
-	u32 bes_rx_compl;	/* number of rx completion entries
-				   processed */
-	u32 bes_ethrx_post_fail;	/* number of ethrx buffer alloc
-					   failures */
-	/*
-	 * number of non ether type II frames dropped where
-	 * frame len > length field of Mac Hdr
-	 */
-	u32 bes_802_3_dropped_frames;
-	/*
-	 * number of non ether type II frames malformed where
-	 * in frame len < length field of Mac Hdr
-	 */
-	u32 bes_802_3_malformed_frames;
-	u32 bes_ips;		/*  interrupts / sec */
-	u32 bes_prev_ints;	/* bes_ints at last IPS calculation  */
-	u16 bes_eth_tx_rate;	/*  ETH TX rate - Mb/sec */
-	u16 bes_eth_rx_rate;	/*  ETH RX rate - Mb/sec */
-	u32 bes_rx_coal;	/* Num pkts coalasced */
-	u32 bes_rx_flush;	/* Num times coalasced */
-	u32 bes_link_change_physical;	/*Num of times physical link changed */
-	u32 bes_link_change_virtual;	/*Num of times virtual link changed */
-	u32 bes_rx_misc_pkts;	/* Misc pkts received */
-};
-
-/* Maximum interrupt delay (in microseconds) allowed */
-#define MAX_EQD				120
-
-/*
- * timer to prevent system shutdown hang for ever if h/w stops responding
- */
-struct be_timer_ctxt {
-	atomic_t get_stat_flag;
-	struct timer_list get_stats_timer;
-	unsigned long get_stat_sem_addr;
-} ;
-
-/* This structure is the main BladeEngine driver context.  */
-struct be_adapter {
-	struct net_device *netdevp;
-	struct be_drvr_stat be_stat;
-	struct net_device_stats benet_stats;
-
-	/* PCI BAR mapped addresses */
-	u8 __iomem *csr_va;	/* CSR */
-	u8 __iomem *db_va;	/* Door  Bell  */
-	u8 __iomem *pci_va;	/* PCI Config */
-
-	struct tasklet_struct sts_handler;
-	struct timer_list cq_timer;
-	spinlock_t int_lock;	/* to protect the isr field in adapter */
-
-	struct FWCMD_ETH_GET_STATISTICS *eth_statsp;
-	/*
-	 * This will enable the use of ethtool to enable or disable
-	 * Checksum on Rx pkts to be obeyed or disobeyed.
-	 * If this is true = 1, then whatever is the checksum on the
-	 * Received pkt as per BE, it will be given to the stack.
-	 * Else the stack will re calculate it.
-	 */
-	bool rx_csum;
-	/*
-	 * This will enable the use of ethtool to enable or disable
-	 * Coalese on Rx pkts to be obeyed or disobeyed.
-	 * If this is grater than 0 and less than 16 then coalascing
-	 * is enabled else it is disabled
-	 */
-	u32 max_rx_coal;
-	struct pci_dev *pdev;	/* Pointer to OS's PCI dvice */
-
-	spinlock_t txq_lock;	/* to stop/wake queue based on tx_q_used */
-
-	u32 isr;		/* copy of Intr status reg. */
-
-	u32 port0_link_sts;	/* Port 0 link status */
-	u32 port1_link_sts;	/* port 1 list status */
-	struct BE_LINK_STATUS *be_link_sts;
-
-	/* pointer to the first netobject of this adapter */
-	struct be_net_object *net_obj;
-
-	/*  Flags to indicate what to clean up */
-	bool tasklet_started;
-	bool isr_registered;
-	/*
-	 * adaptive interrupt coalescing (AIC) related
-	 */
-	bool enable_aic;	/* 1 if AIC is enabled */
-	u16 min_eqd;		/* minimum EQ delay in usec */
-	u16 max_eqd;		/* minimum EQ delay in usec */
-	u16 cur_eqd;		/* current EQ delay in usec */
-	/*
-	 * book keeping for interrupt / sec and TX/RX rate calculation
-	 */
-	ulong ips_jiffies;	/* jiffies at last IPS calc */
-	u32 eth_tx_bytes;
-	ulong eth_tx_jiffies;
-	u32 eth_rx_bytes;
-	ulong eth_rx_jiffies;
-
-	struct semaphore get_eth_stat_sem;
-
-	/* timer ctxt to prevent shutdown hanging due to un-responsive BE */
-	struct be_timer_ctxt timer_ctxt;
-
-#define BE_MAX_MSIX_VECTORS             32
-#define BE_MAX_REQ_MSIX_VECTORS         1 /* only one EQ in Linux driver */
-	struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS];
-	bool msix_enabled;
-	bool dma_64bit_cap;	/* the Device DAC capable  or not */
-	u8 dev_state;	/* The current state of the device */
-	u8 dev_pm_state; /* The State of device before going to suspend */
-};
-
-/*
- * Every second we look at the ints/sec and adjust eq_delay
- * between adapter->min_eqd and adapter->max_eqd to keep the ints/sec between
- * IPS_HI_WM and IPS_LO_WM.
- */
-#define IPS_HI_WM	18000
-#define IPS_LO_WM	8000
-
-
-static inline void index_adv(u32 *index, u32 val,  u32 limit)
-{
-	BUG_ON(limit & (limit-1));
-	*index = (*index + val) & (limit - 1);
-}
-
-static inline void index_inc(u32 *index, u32 limit)
-{
-	BUG_ON(limit & (limit-1));
-	*index = (*index + 1) & (limit - 1);
-}
-
-static inline void be_adv_eq_tl(struct be_net_object *pnob)
-{
-	index_inc(&pnob->event_q_tl, pnob->event_q_len);
-}
-
-static inline void be_adv_txq_hd(struct be_net_object *pnob)
-{
-	index_inc(&pnob->tx_q_hd, pnob->tx_q_len);
-}
-
-static inline void be_adv_txq_tl(struct be_net_object *pnob)
-{
-	index_inc(&pnob->tx_q_tl, pnob->tx_q_len);
-}
-
-static inline void be_adv_txcq_tl(struct be_net_object *pnob)
-{
-	index_inc(&pnob->tx_cq_tl, pnob->txcq_len);
-}
-
-static inline void be_adv_rxq_hd(struct be_net_object *pnob)
-{
-	index_inc(&pnob->rx_q_hd, pnob->rx_q_len);
-}
-
-static inline void be_adv_rxcq_tl(struct be_net_object *pnob)
-{
-	index_inc(&pnob->rx_cq_tl, pnob->rx_cq_len);
-}
-
-static inline u32 tx_compl_lastwrb_idx_get(struct be_net_object *pnob)
-{
-	return (pnob->tx_q_tl + *(u32 *)&pnob->tx_ctxt[pnob->tx_q_tl] - 1)
-		    & (pnob->tx_q_len - 1);
-}
-
-int benet_init(struct net_device *);
-int be_ethtool_ioctl(struct net_device *, struct ifreq *);
-struct net_device_stats *benet_get_stats(struct net_device *);
-void be_process_intr(unsigned long context);
-irqreturn_t be_int(int irq, void *dev);
-void be_post_eth_rx_buffs(struct be_net_object *);
-void be_get_stat_cb(void *, int, struct MCC_WRB_AMAP *);
-void be_get_stats_timer_handler(unsigned long);
-void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *);
-void be_print_link_info(struct BE_LINK_STATUS *);
-void be_update_link_status(struct be_adapter *);
-void be_init_procfs(struct be_adapter *);
-void be_cleanup_procfs(struct be_adapter *);
-int be_poll(struct napi_struct *, int);
-struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *);
-void be_notify_cmpl(struct be_net_object *, int, int, int);
-void be_enable_intr(struct be_net_object *);
-void be_enable_eq_intr(struct be_net_object *);
-void be_disable_intr(struct be_net_object *);
-void be_disable_eq_intr(struct be_net_object *);
-int be_set_uc_mac_adr(struct be_net_object *, u8, u8, u8,
-		    u8 *, mcc_wrb_cqe_callback, void *);
-int be_get_flow_ctl(struct be_function_object *pFnObj, bool *, bool *);
-void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx);
-
-#endif /* _BENET_H_ */
diff --git a/drivers/staging/benet/bestatus.h b/drivers/staging/benet/bestatus.h
deleted file mode 100644
index 59c7a4b6..0000000
--- a/drivers/staging/benet/bestatus.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#ifndef _BESTATUS_H_
-#define _BESTATUS_H_
-
-#define BE_SUCCESS                      (0x00000000L)
-/*
- * MessageId: BE_PENDING
- *  The BladeEngine Driver call succeeded, and pended operation.
- */
-#define BE_PENDING                       (0x20070001L)
-#define BE_STATUS_PENDING                (BE_PENDING)
-/*
- * MessageId: BE_NOT_OK
- *  An error occurred.
- */
-#define BE_NOT_OK                        (0xE0070002L)
-/*
- * MessageId: BE_STATUS_SYSTEM_RESOURCES
- *  Insufficient host system resources exist to complete the API.
- */
-#define BE_STATUS_SYSTEM_RESOURCES       (0xE0070003L)
-/*
- * MessageId: BE_STATUS_CHIP_RESOURCES
- *  Insufficient chip resources exist to complete the API.
- */
-#define BE_STATUS_CHIP_RESOURCES         (0xE0070004L)
-/*
- * MessageId: BE_STATUS_NO_RESOURCE
- *  Insufficient resources to complete request.
- */
-#define BE_STATUS_NO_RESOURCE            (0xE0070005L)
-/*
- * MessageId: BE_STATUS_BUSY
- *  Resource is currently busy.
- */
-#define BE_STATUS_BUSY                   (0xE0070006L)
-/*
- * MessageId: BE_STATUS_INVALID_PARAMETER
- *  Invalid Parameter in request.
- */
-#define BE_STATUS_INVALID_PARAMETER      (0xE0000007L)
-/*
- * MessageId: BE_STATUS_NOT_SUPPORTED
- *  Requested operation is not supported.
- */
-#define BE_STATUS_NOT_SUPPORTED          (0xE000000DL)
-
-/*
- * ***************************************************************************
- *                     E T H E R N E T   S T A T U S
- * ***************************************************************************
- */
-
-/*
- * MessageId: BE_ETH_TX_ERROR
- *  The Ethernet device driver failed to transmit a packet.
- */
-#define BE_ETH_TX_ERROR                  (0xE0070101L)
-
-/*
- * ***************************************************************************
- *                     S H A R E D   S T A T U S
- * ***************************************************************************
- */
-
-/*
- * MessageId: BE_STATUS_VBD_INVALID_VERSION
- *  The device driver is not compatible with this version of the VBD.
- */
-#define BE_STATUS_INVALID_VERSION    (0xE0070402L)
-/*
- * MessageId: BE_STATUS_DOMAIN_DENIED
- *  The operation failed to complete due to insufficient access
- *  rights for the requesting domain.
- */
-#define BE_STATUS_DOMAIN_DENIED          (0xE0070403L)
-/*
- * MessageId: BE_STATUS_TCP_NOT_STARTED
- *  The embedded TCP/IP stack has not been started.
- */
-#define BE_STATUS_TCP_NOT_STARTED        (0xE0070409L)
-/*
- * MessageId: BE_STATUS_NO_MCC_WRB
- *  No free MCC WRB are available for posting the request.
- */
-#define BE_STATUS_NO_MCC_WRB                 (0xE0070414L)
-
-#endif /* _BESTATUS_ */
diff --git a/drivers/staging/benet/cev.h b/drivers/staging/benet/cev.h
deleted file mode 100644
index 3099692..0000000
--- a/drivers/staging/benet/cev.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __cev_amap_h__
-#define __cev_amap_h__
-#include "ep.h"
-
-/*
- * Host Interrupt Status Register 0. The first of four application
- * interrupt status registers. This register contains the interrupts
- * for Event Queues EQ0 through EQ31.
- */
-struct BE_CEV_ISR0_CSR_AMAP {
-	u8 interrupt0;	/* DWORD 0 */
-	u8 interrupt1;	/* DWORD 0 */
-	u8 interrupt2;	/* DWORD 0 */
-	u8 interrupt3;	/* DWORD 0 */
-	u8 interrupt4;	/* DWORD 0 */
-	u8 interrupt5;	/* DWORD 0 */
-	u8 interrupt6;	/* DWORD 0 */
-	u8 interrupt7;	/* DWORD 0 */
-	u8 interrupt8;	/* DWORD 0 */
-	u8 interrupt9;	/* DWORD 0 */
-	u8 interrupt10;	/* DWORD 0 */
-	u8 interrupt11;	/* DWORD 0 */
-	u8 interrupt12;	/* DWORD 0 */
-	u8 interrupt13;	/* DWORD 0 */
-	u8 interrupt14;	/* DWORD 0 */
-	u8 interrupt15;	/* DWORD 0 */
-	u8 interrupt16;	/* DWORD 0 */
-	u8 interrupt17;	/* DWORD 0 */
-	u8 interrupt18;	/* DWORD 0 */
-	u8 interrupt19;	/* DWORD 0 */
-	u8 interrupt20;	/* DWORD 0 */
-	u8 interrupt21;	/* DWORD 0 */
-	u8 interrupt22;	/* DWORD 0 */
-	u8 interrupt23;	/* DWORD 0 */
-	u8 interrupt24;	/* DWORD 0 */
-	u8 interrupt25;	/* DWORD 0 */
-	u8 interrupt26;	/* DWORD 0 */
-	u8 interrupt27;	/* DWORD 0 */
-	u8 interrupt28;	/* DWORD 0 */
-	u8 interrupt29;	/* DWORD 0 */
-	u8 interrupt30;	/* DWORD 0 */
-	u8 interrupt31;	/* DWORD 0 */
-} __packed;
-struct CEV_ISR0_CSR_AMAP {
-	u32 dw[1];
-};
-
-/*
- * Host Interrupt Status Register 1. The second of four application
- * interrupt status registers. This register contains the interrupts
- * for Event Queues EQ32 through EQ63.
- */
-struct BE_CEV_ISR1_CSR_AMAP {
-	u8 interrupt32;	/* DWORD 0 */
-	u8 interrupt33;	/* DWORD 0 */
-	u8 interrupt34;	/* DWORD 0 */
-	u8 interrupt35;	/* DWORD 0 */
-	u8 interrupt36;	/* DWORD 0 */
-	u8 interrupt37;	/* DWORD 0 */
-	u8 interrupt38;	/* DWORD 0 */
-	u8 interrupt39;	/* DWORD 0 */
-	u8 interrupt40;	/* DWORD 0 */
-	u8 interrupt41;	/* DWORD 0 */
-	u8 interrupt42;	/* DWORD 0 */
-	u8 interrupt43;	/* DWORD 0 */
-	u8 interrupt44;	/* DWORD 0 */
-	u8 interrupt45;	/* DWORD 0 */
-	u8 interrupt46;	/* DWORD 0 */
-	u8 interrupt47;	/* DWORD 0 */
-	u8 interrupt48;	/* DWORD 0 */
-	u8 interrupt49;	/* DWORD 0 */
-	u8 interrupt50;	/* DWORD 0 */
-	u8 interrupt51;	/* DWORD 0 */
-	u8 interrupt52;	/* DWORD 0 */
-	u8 interrupt53;	/* DWORD 0 */
-	u8 interrupt54;	/* DWORD 0 */
-	u8 interrupt55;	/* DWORD 0 */
-	u8 interrupt56;	/* DWORD 0 */
-	u8 interrupt57;	/* DWORD 0 */
-	u8 interrupt58;	/* DWORD 0 */
-	u8 interrupt59;	/* DWORD 0 */
-	u8 interrupt60;	/* DWORD 0 */
-	u8 interrupt61;	/* DWORD 0 */
-	u8 interrupt62;	/* DWORD 0 */
-	u8 interrupt63;	/* DWORD 0 */
-} __packed;
-struct CEV_ISR1_CSR_AMAP {
-	u32 dw[1];
-};
-/*
- * Host Interrupt Status Register 2. The third of four application
- * interrupt status registers. This register contains the interrupts
- * for Event Queues EQ64 through EQ95.
- */
-struct BE_CEV_ISR2_CSR_AMAP {
-	u8 interrupt64;	/* DWORD 0 */
-	u8 interrupt65;	/* DWORD 0 */
-	u8 interrupt66;	/* DWORD 0 */
-	u8 interrupt67;	/* DWORD 0 */
-	u8 interrupt68;	/* DWORD 0 */
-	u8 interrupt69;	/* DWORD 0 */
-	u8 interrupt70;	/* DWORD 0 */
-	u8 interrupt71;	/* DWORD 0 */
-	u8 interrupt72;	/* DWORD 0 */
-	u8 interrupt73;	/* DWORD 0 */
-	u8 interrupt74;	/* DWORD 0 */
-	u8 interrupt75;	/* DWORD 0 */
-	u8 interrupt76;	/* DWORD 0 */
-	u8 interrupt77;	/* DWORD 0 */
-	u8 interrupt78;	/* DWORD 0 */
-	u8 interrupt79;	/* DWORD 0 */
-	u8 interrupt80;	/* DWORD 0 */
-	u8 interrupt81;	/* DWORD 0 */
-	u8 interrupt82;	/* DWORD 0 */
-	u8 interrupt83;	/* DWORD 0 */
-	u8 interrupt84;	/* DWORD 0 */
-	u8 interrupt85;	/* DWORD 0 */
-	u8 interrupt86;	/* DWORD 0 */
-	u8 interrupt87;	/* DWORD 0 */
-	u8 interrupt88;	/* DWORD 0 */
-	u8 interrupt89;	/* DWORD 0 */
-	u8 interrupt90;	/* DWORD 0 */
-	u8 interrupt91;	/* DWORD 0 */
-	u8 interrupt92;	/* DWORD 0 */
-	u8 interrupt93;	/* DWORD 0 */
-	u8 interrupt94;	/* DWORD 0 */
-	u8 interrupt95;	/* DWORD 0 */
-} __packed;
-struct CEV_ISR2_CSR_AMAP {
-	u32 dw[1];
-};
-
-/*
- * Host Interrupt Status Register 3. The fourth of four application
- * interrupt status registers. This register contains the interrupts
- * for Event Queues EQ96 through EQ127.
- */
-struct BE_CEV_ISR3_CSR_AMAP {
-	u8 interrupt96;	/* DWORD 0 */
-	u8 interrupt97;	/* DWORD 0 */
-	u8 interrupt98;	/* DWORD 0 */
-	u8 interrupt99;	/* DWORD 0 */
-	u8 interrupt100;	/* DWORD 0 */
-	u8 interrupt101;	/* DWORD 0 */
-	u8 interrupt102;	/* DWORD 0 */
-	u8 interrupt103;	/* DWORD 0 */
-	u8 interrupt104;	/* DWORD 0 */
-	u8 interrupt105;	/* DWORD 0 */
-	u8 interrupt106;	/* DWORD 0 */
-	u8 interrupt107;	/* DWORD 0 */
-	u8 interrupt108;	/* DWORD 0 */
-	u8 interrupt109;	/* DWORD 0 */
-	u8 interrupt110;	/* DWORD 0 */
-	u8 interrupt111;	/* DWORD 0 */
-	u8 interrupt112;	/* DWORD 0 */
-	u8 interrupt113;	/* DWORD 0 */
-	u8 interrupt114;	/* DWORD 0 */
-	u8 interrupt115;	/* DWORD 0 */
-	u8 interrupt116;	/* DWORD 0 */
-	u8 interrupt117;	/* DWORD 0 */
-	u8 interrupt118;	/* DWORD 0 */
-	u8 interrupt119;	/* DWORD 0 */
-	u8 interrupt120;	/* DWORD 0 */
-	u8 interrupt121;	/* DWORD 0 */
-	u8 interrupt122;	/* DWORD 0 */
-	u8 interrupt123;	/* DWORD 0 */
-	u8 interrupt124;	/* DWORD 0 */
-	u8 interrupt125;	/* DWORD 0 */
-	u8 interrupt126;	/* DWORD 0 */
-	u8 interrupt127;	/* DWORD 0 */
-} __packed;
-struct CEV_ISR3_CSR_AMAP {
-	u32 dw[1];
-};
-
-/*  Completions and Events block Registers.  */
-struct BE_CEV_CSRMAP_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-	u8 rsvd1[32];	/* DWORD 1 */
-	u8 rsvd2[32];	/* DWORD 2 */
-	u8 rsvd3[32];	/* DWORD 3 */
-	struct BE_CEV_ISR0_CSR_AMAP isr0;
-	struct BE_CEV_ISR1_CSR_AMAP isr1;
-	struct BE_CEV_ISR2_CSR_AMAP isr2;
-	struct BE_CEV_ISR3_CSR_AMAP isr3;
-	u8 rsvd4[32];	/* DWORD 8 */
-	u8 rsvd5[32];	/* DWORD 9 */
-	u8 rsvd6[32];	/* DWORD 10 */
-	u8 rsvd7[32];	/* DWORD 11 */
-	u8 rsvd8[32];	/* DWORD 12 */
-	u8 rsvd9[32];	/* DWORD 13 */
-	u8 rsvd10[32];	/* DWORD 14 */
-	u8 rsvd11[32];	/* DWORD 15 */
-	u8 rsvd12[32];	/* DWORD 16 */
-	u8 rsvd13[32];	/* DWORD 17 */
-	u8 rsvd14[32];	/* DWORD 18 */
-	u8 rsvd15[32];	/* DWORD 19 */
-	u8 rsvd16[32];	/* DWORD 20 */
-	u8 rsvd17[32];	/* DWORD 21 */
-	u8 rsvd18[32];	/* DWORD 22 */
-	u8 rsvd19[32];	/* DWORD 23 */
-	u8 rsvd20[32];	/* DWORD 24 */
-	u8 rsvd21[32];	/* DWORD 25 */
-	u8 rsvd22[32];	/* DWORD 26 */
-	u8 rsvd23[32];	/* DWORD 27 */
-	u8 rsvd24[32];	/* DWORD 28 */
-	u8 rsvd25[32];	/* DWORD 29 */
-	u8 rsvd26[32];	/* DWORD 30 */
-	u8 rsvd27[32];	/* DWORD 31 */
-	u8 rsvd28[32];	/* DWORD 32 */
-	u8 rsvd29[32];	/* DWORD 33 */
-	u8 rsvd30[192];	/* DWORD 34 */
-	u8 rsvd31[192];	/* DWORD 40 */
-	u8 rsvd32[160];	/* DWORD 46 */
-	u8 rsvd33[160];	/* DWORD 51 */
-	u8 rsvd34[160];	/* DWORD 56 */
-	u8 rsvd35[96];	/* DWORD 61 */
-	u8 rsvd36[192][32];	/* DWORD 64 */
-} __packed;
-struct CEV_CSRMAP_AMAP {
-	u32 dw[256];
-};
-
-#endif /* __cev_amap_h__ */
diff --git a/drivers/staging/benet/cq.c b/drivers/staging/benet/cq.c
deleted file mode 100644
index 6504586..0000000
--- a/drivers/staging/benet/cq.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#include "hwlib.h"
-#include "bestatus.h"
-
-/*
- * Completion Queue Objects
- */
-/*
- *============================================================================
- *                  P U B L I C  R O U T I N E S
- *============================================================================
- */
-
-/*
-    This routine creates a completion queue based on the client completion
-    queue configuration information.
-
-
-    FunctionObject      - Handle to a function object
-    CqBaseVa            - Base VA for a the CQ ring
-    NumEntries          - CEV_CQ_CNT_* values
-    solEventEnable      - 0 = All CQEs can generate Events if CQ is eventable
-			1 = only CQEs with solicited bit set are eventable
-    eventable           - Eventable CQ, generates interrupts.
-    nodelay             - 1 = Force interrupt, relevent if CQ eventable.
-			Interrupt is asserted immediately after EQE
-			write is confirmed, regardless of EQ Timer
-			or watermark settings.
-    wme                 - Enable watermark based coalescing
-    wmThresh            - High watermark(CQ fullness at which event
-			or interrupt should be asserted).  These are the
-			CEV_WATERMARK encoded values.
-    EqObject            - EQ Handle to assign to this CQ
-    ppCqObject          - Internal CQ Handle returned.
-
-    Returns BE_SUCCESS if successfull, otherwise a useful error code is
-	returned.
-
-    IRQL < DISPATCH_LEVEL
-
-*/
-int be_cq_create(struct be_function_object *pfob,
-	struct ring_desc *rd, u32 length, bool solicited_eventable,
-	bool no_delay, u32 wm_thresh,
-	struct be_eq_object *eq_object, struct be_cq_object *cq_object)
-{
-	int status = BE_SUCCESS;
-	u32 num_entries_encoding;
-	u32 num_entries = length / sizeof(struct MCC_CQ_ENTRY_AMAP);
-	struct FWCMD_COMMON_CQ_CREATE *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	u32 n;
-	unsigned long irql;
-
-	ASSERT(rd);
-	ASSERT(cq_object);
-	ASSERT(length % sizeof(struct MCC_CQ_ENTRY_AMAP) == 0);
-
-	switch (num_entries) {
-	case 256:
-		num_entries_encoding = CEV_CQ_CNT_256;
-		break;
-	case 512:
-		num_entries_encoding = CEV_CQ_CNT_512;
-		break;
-	case 1024:
-		num_entries_encoding = CEV_CQ_CNT_1024;
-		break;
-	default:
-		ASSERT(0);
-		return BE_STATUS_INVALID_PARAMETER;
-	}
-
-	/*
-	 * All cq entries all the same size.  Use iSCSI version
-	 * as a test for the proper rd length.
-	 */
-	memset(cq_object, 0, sizeof(*cq_object));
-
-	atomic_set(&cq_object->ref_count, 0);
-	cq_object->parent_function = pfob;
-	cq_object->eq_object = eq_object;
-	cq_object->num_entries = num_entries;
-	/* save for MCC cq processing */
-	cq_object->va = rd->va;
-
-	/* map into UT. */
-	length = num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP);
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		ASSERT(wrb);
-		TRACE(DL_ERR, "No free MCC WRBs in create EQ.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto Error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_CQ_CREATE);
-
-	fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va),
-									length);
-
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, valid, &fwcmd->params.request.context, 1);
-	n = pfob->pci_function_number;
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, Func, &fwcmd->params.request.context, n);
-
-	n = (eq_object != NULL);
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, Eventable,
-				&fwcmd->params.request.context, n);
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, Armed, &fwcmd->params.request.context, 1);
-
-	n = eq_object ? eq_object->eq_id : 0;
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, EQID, &fwcmd->params.request.context, n);
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, Count,
-			&fwcmd->params.request.context, num_entries_encoding);
-
-	n = 0; /* Protection Domain is always 0 in  Linux  driver */
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, PD, &fwcmd->params.request.context, n);
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, NoDelay,
-				&fwcmd->params.request.context, no_delay);
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, SolEvent,
-			&fwcmd->params.request.context, solicited_eventable);
-
-	n = (wm_thresh != 0xFFFFFFFF);
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, WME, &fwcmd->params.request.context, n);
-
-	n = (n ? wm_thresh : 0);
-	AMAP_SET_BITS_PTR(CQ_CONTEXT, Watermark,
-				&fwcmd->params.request.context, n);
-	/* Create a page list for the FWCMD. */
-	be_rd_to_pa_list(rd, fwcmd->params.request.pages,
-			  ARRAY_SIZE(fwcmd->params.request.pages));
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-			NULL, NULL, fwcmd, NULL);
-	if (status != BE_SUCCESS) {
-		TRACE(DL_ERR, "MCC to create CQ failed.");
-		goto Error;
-	}
-	/* Remember the CQ id. */
-	cq_object->cq_id = fwcmd->params.response.cq_id;
-
-	/* insert this cq into eq_object reference */
-	if (eq_object) {
-		atomic_inc(&eq_object->ref_count);
-		list_add_tail(&cq_object->cqlist_for_eq,
-					&eq_object->cq_list_head);
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-
-    Deferences the given object. Once the object's reference count drops to
-    zero, the object is destroyed and all resources that are held by this object
-    are released.  The on-chip context is also destroyed along with the queue
-    ID, and any mappings made into the UT.
-
-    cq_object            - CQ handle returned from cq_object_create.
-
-    returns the current reference count on the object
-
-    IRQL: IRQL < DISPATCH_LEVEL
-*/
-int be_cq_destroy(struct be_cq_object *cq_object)
-{
-	int status = 0;
-
-	/* Nothing should reference this CQ at this point. */
-	ASSERT(atomic_read(&cq_object->ref_count) == 0);
-
-	/* Send fwcmd to destroy the CQ. */
-	status = be_function_ring_destroy(cq_object->parent_function,
-		     cq_object->cq_id, FWCMD_RING_TYPE_CQ,
-					NULL, NULL, NULL, NULL);
-	ASSERT(status == 0);
-
-	/* Remove reference if this is an eventable CQ. */
-	if (cq_object->eq_object) {
-		atomic_dec(&cq_object->eq_object->ref_count);
-		list_del(&cq_object->cqlist_for_eq);
-	}
-	return BE_SUCCESS;
-}
-
diff --git a/drivers/staging/benet/descriptors.h b/drivers/staging/benet/descriptors.h
deleted file mode 100644
index 8da438c..0000000
--- a/drivers/staging/benet/descriptors.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __descriptors_amap_h__
-#define __descriptors_amap_h__
-
-/*
- * --- IPC_NODE_ID_ENUM ---
- * IPC processor id values
- */
-#define TPOST_NODE_ID                   (0)	/* TPOST ID */
-#define TPRE_NODE_ID                    (1)	/* TPRE ID */
-#define TXULP0_NODE_ID                  (2)	/* TXULP0 ID */
-#define TXULP1_NODE_ID                  (3)	/* TXULP1 ID */
-#define TXULP2_NODE_ID                  (4)	/* TXULP2 ID */
-#define RXULP0_NODE_ID                  (5)	/* RXULP0 ID */
-#define RXULP1_NODE_ID                  (6)	/* RXULP1 ID */
-#define RXULP2_NODE_ID                  (7)	/* RXULP2 ID */
-#define MPU_NODE_ID                     (15)	/* MPU ID */
-
-/*
- * --- MAC_ID_ENUM ---
- * Meaning of the mac_id field in rxpp_eth_d
- */
-#define PORT0_HOST_MAC0    (0)  /* PD 0, Port 0, host networking, MAC 0. */
-#define PORT0_HOST_MAC1    (1)	/* PD 0, Port 0, host networking, MAC 1. */
-#define PORT0_STORAGE_MAC0 (2)	/* PD 0, Port 0, host storage, MAC 0. */
-#define PORT0_STORAGE_MAC1 (3)	/* PD 0, Port 0, host storage, MAC 1. */
-#define PORT1_HOST_MAC0    (4)	/* PD 0, Port 1 host networking, MAC 0. */
-#define PORT1_HOST_MAC1    (5)	/* PD 0, Port 1 host networking, MAC 1. */
-#define PORT1_STORAGE_MAC0 (6)	/* PD 0, Port 1 host storage, MAC 0. */
-#define PORT1_STORAGE_MAC1 (7)	/* PD 0, Port 1 host storage, MAC 1. */
-#define FIRST_VM_MAC       (8)	/* PD 1 MAC. Protection domains have IDs */
-				/* from 0x8-0x26, one per PD. */
-#define LAST_VM_MAC        (38)	/* PD 31 MAC. */
-#define MGMT_MAC           (39)	/* Management port MAC. */
-#define MARBLE_MAC0        (59)	/* Used for flushing function 0 receive */
-				  /*
-				   * queues before re-using a torn-down
-				   * receive ring. the DA =
-				   * 00-00-00-00-00-00, and the MSB of the
-				   * SA = 00
-				   */
-#define MARBLE_MAC1        (60)	/* Used for flushing function 1 receive */
-				  /*
-				   * queues before re-using a torn-down
-				   * receive ring. the DA =
-				   * 00-00-00-00-00-00, and the MSB of the
-				   * SA != 00
-				   */
-#define NULL_MAC           (61)	/* Promiscuous mode, indicates no match */
-#define MCAST_MAC          (62)	/* Multicast match. */
-#define BCAST_MATCH        (63)	/* Broadcast match. */
-
-#endif /* __descriptors_amap_h__ */
diff --git a/drivers/staging/benet/doorbells.h b/drivers/staging/benet/doorbells.h
deleted file mode 100644
index 550cc4d..0000000
--- a/drivers/staging/benet/doorbells.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __doorbells_amap_h__
-#define __doorbells_amap_h__
-
-/* The TX/RDMA send queue doorbell. */
-struct BE_SQ_DB_AMAP {
-	u8 cid[11];		/* DWORD 0 */
-	u8 rsvd0[5];	/* DWORD 0 */
-	u8 numPosted[14];	/* DWORD 0 */
-	u8 rsvd1[2];	/* DWORD 0 */
-} __packed;
-struct SQ_DB_AMAP {
-	u32 dw[1];
-};
-
-/* The receive queue doorbell. */
-struct BE_RQ_DB_AMAP {
-	u8 rq[10];		/* DWORD 0 */
-	u8 rsvd0[13];	/* DWORD 0 */
-	u8 Invalidate;	/* DWORD 0 */
-	u8 numPosted[8];	/* DWORD 0 */
-} __packed;
-struct RQ_DB_AMAP {
-	u32 dw[1];
-};
-
-/*
- * The CQ/EQ doorbell. Software MUST set reserved fields in this
- * descriptor to zero, otherwise (CEV) hardware will not execute the
- * doorbell (flagging a bad_db_qid error instead).
- */
-struct BE_CQ_DB_AMAP {
-	u8 qid[10];		/* DWORD 0 */
-	u8 rsvd0[4];	/* DWORD 0 */
-	u8 rearm;		/* DWORD 0 */
-	u8 event;		/* DWORD 0 */
-	u8 num_popped[13];	/* DWORD 0 */
-	u8 rsvd1[3];	/* DWORD 0 */
-} __packed;
-struct CQ_DB_AMAP {
-	u32 dw[1];
-};
-
-struct BE_TPM_RQ_DB_AMAP {
-	u8 qid[10];		/* DWORD 0 */
-	u8 rsvd0[6];	/* DWORD 0 */
-	u8 numPosted[11];	/* DWORD 0 */
-	u8 mss_cnt[5];	/* DWORD 0 */
-} __packed;
-struct TPM_RQ_DB_AMAP {
-	u32 dw[1];
-};
-
-/*
- * Post WRB Queue Doorbell Register used by the host Storage stack
- * to notify the controller of a posted Work Request Block
- */
-struct BE_WRB_POST_DB_AMAP {
-	u8 wrb_cid[10];	/* DWORD 0 */
-	u8 rsvd0[6];	/* DWORD 0 */
-	u8 wrb_index[8];	/* DWORD 0 */
-	u8 numberPosted[8];	/* DWORD 0 */
-} __packed;
-struct WRB_POST_DB_AMAP {
-	u32 dw[1];
-};
-
-/*
- * Update Default PDU Queue Doorbell Register used to communicate
- * to the controller that the driver has stopped processing the queue
- * and where in the queue it stopped, this is
- * a CQ Entry Type. Used by storage driver.
- */
-struct BE_DEFAULT_PDU_DB_AMAP {
-	u8 qid[10];		/* DWORD 0 */
-	u8 rsvd0[4];	/* DWORD 0 */
-	u8 rearm;		/* DWORD 0 */
-	u8 event;		/* DWORD 0 */
-	u8 cqproc[14];	/* DWORD 0 */
-	u8 rsvd1[2];	/* DWORD 0 */
-} __packed;
-struct DEFAULT_PDU_DB_AMAP {
-	u32 dw[1];
-};
-
-/* Management Command and Controller default fragment ring */
-struct BE_MCC_DB_AMAP {
-	u8 rid[11];		/* DWORD 0 */
-	u8 rsvd0[5];	/* DWORD 0 */
-	u8 numPosted[14];	/* DWORD 0 */
-	u8 rsvd1[2];	/* DWORD 0 */
-} __packed;
-struct MCC_DB_AMAP {
-	u32 dw[1];
-};
-
-/*
- * Used for bootstrapping the Host interface. This register is
- * used for driver communication with the MPU when no MCC Rings exist.
- * The software must write this register twice to post any MCC
- * command. First, it writes the register with hi=1 and the upper bits of
- * the  physical address for the MCC_MAILBOX structure.  Software must poll
- * the ready bit until this is acknowledged.  Then, sotware writes the
- * register with hi=0 with the lower bits in the address.  It must
- * poll the ready bit until the MCC command is complete.  Upon completion,
- * the MCC_MAILBOX will contain a valid completion queue  entry.
- */
-struct BE_MPU_MAILBOX_DB_AMAP {
-	u8 ready;		/* DWORD 0 */
-	u8 hi;		/* DWORD 0 */
-	u8 address[30];	/* DWORD 0 */
-} __packed;
-struct MPU_MAILBOX_DB_AMAP {
-	u32 dw[1];
-};
-
-/*
- *  This is the protection domain doorbell register map. Note that
- *  while this map shows doorbells for all Blade Engine supported
- *  protocols, not all of these may be valid in a given function or
- *  protection domain. It is the responsibility of the application
- *  accessing the doorbells to know which are valid. Each doorbell
- *  occupies 32 bytes of space, but unless otherwise specified,
- *  only the first 4 bytes should be written.  There are 32 instances
- *  of these doorbells for the host and 31 virtual machines respectively.
- *  The host and VMs will only map the doorbell pages belonging to its
- *  protection domain. It will not be able to touch the doorbells for
- *  another VM. The doorbells are the only registers directly accessible
- *  by a virtual machine. Similarly, there are 511 additional
- *  doorbells for RDMA protection domains. PD 0 for RDMA shares
- *  the same physical protection domain doorbell page as ETH/iSCSI.
- *
- */
-struct BE_PROTECTION_DOMAIN_DBMAP_AMAP {
-	u8 rsvd0[512];	/* DWORD 0 */
-	struct BE_SQ_DB_AMAP rdma_sq_db;
-	u8 rsvd1[7][32];	/* DWORD 17 */
-	struct BE_WRB_POST_DB_AMAP iscsi_wrb_post_db;
-	u8 rsvd2[7][32];	/* DWORD 25 */
-	struct BE_SQ_DB_AMAP etx_sq_db;
-	u8 rsvd3[7][32];	/* DWORD 33 */
-	struct BE_RQ_DB_AMAP rdma_rq_db;
-	u8 rsvd4[7][32];	/* DWORD 41 */
-	struct BE_DEFAULT_PDU_DB_AMAP iscsi_default_pdu_db;
-	u8 rsvd5[7][32];	/* DWORD 49 */
-	struct BE_TPM_RQ_DB_AMAP tpm_rq_db;
-	u8 rsvd6[7][32];	/* DWORD 57 */
-	struct BE_RQ_DB_AMAP erx_rq_db;
-	u8 rsvd7[7][32];	/* DWORD 65 */
-	struct BE_CQ_DB_AMAP cq_db;
-	u8 rsvd8[7][32];	/* DWORD 73 */
-	struct BE_MCC_DB_AMAP mpu_mcc_db;
-	u8 rsvd9[7][32];	/* DWORD 81 */
-	struct BE_MPU_MAILBOX_DB_AMAP mcc_bootstrap_db;
-	u8 rsvd10[935][32];	/* DWORD 89 */
-} __packed;
-struct PROTECTION_DOMAIN_DBMAP_AMAP {
-	u32 dw[1024];
-};
-
-#endif /* __doorbells_amap_h__ */
diff --git a/drivers/staging/benet/ep.h b/drivers/staging/benet/ep.h
deleted file mode 100644
index 72fcf64..0000000
--- a/drivers/staging/benet/ep.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __ep_amap_h__
-#define __ep_amap_h__
-
-/* General Control and Status Register. */
-struct BE_EP_CONTROL_CSR_AMAP {
-	u8 m0_RxPbuf;	/* DWORD 0 */
-	u8 m1_RxPbuf;	/* DWORD 0 */
-	u8 m2_RxPbuf;	/* DWORD 0 */
-	u8 ff_en;		/* DWORD 0 */
-	u8 rsvd0[27];	/* DWORD 0 */
-	u8 CPU_reset;	/* DWORD 0 */
-} __packed;
-struct EP_CONTROL_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Semaphore Register. */
-struct BE_EP_SEMAPHORE_CSR_AMAP {
-	u8 value[32];	/* DWORD 0 */
-} __packed;
-struct EP_SEMAPHORE_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Embedded Processor Specific Registers. */
-struct BE_EP_CSRMAP_AMAP {
-	struct BE_EP_CONTROL_CSR_AMAP ep_control;
-	u8 rsvd0[32];	/* DWORD 1 */
-	u8 rsvd1[32];	/* DWORD 2 */
-	u8 rsvd2[32];	/* DWORD 3 */
-	u8 rsvd3[32];	/* DWORD 4 */
-	u8 rsvd4[32];	/* DWORD 5 */
-	u8 rsvd5[8][128];	/* DWORD 6 */
-	u8 rsvd6[32];	/* DWORD 38 */
-	u8 rsvd7[32];	/* DWORD 39 */
-	u8 rsvd8[32];	/* DWORD 40 */
-	u8 rsvd9[32];	/* DWORD 41 */
-	u8 rsvd10[32];	/* DWORD 42 */
-	struct BE_EP_SEMAPHORE_CSR_AMAP ep_semaphore;
-	u8 rsvd11[32];	/* DWORD 44 */
-	u8 rsvd12[19][32];	/* DWORD 45 */
-} __packed;
-struct EP_CSRMAP_AMAP {
-	u32 dw[64];
-};
-
-#endif /* __ep_amap_h__ */
diff --git a/drivers/staging/benet/eq.c b/drivers/staging/benet/eq.c
deleted file mode 100644
index db92ccd..0000000
--- a/drivers/staging/benet/eq.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#include "hwlib.h"
-#include "bestatus.h"
-/*
-    This routine creates an event queue based on the client completion
-    queue configuration information.
-
-    FunctionObject      - Handle to a function object
-    EqBaseVa            - Base VA for a the EQ ring
-    SizeEncoding        - The encoded size for the EQ entries. This value is
-			either CEV_EQ_SIZE_4 or CEV_EQ_SIZE_16
-    NumEntries          - CEV_CQ_CNT_* values.
-    Watermark           - Enables watermark based coalescing.  This parameter
-			must be of the type CEV_WMARK_* if watermarks
-			are enabled.  If watermarks to to be disabled
-			this value should be-1.
-    TimerDelay          - If a timer delay is enabled this value should be the
-			time of the delay in 8 microsecond units.  If
-			delays are not used this parameter should be
-			set to -1.
-    ppEqObject          - Internal EQ Handle returned.
-
-    Returns BE_SUCCESS if successfull,, otherwise a useful error code
-	is returned.
-
-    IRQL < DISPATCH_LEVEL
-*/
-int
-be_eq_create(struct be_function_object *pfob,
-		struct ring_desc *rd, u32 eqe_size, u32 num_entries,
-		u32 watermark,	/* CEV_WMARK_* or -1 */
-		u32 timer_delay,	/* in 8us units, or -1 */
-		struct be_eq_object *eq_object)
-{
-	int status = BE_SUCCESS;
-	u32 num_entries_encoding, eqe_size_encoding, length;
-	struct FWCMD_COMMON_EQ_CREATE *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	u32 n;
-	unsigned long irql;
-
-	ASSERT(rd);
-	ASSERT(eq_object);
-
-	switch (num_entries) {
-	case 256:
-		num_entries_encoding = CEV_EQ_CNT_256;
-		break;
-	case 512:
-		num_entries_encoding = CEV_EQ_CNT_512;
-		break;
-	case 1024:
-		num_entries_encoding = CEV_EQ_CNT_1024;
-		break;
-	case 2048:
-		num_entries_encoding = CEV_EQ_CNT_2048;
-		break;
-	case 4096:
-		num_entries_encoding = CEV_EQ_CNT_4096;
-		break;
-	default:
-		ASSERT(0);
-		return BE_STATUS_INVALID_PARAMETER;
-	}
-
-	switch (eqe_size) {
-	case 4:
-		eqe_size_encoding = CEV_EQ_SIZE_4;
-		break;
-	case 16:
-		eqe_size_encoding = CEV_EQ_SIZE_16;
-		break;
-	default:
-		ASSERT(0);
-		return BE_STATUS_INVALID_PARAMETER;
-	}
-
-	if ((eqe_size == 4 && num_entries < 1024) ||
-	    (eqe_size == 16 && num_entries == 4096)) {
-		TRACE(DL_ERR, "Bad EQ size. eqe_size:%d num_entries:%d",
-		      eqe_size, num_entries);
-		ASSERT(0);
-		return BE_STATUS_INVALID_PARAMETER;
-	}
-
-	memset(eq_object, 0, sizeof(*eq_object));
-
-	atomic_set(&eq_object->ref_count, 0);
-	eq_object->parent_function = pfob;
-	eq_object->eq_id = 0xFFFFFFFF;
-
-	INIT_LIST_HEAD(&eq_object->cq_list_head);
-
-	length = num_entries * eqe_size;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		ASSERT(wrb);
-		TRACE(DL_ERR, "No free MCC WRBs in create EQ.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto Error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_EQ_CREATE);
-
-	fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va),
-									length);
-	n = pfob->pci_function_number;
-	AMAP_SET_BITS_PTR(EQ_CONTEXT, Func, &fwcmd->params.request.context, n);
-
-	AMAP_SET_BITS_PTR(EQ_CONTEXT, valid, &fwcmd->params.request.context, 1);
-
-	AMAP_SET_BITS_PTR(EQ_CONTEXT, Size,
-			&fwcmd->params.request.context, eqe_size_encoding);
-
-	n = 0; /* Protection Domain is always 0 in  Linux  driver */
-	AMAP_SET_BITS_PTR(EQ_CONTEXT, PD, &fwcmd->params.request.context, n);
-
-	/* Let the caller ARM the EQ with the doorbell. */
-	AMAP_SET_BITS_PTR(EQ_CONTEXT, Armed, &fwcmd->params.request.context, 0);
-
-	AMAP_SET_BITS_PTR(EQ_CONTEXT, Count, &fwcmd->params.request.context,
-					num_entries_encoding);
-
-	n = pfob->pci_function_number * 32;
-	AMAP_SET_BITS_PTR(EQ_CONTEXT, EventVect,
-				&fwcmd->params.request.context, n);
-	if (watermark != -1) {
-		AMAP_SET_BITS_PTR(EQ_CONTEXT, WME,
-				&fwcmd->params.request.context, 1);
-		AMAP_SET_BITS_PTR(EQ_CONTEXT, Watermark,
-				&fwcmd->params.request.context, watermark);
-		ASSERT(watermark <= CEV_WMARK_240);
-	} else
-		AMAP_SET_BITS_PTR(EQ_CONTEXT, WME,
-					&fwcmd->params.request.context, 0);
-	if (timer_delay != -1) {
-		AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR,
-					&fwcmd->params.request.context, 1);
-
-		ASSERT(timer_delay <= 250);	/* max value according to EAS */
-		timer_delay = min(timer_delay, (u32)250);
-
-		AMAP_SET_BITS_PTR(EQ_CONTEXT, Delay,
-				&fwcmd->params.request.context, timer_delay);
-	} else {
-		AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR,
-				&fwcmd->params.request.context, 0);
-	}
-	/* Create a page list for the FWCMD. */
-	be_rd_to_pa_list(rd, fwcmd->params.request.pages,
-			  ARRAY_SIZE(fwcmd->params.request.pages));
-
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-					NULL, NULL, fwcmd, NULL);
-	if (status != BE_SUCCESS) {
-		TRACE(DL_ERR, "MCC to create EQ failed.");
-		goto Error;
-	}
-	/* Get the EQ id.  The MPU allocates the IDs. */
-	eq_object->eq_id = fwcmd->params.response.eq_id;
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-    Deferences the given object. Once the object's reference count drops to
-    zero, the object is destroyed and all resources that are held by this
-    object are released.  The on-chip context is also destroyed along with
-    the queue ID, and any mappings made into the UT.
-
-    eq_object            - EQ handle returned from eq_object_create.
-
-    Returns BE_SUCCESS if successfull, otherwise a useful error code
-	is returned.
-
-    IRQL: IRQL < DISPATCH_LEVEL
-*/
-int be_eq_destroy(struct be_eq_object *eq_object)
-{
-	int status = 0;
-
-	ASSERT(atomic_read(&eq_object->ref_count) == 0);
-	/* no CQs should reference this EQ now */
-	ASSERT(list_empty(&eq_object->cq_list_head));
-
-	/* Send fwcmd to destroy the EQ. */
-	status = be_function_ring_destroy(eq_object->parent_function,
-			     eq_object->eq_id, FWCMD_RING_TYPE_EQ,
-					NULL, NULL, NULL, NULL);
-	ASSERT(status == 0);
-
-	return BE_SUCCESS;
-}
-/*
- *---------------------------------------------------------------------------
- * Function: be_eq_modify_delay
- *   Changes the EQ delay for a group of EQs.
- * num_eq             - The number of EQs in the eq_array to adjust.
- * 			This also is the number of delay values in
- * 			the eq_delay_array.
- * eq_array           - Array of struct be_eq_object pointers to adjust.
- * eq_delay_array     - Array of "num_eq" timer delays in units
- * 			of microseconds. The be_eq_query_delay_range
- * 			fwcmd returns the resolution and range of
- *                      legal EQ delays.
- * cb           -
- * cb_context   -
- * q_ctxt             - Optional. Pointer to a previously allocated
- * 			struct. If the MCC WRB ring is full, this
- * 			structure is used to queue the operation. It
- *                      will be posted to the MCC ring when space
- *                      becomes available. All queued commands will
- *                      be posted to the ring in the order they are
- *                      received. It is always valid to pass a pointer to
- *                      a generic be_generic_q_cntxt. However,
- *                      the specific context structs
- *                      are generally smaller than the generic struct.
- * return pend_status - BE_SUCCESS (0) on success.
- * 			BE_PENDING (postive value) if the FWCMD
- *                      completion is pending. Negative error code on failure.
- *-------------------------------------------------------------------------
- */
-int
-be_eq_modify_delay(struct be_function_object *pfob,
-		   u32 num_eq, struct be_eq_object **eq_array,
-		   u32 *eq_delay_array, mcc_wrb_cqe_callback cb,
-		   void *cb_context, struct be_eq_modify_delay_q_ctxt *q_ctxt)
-{
-	struct FWCMD_COMMON_MODIFY_EQ_DELAY *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	struct be_generic_q_ctxt *gen_ctxt = NULL;
-	u32 i;
-	unsigned long irql;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		if (q_ctxt && cb) {
-			wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
-			gen_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
-			gen_ctxt->context.bytes = sizeof(*q_ctxt);
-		} else {
-			status = BE_STATUS_NO_MCC_WRB;
-			goto Error;
-		}
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MODIFY_EQ_DELAY);
-
-	ASSERT(num_eq > 0);
-	ASSERT(num_eq <= ARRAY_SIZE(fwcmd->params.request.delay));
-	fwcmd->params.request.num_eq = num_eq;
-	for (i = 0; i < num_eq; i++) {
-		fwcmd->params.request.delay[i].eq_id = eq_array[i]->eq_id;
-		fwcmd->params.request.delay[i].delay_in_microseconds =
-		    eq_delay_array[i];
-	}
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, gen_ctxt,
-			cb, cb_context, NULL, NULL, fwcmd, NULL);
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
diff --git a/drivers/staging/benet/eth.c b/drivers/staging/benet/eth.c
deleted file mode 100644
index f641b62..0000000
--- a/drivers/staging/benet/eth.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#include <linux/if_ether.h>
-#include "hwlib.h"
-#include "bestatus.h"
-
-/*
- *---------------------------------------------------------
- * Function: be_eth_sq_create_ex
- *   Creates an ethernet send ring - extended version with
- *   additional parameters.
- * pfob -
- * rd             - ring address
- * length_in_bytes -
- * type            - The type of ring to create.
- * ulp             - The requested ULP number for the ring.
- * 		     This should be zero based, i.e. 0,1,2. This must
- * 		     be valid NIC ULP based on the firmware config.
- *                   All doorbells for this ring must be sent to
- *                   this ULP. The first network ring allocated for
- *                   each ULP are higher performance than subsequent rings.
- * cq_object       - cq object for completions
- * ex_parameters   - Additional parameters (that may increase in
- * 		     future revisions). These parameters are only used
- * 		     for certain ring types -- see
- *                   struct be_eth_sq_parameters for details.
- * eth_sq          -
- * return status   - BE_SUCCESS (0) on success. Negative error code on failure.
- *---------------------------------------------------------
- */
-int
-be_eth_sq_create_ex(struct be_function_object *pfob, struct ring_desc *rd,
-		u32 length, u32 type, u32 ulp, struct be_cq_object *cq_object,
-		struct be_eth_sq_parameters *ex_parameters,
-		struct be_ethsq_object *eth_sq)
-{
-	struct FWCMD_COMMON_ETH_TX_CREATE *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	u32 n;
-	unsigned long irql;
-
-	ASSERT(rd);
-	ASSERT(eth_sq);
-	ASSERT(ex_parameters);
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	memset(eth_sq, 0, sizeof(*eth_sq));
-
-	eth_sq->parent_function = pfob;
-	eth_sq->bid = 0xFFFFFFFF;
-	eth_sq->cq_object = cq_object;
-
-	/* Translate hwlib interface to arm interface. */
-	switch (type) {
-	case BE_ETH_TX_RING_TYPE_FORWARDING:
-		type = ETH_TX_RING_TYPE_FORWARDING;
-		break;
-	case BE_ETH_TX_RING_TYPE_STANDARD:
-		type = ETH_TX_RING_TYPE_STANDARD;
-		break;
-	case BE_ETH_TX_RING_TYPE_BOUND:
-		ASSERT(ex_parameters->port < 2);
-		type = ETH_TX_RING_TYPE_BOUND;
-		break;
-	default:
-		TRACE(DL_ERR, "Invalid eth tx ring type:%d", type);
-		return BE_NOT_OK;
-		break;
-	}
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		ASSERT(wrb);
-		TRACE(DL_ERR, "No free MCC WRBs in create EQ.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto Error;
-	}
-	/* NIC must be supported by the current config. */
-	ASSERT(pfob->fw_config.nic_ulp_mask);
-
-	/*
-	 * The ulp parameter must select a valid NIC ULP
-	 * for the current config.
-	 */
-	ASSERT((1 << ulp) & pfob->fw_config.nic_ulp_mask);
-
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_TX_CREATE);
-	fwcmd->header.request.port_number = ex_parameters->port;
-
-	AMAP_SET_BITS_PTR(ETX_CONTEXT, pd_id,
-				&fwcmd->params.request.context, 0);
-
-	n = be_ring_length_to_encoding(length, sizeof(struct ETH_WRB_AMAP));
-	AMAP_SET_BITS_PTR(ETX_CONTEXT, tx_ring_size,
-					&fwcmd->params.request.context, n);
-
-	AMAP_SET_BITS_PTR(ETX_CONTEXT, cq_id_send,
-			&fwcmd->params.request.context, cq_object->cq_id);
-
-	n = pfob->pci_function_number;
-	AMAP_SET_BITS_PTR(ETX_CONTEXT, func, &fwcmd->params.request.context, n);
-
-	fwcmd->params.request.type = type;
-	fwcmd->params.request.ulp_num  = (1 << ulp);
-	fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE);
-	ASSERT(PAGES_SPANNED(rd->va, rd->length) >=
-				fwcmd->params.request.num_pages);
-
-	/* Create a page list for the FWCMD. */
-	be_rd_to_pa_list(rd, fwcmd->params.request.pages,
-			  ARRAY_SIZE(fwcmd->params.request.pages));
-
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-					NULL, NULL, fwcmd, NULL);
-	if (status != BE_SUCCESS) {
-		TRACE(DL_ERR, "MCC to create etx queue failed.");
-		goto Error;
-	}
-	/* save the butler ID */
-	eth_sq->bid = fwcmd->params.response.cid;
-
-	/* add a reference to the corresponding CQ */
-	atomic_inc(&cq_object->ref_count);
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-
-/*
-    This routine destroys an ethernet send queue
-
-    EthSq - EthSq Handle returned from EthSqCreate
-
-    This function always return BE_SUCCESS.
-
-    This function frees memory allocated by EthSqCreate for the EthSq Object.
-
-*/
-int be_eth_sq_destroy(struct be_ethsq_object *eth_sq)
-{
-	int status = 0;
-
-	/* Send fwcmd to destroy the queue. */
-	status = be_function_ring_destroy(eth_sq->parent_function, eth_sq->bid,
-		     FWCMD_RING_TYPE_ETH_TX, NULL, NULL, NULL, NULL);
-	ASSERT(status == 0);
-
-	/* Derefence any associated CQs. */
-	atomic_dec(&eth_sq->cq_object->ref_count);
-	return status;
-}
-/*
-    This routine attempts to set the transmit flow control parameters.
-
-    FunctionObject      - Handle to a function object
-
-    txfc_enable         - transmit flow control enable - true for
-			  enable, false for disable
-
-    rxfc_enable         - receive flow control enable - true for
-				enable, false for disable
-
-    Returns BE_SUCCESS if successfull, otherwise a useful int error
-    code is returned.
-
-    IRQL: < DISPATCH_LEVEL
-
-    This function always fails in non-privileged machine context.
-*/
-int
-be_eth_set_flow_control(struct be_function_object *pfob,
-			bool txfc_enable, bool rxfc_enable)
-{
-	struct FWCMD_COMMON_SET_FLOW_CONTROL *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	unsigned long irql;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FLOW_CONTROL);
-
-	fwcmd->params.request.rx_flow_control = rxfc_enable;
-	fwcmd->params.request.tx_flow_control = txfc_enable;
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-					NULL, NULL, fwcmd, NULL);
-
-	if (status != 0) {
-		TRACE(DL_ERR, "set flow control fwcmd failed.");
-		goto error;
-	}
-
-error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-    This routine attempts to get the transmit flow control parameters.
-
-    pfob      - Handle to a function object
-
-    txfc_enable         - transmit flow control enable - true for
-			enable, false for disable
-
-    rxfc_enable         - receive flow control enable - true for enable,
-			false for disable
-
-    Returns BE_SUCCESS if successfull, otherwise a useful int error code
-			is returned.
-
-    IRQL: < DISPATCH_LEVEL
-
-    This function always fails in non-privileged machine context.
-*/
-int
-be_eth_get_flow_control(struct be_function_object *pfob,
-			bool *txfc_enable, bool *rxfc_enable)
-{
-	struct FWCMD_COMMON_GET_FLOW_CONTROL *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	unsigned long irql;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FLOW_CONTROL);
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-						NULL, NULL, fwcmd, NULL);
-
-	if (status != 0) {
-		TRACE(DL_ERR, "get flow control fwcmd failed.");
-		goto error;
-	}
-
-	*txfc_enable = fwcmd->params.response.tx_flow_control;
-	*rxfc_enable = fwcmd->params.response.rx_flow_control;
-
-error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
- *---------------------------------------------------------
- * Function: be_eth_set_qos
- *   This function sets the ethernet transmit Quality of Service (QoS)
- *   characteristics of BladeEngine for the domain. All ethernet
- *   transmit rings of the domain will evenly share the bandwidth.
- *   The exeception to sharing is the host primary (super) ethernet
- *   transmit ring as well as the host ethernet forwarding ring
- *   for missed offload data.
- * pfob -
- * max_bps         - the maximum bits per second in units of
- * 			10 Mbps (valid 0-100)
- * max_pps         - the maximum packets per second in units
- * 			of 1 Kpps (0 indicates no limit)
- * return status   - BE_SUCCESS (0) on success. Negative error code on failure.
- *---------------------------------------------------------
- */
-int
-be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps)
-{
-	struct FWCMD_COMMON_SET_QOS *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	unsigned long irql;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_QOS);
-
-	/* Set fields in fwcmd */
-	fwcmd->params.request.max_bits_per_second_NIC = max_bps;
-	fwcmd->params.request.max_packets_per_second_NIC = max_pps;
-	fwcmd->params.request.valid_flags = QOS_BITS_NIC | QOS_PKTS_NIC;
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-					NULL, NULL, fwcmd, NULL);
-
-	if (status != 0)
-		TRACE(DL_ERR, "network set qos fwcmd failed.");
-
-error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
- *---------------------------------------------------------
- * Function: be_eth_get_qos
- *   This function retrieves the ethernet transmit Quality of Service (QoS)
- *   characteristics for the domain.
- * max_bps         - the maximum bits per second in units of
- * 			10 Mbps (valid 0-100)
- * max_pps         - the maximum packets per second in units of
- * 			1 Kpps (0 indicates no limit)
- * return status   - BE_SUCCESS (0) on success. Negative error code on failure.
- *---------------------------------------------------------
- */
-int
-be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps)
-{
-	struct FWCMD_COMMON_GET_QOS *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	unsigned long irql;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_QOS);
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-					NULL, NULL, fwcmd, NULL);
-
-	if (status != 0) {
-		TRACE(DL_ERR, "network get qos fwcmd failed.");
-		goto error;
-	}
-
-	*max_bps = fwcmd->params.response.max_bits_per_second_NIC;
-	*max_pps = fwcmd->params.response.max_packets_per_second_NIC;
-
-error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
- *---------------------------------------------------------
- * Function: be_eth_set_frame_size
- *   This function sets the ethernet maximum frame size. The previous
- *   values are returned.
- * pfob -
- * tx_frame_size   - maximum transmit frame size in bytes
- * rx_frame_size   - maximum receive frame size in bytes
- * return status   - BE_SUCCESS (0) on success. Negative error code on failure.
- *---------------------------------------------------------
- */
-int
-be_eth_set_frame_size(struct be_function_object *pfob,
-		      u32 *tx_frame_size, u32 *rx_frame_size)
-{
-	struct FWCMD_COMMON_SET_FRAME_SIZE *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	unsigned long irql;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FRAME_SIZE);
-	fwcmd->params.request.max_tx_frame_size = *tx_frame_size;
-	fwcmd->params.request.max_rx_frame_size = *rx_frame_size;
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-						NULL, NULL, fwcmd, NULL);
-
-	if (status != 0) {
-		TRACE(DL_ERR, "network set frame size fwcmd failed.");
-		goto error;
-	}
-
-	*tx_frame_size = fwcmd->params.response.chip_max_tx_frame_size;
-	*rx_frame_size = fwcmd->params.response.chip_max_rx_frame_size;
-
-error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-
-/*
-    This routine creates a Ethernet receive ring.
-
-    pfob      - handle to a function object
-    rq_base_va            - base VA for the default receive ring. this must be
-			exactly 8K in length and continguous physical memory.
-    cq_object            - handle to a previously created CQ to be associated
-			with the RQ.
-    pp_eth_rq             - pointer to an opqaue handle where an eth
-			receive object is returned.
-    Returns BE_SUCCESS if successfull, , otherwise a useful
-    int error code is returned.
-
-    IRQL: < DISPATCH_LEVEL
-    this function allocates a struct be_ethrq_object *object.
-    there must be no more than 1 of these per function object, unless the
-    function object supports RSS (is networking and on the host).
-    the rq_base_va must point to a buffer of exactly 8K.
-    the erx::host_cqid (or host_stor_cqid) register and erx::ring_page registers
-    will be updated as appropriate on return
-*/
-int
-be_eth_rq_create(struct be_function_object *pfob,
-			struct ring_desc *rd, struct be_cq_object *cq_object,
-			struct be_cq_object *bcmc_cq_object,
-			struct be_ethrq_object *eth_rq)
-{
-	int status = 0;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	struct FWCMD_COMMON_ETH_RX_CREATE *fwcmd = NULL;
-	unsigned long irql;
-
-	/* MPU will set the  */
-	ASSERT(rd);
-	ASSERT(eth_rq);
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	eth_rq->parent_function = pfob;
-	eth_rq->cq_object = cq_object;
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto Error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_RX_CREATE);
-
-	fwcmd->params.request.num_pages = 2;	/* required length */
-	fwcmd->params.request.cq_id = cq_object->cq_id;
-
-	if (bcmc_cq_object)
-		fwcmd->params.request.bcmc_cq_id = bcmc_cq_object->cq_id;
-	else
-		fwcmd->params.request.bcmc_cq_id = 0xFFFF;
-
-	/* Create a page list for the FWCMD. */
-	be_rd_to_pa_list(rd, fwcmd->params.request.pages,
-			  ARRAY_SIZE(fwcmd->params.request.pages));
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-						NULL, NULL, fwcmd, NULL);
-	if (status != BE_SUCCESS) {
-		TRACE(DL_ERR, "fwcmd to map eth rxq frags failed.");
-		goto Error;
-	}
-	/* Save the ring ID for cleanup. */
-	eth_rq->rid = fwcmd->params.response.id;
-
-	atomic_inc(&cq_object->ref_count);
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-    This routine destroys an Ethernet receive queue
-
-    eth_rq - ethernet receive queue handle returned from eth_rq_create
-
-    Returns BE_SUCCESS on success and an appropriate int on failure.
-
-    This function frees resourcs allocated by EthRqCreate.
-    The erx::host_cqid (or host_stor_cqid) register and erx::ring_page
-    registers will be updated as appropriate on return
-    IRQL: < DISPATCH_LEVEL
-*/
-
-static void be_eth_rq_destroy_internal_cb(void *context, int status,
-					 struct MCC_WRB_AMAP *wrb)
-{
-	struct be_ethrq_object *eth_rq = (struct be_ethrq_object *) context;
-
-	if (status != BE_SUCCESS) {
-		TRACE(DL_ERR, "Destroy eth rq failed in internal callback.\n");
-	} else {
-		/* Dereference any CQs associated with this queue. */
-		atomic_dec(&eth_rq->cq_object->ref_count);
-	}
-
-	return;
-}
-
-int be_eth_rq_destroy(struct be_ethrq_object *eth_rq)
-{
-	int status = BE_SUCCESS;
-
-	/* Send fwcmd to destroy the RQ. */
-	status = be_function_ring_destroy(eth_rq->parent_function,
-			eth_rq->rid, FWCMD_RING_TYPE_ETH_RX, NULL, NULL,
-			be_eth_rq_destroy_internal_cb, eth_rq);
-
-	return status;
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: be_eth_rq_destroy_options
- *   Destroys an ethernet receive ring with finer granularity options
- *   than the standard be_eth_rq_destroy() API function.
- * eth_rq           -
- * flush            - Set to 1 to flush the ring, set to 0 to bypass the flush
- * cb               - Callback function on completion
- * cb_context       - Callback context
- * return status    - BE_SUCCESS (0) on success. Negative error code on failure.
- *----------------------------------------------------------------------------
- */
-int
-be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush,
-		mcc_wrb_cqe_callback cb, void *cb_context)
-{
-	struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = BE_SUCCESS;
-	struct be_function_object *pfob = NULL;
-	unsigned long irql;
-
-	pfob = eth_rq->parent_function;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	TRACE(DL_INFO, "Destroy eth_rq ring id:%d, flush:%d", eth_rq->rid,
-	      flush);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		ASSERT(wrb);
-		TRACE(DL_ERR, "No free MCC WRBs in destroy eth_rq ring.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto Error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY);
-
-	fwcmd->params.request.id = eth_rq->rid;
-	fwcmd->params.request.ring_type = FWCMD_RING_TYPE_ETH_RX;
-	fwcmd->params.request.bypass_flush = ((0 == flush) ? 1 : 0);
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context,
-			be_eth_rq_destroy_internal_cb, eth_rq, fwcmd, NULL);
-
-	if (status != BE_SUCCESS && status != BE_PENDING) {
-		TRACE(DL_ERR, "eth_rq ring destroy failed. id:%d, flush:%d",
-		      eth_rq->rid, flush);
-		goto Error;
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-    This routine queries the frag size for erx.
-
-    pfob      - handle to a function object
-
-    frag_size_bytes       - erx frag size in bytes that is/was set.
-
-    Returns BE_SUCCESS if successfull, otherwise a useful int error
-    code is returned.
-
-    IRQL: < DISPATCH_LEVEL
-
-*/
-int
-be_eth_rq_get_frag_size(struct be_function_object *pfob, u32 *frag_size_bytes)
-{
-	struct FWCMD_ETH_GET_RX_FRAG_SIZE *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	unsigned long irql;
-
-	ASSERT(frag_size_bytes);
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		return BE_STATUS_NO_MCC_WRB;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_GET_RX_FRAG_SIZE);
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-				NULL, NULL, fwcmd, NULL);
-
-	if (status != 0) {
-		TRACE(DL_ERR, "get frag size fwcmd failed.");
-		goto error;
-	}
-
-	*frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2;
-
-error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-    This routine attempts to set the frag size for erx.  If the frag size is
-    already set, the attempt fails and the current frag size is returned.
-
-    pfob      - Handle to a function object
-
-    frag_size       - Erx frag size in bytes that is/was set.
-
-    current_frag_size_bytes    - Pointer to location where currrent frag
-				 is to be rturned
-
-    Returns BE_SUCCESS if successfull, otherwise a useful int error
-    code is returned.
-
-    IRQL: < DISPATCH_LEVEL
-
-    This function always fails in non-privileged machine context.
-*/
-int
-be_eth_rq_set_frag_size(struct be_function_object *pfob,
-			u32 frag_size, u32 *frag_size_bytes)
-{
-	struct FWCMD_ETH_SET_RX_FRAG_SIZE *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	unsigned long irql;
-
-	ASSERT(frag_size_bytes);
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_SET_RX_FRAG_SIZE);
-
-	ASSERT(frag_size >= 128 && frag_size <= 16 * 1024);
-
-	/* This is the log2 of the fragsize.  This is not the exact
-	 * ERX encoding. */
-	fwcmd->params.request.new_fragsize_log2 = __ilog2_u32(frag_size);
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-				NULL, NULL, fwcmd, NULL);
-
-	if (status != 0) {
-		TRACE(DL_ERR, "set frag size fwcmd failed.");
-		goto error;
-	}
-
-	*frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2;
-error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-
-/*
-    This routine gets or sets a mac address for a domain
-    given the port and mac.
-
-    FunctionObject  - Function object handle.
-    port1           - Set to TRUE if this function will set/get the Port 1
-			address.  Only the host may set this to TRUE.
-    mac1            - Set to TRUE if this function will set/get the
-			MAC 1 address.  Only the host may set this to TRUE.
-    write           - Set to TRUE if this function should write the mac address.
-    mac_address      - Buffer of the mac address to read or write.
-
-    Returns BE_SUCCESS if successfull, otherwise a useful int is returned.
-
-    IRQL: < DISPATCH_LEVEL
-*/
-int be_rxf_mac_address_read_write(struct be_function_object *pfob,
-		bool port1,	/* VM must always set to false */
-		bool mac1,	/* VM must always set to false */
-		bool mgmt, bool write,
-		bool permanent, u8 *mac_address,
-		mcc_wrb_cqe_callback cb,	/* optional */
-		void *cb_context)	/* optional */
-{
-	int status = BE_SUCCESS;
-	union {
-		struct FWCMD_COMMON_NTWK_MAC_QUERY *query;
-		struct FWCMD_COMMON_NTWK_MAC_SET *set;
-	} fwcmd = {NULL};
-	struct MCC_WRB_AMAP *wrb = NULL;
-	u32 type = 0;
-	unsigned long irql;
-	struct be_mcc_wrb_response_copy rc;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	ASSERT(mac_address);
-
-	ASSERT(port1 == false);
-	ASSERT(mac1 == false);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto Error;
-	}
-
-	if (mgmt) {
-		type = MAC_ADDRESS_TYPE_MANAGEMENT;
-	} else {
-		if (pfob->type == BE_FUNCTION_TYPE_NETWORK)
-			type = MAC_ADDRESS_TYPE_NETWORK;
-		else
-			type = MAC_ADDRESS_TYPE_STORAGE;
-	}
-
-	if (write) {
-		/* Prepares an embedded fwcmd, including
-		 * request/response sizes.
-		 */
-		fwcmd.set = BE_PREPARE_EMBEDDED_FWCMD(pfob,
-					       wrb, COMMON_NTWK_MAC_SET);
-
-		fwcmd.set->params.request.invalidate = 0;
-		fwcmd.set->params.request.mac1 = (mac1 ? 1 : 0);
-		fwcmd.set->params.request.port = (port1 ? 1 : 0);
-		fwcmd.set->params.request.type = type;
-
-		/* Copy the mac address to set. */
-		fwcmd.set->params.request.mac.SizeOfStructure =
-			    sizeof(fwcmd.set->params.request.mac);
-		memcpy(fwcmd.set->params.request.mac.MACAddress,
-			mac_address, ETH_ALEN);
-
-		/* Post the f/w command */
-		status = be_function_post_mcc_wrb(pfob, wrb, NULL,
-				cb, cb_context, NULL, NULL, fwcmd.set, NULL);
-
-	} else {
-
-		/*
-		 * Prepares an embedded fwcmd, including
-		 * request/response sizes.
-		 */
-		fwcmd.query = BE_PREPARE_EMBEDDED_FWCMD(pfob,
-					       wrb, COMMON_NTWK_MAC_QUERY);
-
-		fwcmd.query->params.request.mac1 = (mac1 ? 1 : 0);
-		fwcmd.query->params.request.port = (port1 ? 1 : 0);
-		fwcmd.query->params.request.type = type;
-		fwcmd.query->params.request.permanent = permanent;
-
-		rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_MAC_QUERY,
-						params.response.mac.MACAddress);
-		rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_MAC_QUERY,
-						params.response.mac.MACAddress);
-		rc.va = mac_address;
-		/* Post the f/w command (with a copy for the response) */
-		status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb,
-				cb_context, NULL, NULL, fwcmd.query, &rc);
-	}
-
-	if (status < 0) {
-		TRACE(DL_ERR, "mac set/query failed.");
-		goto Error;
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-    This routine writes data to context memory.
-
-    pfob  - Function object handle.
-    mac_table     - Set to the 128-bit multicast address hash table.
-
-    Returns BE_SUCCESS if successfull, otherwise a useful int is returned.
-
-    IRQL: < DISPATCH_LEVEL
-*/
-
-int be_rxf_multicast_config(struct be_function_object *pfob,
-		bool promiscuous, u32 num, u8 *mac_table,
-		mcc_wrb_cqe_callback cb,	/* optional */
-		void *cb_context,
-		struct be_multicast_q_ctxt *q_ctxt)
-{
-	int status = BE_SUCCESS;
-	struct FWCMD_COMMON_NTWK_MULTICAST_SET *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	struct be_generic_q_ctxt *generic_ctxt = NULL;
-	unsigned long irql;
-
-	ASSERT(num <= ARRAY_SIZE(fwcmd->params.request.mac));
-
-	if (num > ARRAY_SIZE(fwcmd->params.request.mac)) {
-		TRACE(DL_ERR, "Too many multicast addresses. BE supports %d.",
-		      (int) ARRAY_SIZE(fwcmd->params.request.mac));
-		return BE_NOT_OK;
-	}
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		if (q_ctxt && cb) {
-			wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
-			generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
-			generic_ctxt->context.bytes = sizeof(*q_ctxt);
-		} else {
-			status = BE_STATUS_NO_MCC_WRB;
-			goto Error;
-		}
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_MULTICAST_SET);
-
-	fwcmd->params.request.promiscuous = promiscuous;
-	if (!promiscuous) {
-		fwcmd->params.request.num_mac = num;
-		if (num > 0) {
-			ASSERT(mac_table);
-			memcpy(fwcmd->params.request.mac,
-						mac_table, ETH_ALEN * num);
-		}
-	}
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
-			cb, cb_context, NULL, NULL, fwcmd, NULL);
-	if (status < 0) {
-		TRACE(DL_ERR, "multicast fwcmd failed.");
-		goto Error;
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-    This routine adds or removes a vlan tag from the rxf table.
-
-    FunctionObject  - Function object handle.
-    VLanTag         - VLan tag to add or remove.
-    Add             - Set to TRUE if this will add a vlan tag
-
-    Returns BE_SUCCESS if successfull, otherwise a useful int is returned.
-
-    IRQL: < DISPATCH_LEVEL
-*/
-int be_rxf_vlan_config(struct be_function_object *pfob,
-		bool promiscuous, u32 num, u16 *vlan_tag_array,
-		mcc_wrb_cqe_callback cb,	/* optional */
-		void *cb_context,
-		struct be_vlan_q_ctxt *q_ctxt)	/* optional */
-{
-	int status = BE_SUCCESS;
-	struct FWCMD_COMMON_NTWK_VLAN_CONFIG *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	struct be_generic_q_ctxt *generic_ctxt = NULL;
-	unsigned long irql;
-
-	if (num > ARRAY_SIZE(fwcmd->params.request.vlan_tag)) {
-		TRACE(DL_ERR, "Too many VLAN tags.");
-		return BE_NOT_OK;
-	}
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		if (q_ctxt && cb) {
-			wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
-			generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
-			generic_ctxt->context.bytes = sizeof(*q_ctxt);
-		} else {
-			status = BE_STATUS_NO_MCC_WRB;
-			goto Error;
-		}
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_VLAN_CONFIG);
-
-	fwcmd->params.request.promiscuous = promiscuous;
-	if (!promiscuous) {
-		fwcmd->params.request.num_vlan = num;
-
-		if (num > 0) {
-			ASSERT(vlan_tag_array);
-			memcpy(fwcmd->params.request.vlan_tag, vlan_tag_array,
-				  num * sizeof(vlan_tag_array[0]));
-		}
-	}
-
-	/* Post the commadn */
-	status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
-			cb, cb_context, NULL, NULL, fwcmd, NULL);
-	if (status < 0) {
-		TRACE(DL_ERR, "vlan fwcmd failed.");
-		goto Error;
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-
-int be_rxf_link_status(struct be_function_object *pfob,
-		struct BE_LINK_STATUS *link_status,
-		mcc_wrb_cqe_callback cb,
-		void *cb_context,
-		struct be_link_status_q_ctxt *q_ctxt)
-{
-	struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	struct be_generic_q_ctxt *generic_ctxt = NULL;
-	unsigned long irql;
-	struct be_mcc_wrb_response_copy rc;
-
-	ASSERT(link_status);
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-
-	if (!wrb) {
-		if (q_ctxt && cb) {
-			wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
-			generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
-			generic_ctxt->context.bytes = sizeof(*q_ctxt);
-		} else {
-			status = BE_STATUS_NO_MCC_WRB;
-			goto Error;
-		}
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb,
-					       COMMON_NTWK_LINK_STATUS_QUERY);
-
-	rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY,
-					params.response);
-	rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY,
-					params.response);
-	rc.va = link_status;
-	/* Post or queue the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
-			cb, cb_context, NULL, NULL, fwcmd, &rc);
-
-	if (status < 0) {
-		TRACE(DL_ERR, "link status fwcmd failed.");
-		goto Error;
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-int
-be_rxf_query_eth_statistics(struct be_function_object *pfob,
-		    struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd,
-		    u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb,
-		    void *cb_context,
-		    struct be_nonembedded_q_ctxt *q_ctxt)
-{
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	struct be_generic_q_ctxt *generic_ctxt = NULL;
-	unsigned long irql;
-
-	ASSERT(va_for_fwcmd);
-	ASSERT(pa_for_fwcmd);
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-
-	if (!wrb) {
-		if (q_ctxt && cb) {
-			wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
-			generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
-			generic_ctxt->context.bytes = sizeof(*q_ctxt);
-		} else {
-			status = BE_STATUS_NO_MCC_WRB;
-			goto Error;
-		}
-	}
-
-	TRACE(DL_INFO, "Query eth stats. fwcmd va:%p pa:0x%08x_%08x",
-	      va_for_fwcmd, upper_32_bits(pa_for_fwcmd), (u32)pa_for_fwcmd);
-
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	va_for_fwcmd = BE_PREPARE_NONEMBEDDED_FWCMD(pfob, wrb,
-			  va_for_fwcmd, pa_for_fwcmd, ETH_GET_STATISTICS);
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
-		cb, cb_context, NULL, NULL, va_for_fwcmd, NULL);
-	if (status < 0) {
-		TRACE(DL_ERR, "eth stats fwcmd failed.");
-		goto Error;
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-int
-be_rxf_promiscuous(struct be_function_object *pfob,
-		   bool enable_port0, bool enable_port1,
-		   mcc_wrb_cqe_callback cb, void *cb_context,
-		   struct be_promiscuous_q_ctxt *q_ctxt)
-{
-	struct FWCMD_ETH_PROMISCUOUS *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	struct be_generic_q_ctxt *generic_ctxt = NULL;
-	unsigned long irql;
-
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-
-	if (!wrb) {
-		if (q_ctxt && cb) {
-			wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
-			generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
-			generic_ctxt->context.bytes = sizeof(*q_ctxt);
-		} else {
-			status = BE_STATUS_NO_MCC_WRB;
-			goto Error;
-		}
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_PROMISCUOUS);
-
-	fwcmd->params.request.port0_promiscuous = enable_port0;
-	fwcmd->params.request.port1_promiscuous = enable_port1;
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
-			cb, cb_context, NULL, NULL, fwcmd, NULL);
-
-	if (status < 0) {
-		TRACE(DL_ERR, "promiscuous fwcmd failed.");
-		goto Error;
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-
-/*
- *-------------------------------------------------------------------------
- * Function: be_rxf_filter_config
- *   Configures BladeEngine ethernet receive filter settings.
- * pfob    -
- * settings           - Pointer to the requested filter settings.
- * 			The response from BladeEngine will be placed back
- * 			in this structure.
- * cb                 - optional
- * cb_context         - optional
- * q_ctxt             - Optional. Pointer to a previously allocated struct.
- * 			If the MCC WRB ring is full, this structure is
- * 			used to queue the operation. It will be posted
- * 			to the MCC ring when space becomes available. All
- *                      queued commands will be posted to the ring in
- *                      the order they are received. It is always valid
- *                      to pass a pointer to a generic
- *                      be_generic_q_ctxt. However, the specific
- *                      context structs are generally smaller than
- *                      the generic struct.
- * return pend_status - BE_SUCCESS (0) on success.
- * 			BE_PENDING (postive value) if the FWCMD
- *                      completion is pending. Negative error code on failure.
- *---------------------------------------------------------------------------
- */
-int
-be_rxf_filter_config(struct be_function_object *pfob,
-		     struct NTWK_RX_FILTER_SETTINGS *settings,
-		     mcc_wrb_cqe_callback cb, void *cb_context,
-		     struct be_rxf_filter_q_ctxt *q_ctxt)
-{
-	struct FWCMD_COMMON_NTWK_RX_FILTER *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	struct be_generic_q_ctxt *generic_ctxt = NULL;
-	unsigned long irql;
-	struct be_mcc_wrb_response_copy rc;
-
-	ASSERT(settings);
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-
-	if (!wrb) {
-		if (q_ctxt && cb) {
-			wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
-			generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
-			generic_ctxt->context.bytes = sizeof(*q_ctxt);
-		} else {
-			status = BE_STATUS_NO_MCC_WRB;
-			goto Error;
-		}
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_RX_FILTER);
-	memcpy(&fwcmd->params.request, settings, sizeof(*settings));
-
-	rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_RX_FILTER,
-					params.response);
-	rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_RX_FILTER,
-					params.response);
-	rc.va = settings;
-	/* Post or queue the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
-			cb, cb_context, NULL, NULL, fwcmd, &rc);
-
-	if (status < 0) {
-		TRACE(DL_ERR, "RXF/ERX filter config fwcmd failed.");
-		goto Error;
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
diff --git a/drivers/staging/benet/etx_context.h b/drivers/staging/benet/etx_context.h
deleted file mode 100644
index 554fbe5..0000000
--- a/drivers/staging/benet/etx_context.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __etx_context_amap_h__
-#define __etx_context_amap_h__
-
-/* ETX ring  context structure. */
-struct BE_ETX_CONTEXT_AMAP {
-	u8 tx_cidx[11];	/* DWORD 0 */
-	u8 rsvd0[5];	/* DWORD 0 */
-	u8 rsvd1[16];	/* DWORD 0 */
-	u8 tx_pidx[11];	/* DWORD 1 */
-	u8 rsvd2;		/* DWORD 1 */
-	u8 tx_ring_size[4];	/* DWORD 1 */
-	u8 pd_id[5];	/* DWORD 1 */
-	u8 pd_id_not_valid;	/* DWORD 1 */
-	u8 cq_id_send[10];	/* DWORD 1 */
-	u8 rsvd3[32];	/* DWORD 2 */
-	u8 rsvd4[32];	/* DWORD 3 */
-	u8 cur_bytes[32];	/* DWORD 4 */
-	u8 max_bytes[32];	/* DWORD 5 */
-	u8 time_stamp[32];	/* DWORD 6 */
-	u8 rsvd5[11];	/* DWORD 7 */
-	u8 func;		/* DWORD 7 */
-	u8 rsvd6[20];	/* DWORD 7 */
-	u8 cur_txd_count[32];	/* DWORD 8 */
-	u8 max_txd_count[32];	/* DWORD 9 */
-	u8 rsvd7[32];	/* DWORD 10 */
-	u8 rsvd8[32];	/* DWORD 11 */
-	u8 rsvd9[32];	/* DWORD 12 */
-	u8 rsvd10[32];	/* DWORD 13 */
-	u8 rsvd11[32];	/* DWORD 14 */
-	u8 rsvd12[32];	/* DWORD 15 */
-} __packed;
-struct ETX_CONTEXT_AMAP {
-	u32 dw[16];
-};
-
-#endif /* __etx_context_amap_h__ */
diff --git a/drivers/staging/benet/funcobj.c b/drivers/staging/benet/funcobj.c
deleted file mode 100644
index 0f57eb5..0000000
--- a/drivers/staging/benet/funcobj.c
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#include "hwlib.h"
-#include "bestatus.h"
-
-
-int
-be_function_internal_query_firmware_config(struct be_function_object *pfob,
-				   struct BE_FIRMWARE_CONFIG *config)
-{
-	struct FWCMD_COMMON_FIRMWARE_CONFIG *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	unsigned long irql;
-	struct be_mcc_wrb_response_copy rc;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_FIRMWARE_CONFIG);
-
-	rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_FIRMWARE_CONFIG,
-					params.response);
-	rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_FIRMWARE_CONFIG,
-					params.response);
-	rc.va = config;
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL,
-					NULL, NULL, NULL, fwcmd, &rc);
-error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-    This allocates and initializes a function object based on the information
-    provided by upper layer drivers.
-
-    Returns BE_SUCCESS on success and an appropriate int on failure.
-
-    A function object represents a single BladeEngine (logical) PCI function.
-    That is a function object either represents
-    the networking side of BladeEngine or the iSCSI side of BladeEngine.
-
-    This routine will also detect and create an appropriate PD object for the
-    PCI function as needed.
-*/
-int
-be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va,
-		u8 __iomem *pci_va, u32 function_type,
-		struct ring_desc *mailbox, struct be_function_object *pfob)
-{
-	int status;
-
-	ASSERT(pfob);	/* not a magic assert */
-	ASSERT(function_type <= 2);
-
-	TRACE(DL_INFO, "Create function object. type:%s object:0x%p",
-	      (function_type == BE_FUNCTION_TYPE_ISCSI ? "iSCSI" :
-	       (function_type == BE_FUNCTION_TYPE_NETWORK ? "Network" :
-		"Arm")), pfob);
-
-	memset(pfob, 0, sizeof(*pfob));
-
-	pfob->type = function_type;
-	pfob->csr_va = csr_va;
-	pfob->db_va = db_va;
-	pfob->pci_va = pci_va;
-
-	spin_lock_init(&pfob->cq_lock);
-	spin_lock_init(&pfob->post_lock);
-	spin_lock_init(&pfob->mcc_context_lock);
-
-
-	pfob->pci_function_number = 1;
-
-
-	pfob->emulate = false;
-	TRACE(DL_NOTE, "Non-emulation mode");
-	status = be_drive_POST(pfob);
-	if (status != BE_SUCCESS) {
-		TRACE(DL_ERR, "BladeEngine POST failed.");
-		goto error;
-	}
-
-	/* Initialize the mailbox */
-	status = be_mpu_init_mailbox(pfob, mailbox);
-	if (status != BE_SUCCESS) {
-		TRACE(DL_ERR, "Failed to initialize mailbox.");
-		goto error;
-	}
-	/*
-	 * Cache the firmware config for ASSERTs in hwclib and later
-	 * driver queries.
-	 */
-	status = be_function_internal_query_firmware_config(pfob,
-					       &pfob->fw_config);
-	if (status != BE_SUCCESS) {
-		TRACE(DL_ERR, "Failed to query firmware config.");
-		goto error;
-	}
-
-error:
-	if (status != BE_SUCCESS) {
-		/* No cleanup necessary */
-		TRACE(DL_ERR, "Failed to create function.");
-		memset(pfob, 0, sizeof(*pfob));
-	}
-	return status;
-}
-
-/*
-    This routine drops the reference count on a given function object. Once
-    the reference count falls to zero, the function object is destroyed and all
-    resources held are freed.
-
-    FunctionObject      - The function object to drop the reference to.
-*/
-int be_function_object_destroy(struct be_function_object *pfob)
-{
-	TRACE(DL_INFO, "Destroy pfob. Object:0x%p",
-	      pfob);
-
-
-	ASSERT(pfob->mcc == NULL);
-
-	return BE_SUCCESS;
-}
-
-int be_function_cleanup(struct be_function_object *pfob)
-{
-	int status = 0;
-	u32 isr;
-	u32 host_intr;
-	struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl;
-
-
-	if (pfob->type == BE_FUNCTION_TYPE_NETWORK) {
-		status = be_rxf_multicast_config(pfob, false, 0,
-						NULL, NULL, NULL, NULL);
-		ASSERT(status == BE_SUCCESS);
-	}
-	/* VLAN */
-	status = be_rxf_vlan_config(pfob, false, 0, NULL, NULL, NULL, NULL);
-	ASSERT(status == BE_SUCCESS);
-	/*
-	 * MCC Queue -- Switches to mailbox mode.  May want to destroy
-	 * all but the MCC CQ before this call if polling CQ is much better
-	 * performance than polling mailbox register.
-	 */
-	if (pfob->mcc)
-		status = be_mcc_ring_destroy(pfob->mcc);
-	/*
-	 * If interrupts are disabled, clear any CEV interrupt assertions that
-	 * fired after we stopped processing EQs.
-	 */
-	ctrl.dw[0] = PCICFG1_READ(pfob, host_timer_int_ctrl);
-	host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR,
-							hostintr, ctrl.dw);
-	if (!host_intr)
-		if (pfob->type == BE_FUNCTION_TYPE_NETWORK)
-			isr = CSR_READ(pfob, cev.isr1);
-		else
-			isr = CSR_READ(pfob, cev.isr0);
-	else
-		/* This should never happen... */
-		TRACE(DL_ERR, "function_cleanup called with interrupt enabled");
-	/* Function object destroy */
-	status = be_function_object_destroy(pfob);
-	ASSERT(status == BE_SUCCESS);
-
-	return status;
-}
-
-
-void *
-be_function_prepare_embedded_fwcmd(struct be_function_object *pfob,
-	struct MCC_WRB_AMAP *wrb, u32 payld_len, u32 request_length,
-	u32 response_length, u32 opcode, u32 subsystem)
-{
-	struct FWCMD_REQUEST_HEADER *header = NULL;
-	u32 n;
-
-	ASSERT(wrb);
-
-	n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8;
-	AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 1);
-	AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, min(payld_len, n));
-	header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n);
-
-	header->timeout = 0;
-	header->domain = 0;
-	header->request_length = max(request_length, response_length);
-	header->opcode = opcode;
-	header->subsystem = subsystem;
-
-	return header;
-}
-
-void *
-be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob,
-	struct MCC_WRB_AMAP *wrb,
-	void *fwcmd_va, u64 fwcmd_pa,
-	u32 payld_len,
-	u32 request_length,
-	u32 response_length,
-	u32 opcode, u32 subsystem)
-{
-	struct FWCMD_REQUEST_HEADER *header = NULL;
-	u32 n;
-	struct MCC_WRB_PAYLOAD_AMAP *plp;
-
-	ASSERT(wrb);
-	ASSERT(fwcmd_va);
-
-	header = (struct FWCMD_REQUEST_HEADER *) fwcmd_va;
-
-	AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 0);
-	AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, payld_len);
-
-	/*
-	 * Assume one fragment. The caller may override the SGL by
-	 * rewriting the 0th length and adding more entries.  They
-	 * will also need to update the sge_count.
-	 */
-	AMAP_SET_BITS_PTR(MCC_WRB, sge_count, wrb, 1);
-
-	n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8;
-	plp = (struct MCC_WRB_PAYLOAD_AMAP *)((u8 *)wrb + n);
-	AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].length, plp, payld_len);
-	AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_lo, plp, (u32)fwcmd_pa);
-	AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_hi, plp,
-					upper_32_bits(fwcmd_pa));
-
-	header->timeout = 0;
-	header->domain = 0;
-	header->request_length = max(request_length, response_length);
-	header->opcode = opcode;
-	header->subsystem = subsystem;
-
-	return header;
-}
-
-struct MCC_WRB_AMAP *
-be_function_peek_mcc_wrb(struct be_function_object *pfob)
-{
-	struct MCC_WRB_AMAP *wrb = NULL;
-	u32 offset;
-
-	if (pfob->mcc)
-		wrb = _be_mpu_peek_ring_wrb(pfob->mcc, false);
-	else {
-		offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8;
-		wrb = (struct MCC_WRB_AMAP *) ((u8 *) pfob->mailbox.va +
-				offset);
-	}
-
-	if (wrb)
-		memset(wrb, 0, sizeof(struct MCC_WRB_AMAP));
-
-	return wrb;
-}
-
-#if defined(BE_DEBUG)
-void be_function_debug_print_wrb(struct be_function_object *pfob,
-		struct MCC_WRB_AMAP *wrb, void *optional_fwcmd_va,
-		struct be_mcc_wrb_context *wrb_context)
-{
-
-	struct FWCMD_REQUEST_HEADER *header = NULL;
-	u8 embedded;
-	u32 n;
-
-	embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, wrb);
-
-	if (embedded) {
-		n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8;
-		header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n);
-	} else {
-		header = (struct FWCMD_REQUEST_HEADER *) optional_fwcmd_va;
-	}
-
-	/* Save the completed count before posting for a debug assert. */
-
-	if (header) {
-		wrb_context->opcode = header->opcode;
-		wrb_context->subsystem = header->subsystem;
-
-	} else {
-		wrb_context->opcode = 0;
-		wrb_context->subsystem = 0;
-	}
-}
-#else
-#define be_function_debug_print_wrb(a_, b_, c_, d_)
-#endif
-
-int
-be_function_post_mcc_wrb(struct be_function_object *pfob,
-		struct MCC_WRB_AMAP *wrb,
-		struct be_generic_q_ctxt *q_ctxt,
-		mcc_wrb_cqe_callback cb, void *cb_context,
-		mcc_wrb_cqe_callback internal_cb,
-		void *internal_cb_context, void *optional_fwcmd_va,
-		struct be_mcc_wrb_response_copy *rc)
-{
-	int status;
-	struct be_mcc_wrb_context *wrb_context = NULL;
-	u64 *p;
-
-	if (q_ctxt) {
-		/* Initialize context.         */
-		q_ctxt->context.internal_cb = internal_cb;
-		q_ctxt->context.internal_cb_context = internal_cb_context;
-		q_ctxt->context.cb = cb;
-		q_ctxt->context.cb_context = cb_context;
-		if (rc) {
-			q_ctxt->context.copy.length = rc->length;
-			q_ctxt->context.copy.fwcmd_offset = rc->fwcmd_offset;
-			q_ctxt->context.copy.va = rc->va;
-		} else
-			q_ctxt->context.copy.length = 0;
-
-		q_ctxt->context.optional_fwcmd_va = optional_fwcmd_va;
-
-		/* Queue this request */
-		status = be_function_queue_mcc_wrb(pfob, q_ctxt);
-
-		goto Error;
-	}
-	/*
-	 * Allocate a WRB context struct to hold the callback pointers,
-	 * status, etc.  This is required if commands complete out of order.
-	 */
-	wrb_context = _be_mcc_allocate_wrb_context(pfob);
-	if (!wrb_context) {
-		TRACE(DL_WARN, "Failed to allocate MCC WRB context.");
-		status = BE_STATUS_SYSTEM_RESOURCES;
-		goto Error;
-	}
-	/* Initialize context. */
-	memset(wrb_context, 0, sizeof(*wrb_context));
-	wrb_context->internal_cb = internal_cb;
-	wrb_context->internal_cb_context = internal_cb_context;
-	wrb_context->cb = cb;
-	wrb_context->cb_context = cb_context;
-	if (rc) {
-		wrb_context->copy.length = rc->length;
-		wrb_context->copy.fwcmd_offset = rc->fwcmd_offset;
-		wrb_context->copy.va = rc->va;
-	} else
-		wrb_context->copy.length = 0;
-	wrb_context->wrb = wrb;
-
-	/*
-	 * Copy the context pointer into the WRB opaque tag field.
-	 * Verify assumption of 64-bit tag with a compile time assert.
-	 */
-	p = (u64 *) ((u8 *)wrb + offsetof(struct BE_MCC_WRB_AMAP, tag)/8);
-	*p = (u64)(size_t)wrb_context;
-
-	/* Print info about this FWCMD for debug builds. */
-	be_function_debug_print_wrb(pfob, wrb, optional_fwcmd_va, wrb_context);
-
-	/*
-	 * issue the WRB to the MPU as appropriate
-	 */
-	if (pfob->mcc) {
-		/*
-		 * we're in WRB mode, pass to the mcc layer
-		 */
-		status = _be_mpu_post_wrb_ring(pfob->mcc, wrb, wrb_context);
-	} else {
-		/*
-		 * we're in mailbox mode
-		 */
-		status = _be_mpu_post_wrb_mailbox(pfob, wrb, wrb_context);
-
-		/* mailbox mode always completes synchronously */
-		ASSERT(status != BE_STATUS_PENDING);
-	}
-
-Error:
-
-	return status;
-}
-
-int
-be_function_ring_destroy(struct be_function_object *pfob,
-		u32 id, u32 ring_type, mcc_wrb_cqe_callback cb,
-		void *cb_context, mcc_wrb_cqe_callback internal_cb,
-		void *internal_cb_context)
-{
-
-	struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	int status = 0;
-	unsigned long irql;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	TRACE(DL_INFO, "Destroy ring id:%d type:%d", id, ring_type);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		ASSERT(wrb);
-		TRACE(DL_ERR, "No free MCC WRBs in destroy ring.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto Error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY);
-
-	fwcmd->params.request.id = id;
-	fwcmd->params.request.ring_type = ring_type;
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context,
-				internal_cb, internal_cb_context, fwcmd, NULL);
-	if (status != BE_SUCCESS && status != BE_PENDING) {
-		TRACE(DL_ERR, "Ring destroy fwcmd failed. id:%d ring_type:%d",
-			id, ring_type);
-		goto Error;
-	}
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-void
-be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, u32 max_num)
-{
-	u32 num_pages = PAGES_SPANNED(rd->va, rd->length);
-	u32 i = 0;
-	u64 pa = rd->pa;
-	__le64 lepa;
-
-	ASSERT(pa_list);
-	ASSERT(pa);
-
-	for (i = 0; i < min(num_pages, max_num); i++) {
-		lepa = cpu_to_le64(pa);
-		pa_list[i].lo = (u32)lepa;
-		pa_list[i].hi = upper_32_bits(lepa);
-		pa += PAGE_SIZE;
-	}
-}
-
-
-
-/*-----------------------------------------------------------------------------
- * Function: be_function_get_fw_version
- *   Retrieves the firmware version on the adpater. If the callback is
- *   NULL this call executes synchronously. If the callback is not NULL,
- *   the returned status will be BE_PENDING if the command was issued
- *   successfully.
- * pfob    -
- * fwv         - Pointer to response buffer if callback is NULL.
- * cb           - Callback function invoked when the FWCMD completes.
- * cb_context   - Passed to the callback function.
- * return pend_status - BE_SUCCESS (0) on success.
- * 			BE_PENDING (postive value) if the FWCMD
- *                      completion is pending. Negative error code on failure.
- *---------------------------------------------------------------------------
- */
-int
-be_function_get_fw_version(struct be_function_object *pfob,
-		struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fwv,
-		mcc_wrb_cqe_callback cb, void *cb_context)
-{
-	int status = BE_SUCCESS;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	struct FWCMD_COMMON_GET_FW_VERSION *fwcmd = NULL;
-	unsigned long irql;
-	struct be_mcc_wrb_response_copy rc;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		TRACE(DL_ERR, "MCC wrb peek failed.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto Error;
-	}
-
-	if (!cb && !fwv) {
-		TRACE(DL_ERR, "callback and response buffer NULL!");
-		status = BE_NOT_OK;
-		goto Error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FW_VERSION);
-
-	rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_GET_FW_VERSION,
-					params.response);
-	rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_GET_FW_VERSION,
-					params.response);
-	rc.va = fwv;
-
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb,
-				cb_context, NULL, NULL, fwcmd, &rc);
-
-Error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-int
-be_function_queue_mcc_wrb(struct be_function_object *pfob,
-			  struct be_generic_q_ctxt *q_ctxt)
-{
-	int status;
-
-	ASSERT(q_ctxt);
-
-	/*
-	 * issue the WRB to the MPU as appropriate
-	 */
-	if (pfob->mcc) {
-
-		/* We're in ring mode.  Queue this item. */
-		pfob->mcc->backlog_length++;
-		list_add_tail(&q_ctxt->context.list, &pfob->mcc->backlog);
-		status = BE_PENDING;
-	} else {
-		status = BE_NOT_OK;
-	}
-	return status;
-}
-
diff --git a/drivers/staging/benet/fwcmd_common.h b/drivers/staging/benet/fwcmd_common.h
deleted file mode 100644
index 406e0d6..0000000
--- a/drivers/staging/benet/fwcmd_common.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __fwcmd_common_amap_h__
-#define __fwcmd_common_amap_h__
-#include "host_struct.h"
-
-/* --- PHY_LINK_DUPLEX_ENUM --- */
-#define PHY_LINK_DUPLEX_NONE            (0)
-#define PHY_LINK_DUPLEX_HALF            (1)
-#define PHY_LINK_DUPLEX_FULL            (2)
-
-/* --- PHY_LINK_SPEED_ENUM --- */
-#define PHY_LINK_SPEED_ZERO             (0)	/* No link. */
-#define PHY_LINK_SPEED_10MBPS           (1)	/* 10 Mbps */
-#define PHY_LINK_SPEED_100MBPS          (2)	/* 100 Mbps */
-#define PHY_LINK_SPEED_1GBPS            (3)	/* 1 Gbps */
-#define PHY_LINK_SPEED_10GBPS           (4)	/* 10 Gbps */
-
-/* --- PHY_LINK_FAULT_ENUM --- */
-#define PHY_LINK_FAULT_NONE             (0)	/* No fault status
-							available or detected */
-#define PHY_LINK_FAULT_LOCAL            (1)	/* Local fault detected */
-#define PHY_LINK_FAULT_REMOTE           (2)	/* Remote fault detected */
-
-/* --- BE_ULP_MASK --- */
-#define BE_ULP0_MASK                    (1)
-#define BE_ULP1_MASK                    (2)
-#define BE_ULP2_MASK                    (4)
-
-/* --- NTWK_ACTIVE_PORT --- */
-#define NTWK_PORT_A                     (0)	/* Port A is currently active */
-#define NTWK_PORT_B                     (1)	/* Port B is currently active */
-#define NTWK_NO_ACTIVE_PORT             (15)	/* Both ports have lost link */
-
-/* --- NTWK_LINK_TYPE --- */
-#define NTWK_LINK_TYPE_PHYSICAL         (0)	/* link up/down event
-						   applies to BladeEngine's
-						   Physical Ports
-						   */
-#define NTWK_LINK_TYPE_VIRTUAL          (1)	/* Virtual link up/down event
-						   reported by BladeExchange.
-						   This applies only when the
-						   VLD feature is enabled
-						   */
-
-/*
- * --- FWCMD_MAC_TYPE_ENUM ---
- * This enum defines the types of MAC addresses in the RXF MAC Address Table.
- */
-#define MAC_ADDRESS_TYPE_STORAGE        (0)	/* Storage MAC Address */
-#define MAC_ADDRESS_TYPE_NETWORK        (1)	/* Network MAC Address */
-#define MAC_ADDRESS_TYPE_PD             (2)	/* Protection Domain MAC Addr */
-#define MAC_ADDRESS_TYPE_MANAGEMENT     (3)	/* Managment MAC Address */
-
-
-/* --- FWCMD_RING_TYPE_ENUM --- */
-#define FWCMD_RING_TYPE_ETH_RX          (1)	/* Ring created with */
-					/* FWCMD_COMMON_ETH_RX_CREATE. */
-#define FWCMD_RING_TYPE_ETH_TX          (2)	/* Ring created with */
-					/* FWCMD_COMMON_ETH_TX_CREATE. */
-#define FWCMD_RING_TYPE_ISCSI_WRBQ      (3)	/* Ring created with */
-					/* FWCMD_COMMON_ISCSI_WRBQ_CREATE. */
-#define FWCMD_RING_TYPE_ISCSI_DEFQ      (4)	/* Ring created with */
-					/* FWCMD_COMMON_ISCSI_DEFQ_CREATE. */
-#define FWCMD_RING_TYPE_TPM_WRBQ        (5)	/* Ring created with */
-					/* FWCMD_COMMON_TPM_WRBQ_CREATE. */
-#define FWCMD_RING_TYPE_TPM_DEFQ        (6)	/* Ring created with */
-					/* FWCMD_COMMONTPM_TDEFQ_CREATE. */
-#define FWCMD_RING_TYPE_TPM_RQ          (7)	/* Ring created with */
-					/* FWCMD_COMMON_TPM_RQ_CREATE. */
-#define FWCMD_RING_TYPE_MCC             (8)	/* Ring created with */
-					/* FWCMD_COMMON_MCC_CREATE. */
-#define FWCMD_RING_TYPE_CQ              (9)	/* Ring created with */
-					/* FWCMD_COMMON_CQ_CREATE. */
-#define FWCMD_RING_TYPE_EQ              (10)	/* Ring created with */
-					/* FWCMD_COMMON_EQ_CREATE. */
-#define FWCMD_RING_TYPE_QP              (11)	/* Ring created with */
-					/* FWCMD_RDMA_QP_CREATE. */
-
-
-/* --- ETH_TX_RING_TYPE_ENUM --- */
-#define ETH_TX_RING_TYPE_FORWARDING     (1)	/* Ethernet ring for
-						   forwarding packets */
-#define ETH_TX_RING_TYPE_STANDARD       (2)	/* Ethernet ring for sending
-						   network packets. */
-#define ETH_TX_RING_TYPE_BOUND          (3)	/* Ethernet ring bound to the
-						   port specified in the command
-						   header.port_number field.
-						   Rings of this type are
-						   NOT subject to the
-						   failover logic implemented
-						   in the BladeEngine.
-						   */
-
-/* --- FWCMD_COMMON_QOS_TYPE_ENUM --- */
-#define QOS_BITS_NIC                    (1)	/* max_bits_per_second_NIC */
-						  /* field is valid.  */
-#define QOS_PKTS_NIC                    (2)	/* max_packets_per_second_NIC */
-						  /* field is valid.  */
-#define QOS_IOPS_ISCSI                  (4)	/* max_ios_per_second_iSCSI */
-						  /*field is valid.  */
-#define QOS_VLAN_TAG                    (8)	/* domain_VLAN_tag field
-						   is valid. */
-#define QOS_FABRIC_ID                   (16)	/* fabric_domain_ID field
-						   is valid. */
-#define QOS_OEM_PARAMS                  (32)	/* qos_params_oem field
-						   is valid. */
-#define QOS_TPUT_ISCSI                  (64)	/* max_bytes_per_second_iSCSI
-						   field  is valid.  */
-
-
-/*
- * --- FAILOVER_CONFIG_ENUM ---
- * Failover configuration setting used in FWCMD_COMMON_FORCE_FAILOVER
- */
-#define FAILOVER_CONFIG_NO_CHANGE       (0)	/* No change to automatic */
-						  /* port failover setting. */
-#define FAILOVER_CONFIG_ON              (1)	/* Automatic port failover
-						   on link down  is enabled. */
-#define FAILOVER_CONFIG_OFF             (2)	/* Automatic port failover
-						   on link down is disabled. */
-
-/*
- * --- FAILOVER_PORT_ENUM ---
- * Failover port setting used in FWCMD_COMMON_FORCE_FAILOVER
- */
-#define FAILOVER_PORT_A                 (0)	/* Selects port A. */
-#define FAILOVER_PORT_B                 (1)	/* Selects port B. */
-#define FAILOVER_PORT_NONE              (15)	/* No port change requested. */
-
-
-/*
- * --- MGMT_FLASHROM_OPCODE ---
- * Flash ROM operation code
- */
-#define MGMT_FLASHROM_OPCODE_FLASH      (1)	/* Commit downloaded data
-						   to Flash ROM */
-#define MGMT_FLASHROM_OPCODE_SAVE       (2)	/* Save downloaded data to
-						   ARM's DDR - do not flash */
-#define MGMT_FLASHROM_OPCODE_CLEAR      (3)	/* Erase specified component
-						   from FlashROM */
-#define MGMT_FLASHROM_OPCODE_REPORT     (4)	/* Read specified component
-						   from Flash ROM */
-#define MGMT_FLASHROM_OPCODE_IMAGE_INFO (5)	/* Returns size of a
-						   component */
-
-/*
- * --- MGMT_FLASHROM_OPTYPE ---
- * Flash ROM operation type
- */
-#define MGMT_FLASHROM_OPTYPE_CODE_FIRMWARE (0)	/* Includes ARM firmware,
-						   IPSec (optional) and EP
-						   firmware  */
-#define MGMT_FLASHROM_OPTYPE_CODE_REDBOOT (1)
-#define MGMT_FLASHROM_OPTYPE_CODE_BIOS  (2)
-#define MGMT_FLASHROM_OPTYPE_CODE_PXE_BIOS (3)
-#define MGMT_FLASHROM_OPTYPE_CODE_CTRLS (4)
-#define MGMT_FLASHROM_OPTYPE_CFG_IPSEC  (5)
-#define MGMT_FLASHROM_OPTYPE_CFG_INI    (6)
-#define MGMT_FLASHROM_OPTYPE_ROM_OFFSET_SPECIFIED (7)
-
-/*
- * --- FLASHROM_TYPE ---
- * Flash ROM manufacturers supported in the f/w
- */
-#define INTEL                           (0)
-#define SPANSION                        (1)
-#define MICRON                          (2)
-
-/* --- DDR_CAS_TYPE --- */
-#define CAS_3                           (0)
-#define CAS_4                           (1)
-#define CAS_5                           (2)
-
-/* --- DDR_SIZE_TYPE --- */
-#define SIZE_256MB                      (0)
-#define SIZE_512MB                      (1)
-
-/* --- DDR_MODE_TYPE --- */
-#define DDR_NO_ECC                      (0)
-#define DDR_ECC                         (1)
-
-/* --- INTERFACE_10GB_TYPE --- */
-#define CX4_TYPE                        (0)
-#define XFP_TYPE                        (1)
-
-/* --- BE_CHIP_MAX_MTU --- */
-#define CHIP_MAX_MTU                    (9000)
-
-/* --- XAUI_STATE_ENUM --- */
-#define XAUI_STATE_ENABLE               (0)	/* This MUST be the default
-						   value for all requests
-						   which set/change
-						   equalization parameter.  */
-#define XAUI_STATE_DISABLE              (255)	/* The XAUI for both ports
-						   may be disabled for EMI
-						   tests. There is no
-						   provision for turning off
-						   individual ports.
-						   */
-/* --- BE_ASIC_REVISION --- */
-#define BE_ASIC_REV_A0                  (1)
-#define BE_ASIC_REV_A1                  (2)
-
-#endif /* __fwcmd_common_amap_h__ */
diff --git a/drivers/staging/benet/fwcmd_common_bmap.h b/drivers/staging/benet/fwcmd_common_bmap.h
deleted file mode 100644
index a007cf2..0000000
--- a/drivers/staging/benet/fwcmd_common_bmap.h
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __fwcmd_common_bmap_h__
-#define __fwcmd_common_bmap_h__
-#include "fwcmd_types_bmap.h"
-#include "fwcmd_hdr_bmap.h"
-
-#if defined(__BIG_ENDIAN)
-   /* Physical Address. */
-struct PHYS_ADDR {
-	union {
-		struct {
-			u32 lo;	/* DWORD 0 */
-			u32 hi;	/* DWORD 1 */
-		} __packed;	/* unnamed struct */
-		u32 dw[2];	/* dword union */
-	};			/* unnamed union */
-} __packed ;
-
-
-#else
-   /* Physical Address. */
-struct PHYS_ADDR {
-	union {
-		struct {
-			u32 lo;	/* DWORD 0 */
-			u32 hi;	/* DWORD 1 */
-		} __packed;	/* unnamed struct */
-		u32 dw[2];	/* dword union */
-	};			/* unnamed union */
-} __packed ;
-
-struct BE_LINK_STATUS {
-	u8 mac0_duplex;
-	u8 mac0_speed;
-	u8 mac1_duplex;
-	u8 mac1_speed;
-	u8 mgmt_mac_duplex;
-	u8 mgmt_mac_speed;
-	u8 active_port;
-	u8 rsvd0;
-	u8 mac0_fault;
-	u8 mac1_fault;
-	u16 rsvd1;
-} __packed;
-#endif
-
-struct FWCMD_COMMON_ANON_170_REQUEST {
-	u32 rsvd0;
-} __packed;
-
-union LINK_STATUS_QUERY_PARAMS {
-	struct BE_LINK_STATUS response;
-	struct FWCMD_COMMON_ANON_170_REQUEST request;
-} __packed;
-
-/*
- *  Queries the the link status for all ports.  The valid values below
- *  DO NOT indicate that  a particular duplex or speed is supported by
- *  BladeEngine. These enumerations simply  list all possible duplexes
- *  and speeds for any port. Consult BladeEngine product  documentation
- *  for the supported parameters.
- */
-struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY {
-	union FWCMD_HEADER header;
-	union LINK_STATUS_QUERY_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_ANON_171_REQUEST {
-	u8 type;
-	u8 port;
-	u8 mac1;
-	u8 permanent;
-} __packed;
-
-struct FWCMD_COMMON_ANON_172_RESPONSE {
-	struct MAC_ADDRESS_FORMAT mac;
-} __packed;
-
-union NTWK_MAC_QUERY_PARAMS {
-	struct FWCMD_COMMON_ANON_171_REQUEST request;
-	struct FWCMD_COMMON_ANON_172_RESPONSE response;
-} __packed;
-
-/* Queries one MAC address.  */
-struct FWCMD_COMMON_NTWK_MAC_QUERY {
-	union FWCMD_HEADER header;
-	union NTWK_MAC_QUERY_PARAMS params;
-} __packed;
-
-struct MAC_SET_PARAMS_IN {
-	u8 type;
-	u8 port;
-	u8 mac1;
-	u8 invalidate;
-	struct MAC_ADDRESS_FORMAT mac;
-} __packed;
-
-struct MAC_SET_PARAMS_OUT {
-	u32 rsvd0;
-} __packed;
-
-union MAC_SET_PARAMS {
-	struct MAC_SET_PARAMS_IN request;
-	struct MAC_SET_PARAMS_OUT response;
-} __packed;
-
-/* Sets a MAC address.  */
-struct FWCMD_COMMON_NTWK_MAC_SET {
-	union FWCMD_HEADER header;
-	union MAC_SET_PARAMS params;
-} __packed;
-
-/* MAC address list. */
-struct NTWK_MULTICAST_MAC_LIST {
-	u8 byte[6];
-} __packed;
-
-struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD {
-	u16 num_mac;
-	u8 promiscuous;
-	u8 rsvd0;
-	struct NTWK_MULTICAST_MAC_LIST mac[32];
-} __packed;
-
-struct FWCMD_COMMON_ANON_174_RESPONSE {
-	u32 rsvd0;
-} __packed;
-
-union FWCMD_COMMON_ANON_173_PARAMS {
-	struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD request;
-	struct FWCMD_COMMON_ANON_174_RESPONSE response;
-} __packed;
-
-/*
- *  Sets multicast address hash. The MPU will merge the MAC address lists
- *  from all clients,  including the networking and storage functions.
- *  This command may fail if the final merged  list of MAC addresses exceeds
- *  32 entries.
- */
-struct FWCMD_COMMON_NTWK_MULTICAST_SET {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_173_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD {
-	u16 num_vlan;
-	u8 promiscuous;
-	u8 rsvd0;
-	u16 vlan_tag[32];
-} __packed;
-
-struct FWCMD_COMMON_ANON_176_RESPONSE {
-	u32 rsvd0;
-} __packed;
-
-union FWCMD_COMMON_ANON_175_PARAMS {
-	struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD request;
-	struct FWCMD_COMMON_ANON_176_RESPONSE response;
-} __packed;
-
-/*
- *  Sets VLAN tag filter. The MPU will merge the VLAN tag list from all
- *  clients, including  the networking and storage functions. This command
- *  may fail if the final vlan_tag array  (from all functions) is longer
- *  than 32 entries.
- */
-struct FWCMD_COMMON_NTWK_VLAN_CONFIG {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_175_PARAMS params;
-} __packed;
-
-struct RING_DESTROY_REQUEST {
-	u16 ring_type;
-	u16 id;
-	u8 bypass_flush;
-	u8 rsvd0;
-	u16 rsvd1;
-} __packed;
-
-struct FWCMD_COMMON_ANON_190_RESPONSE {
-	u32 rsvd0;
-} __packed;
-
-union FWCMD_COMMON_ANON_189_PARAMS {
-	struct RING_DESTROY_REQUEST request;
-	struct FWCMD_COMMON_ANON_190_RESPONSE response;
-} __packed;
-/*
- *  Command for destroying any ring. The connection(s) using the ring should
- *  be quiesced  before destroying the ring.
- */
-struct FWCMD_COMMON_RING_DESTROY {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_189_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_ANON_192_REQUEST {
-	u16 num_pages;
-	u16 rsvd0;
-	struct CQ_CONTEXT_AMAP context;
-	struct PHYS_ADDR pages[4];
-} __packed ;
-
-struct FWCMD_COMMON_ANON_193_RESPONSE {
-	u16 cq_id;
-} __packed ;
-
-union FWCMD_COMMON_ANON_191_PARAMS {
-	struct FWCMD_COMMON_ANON_192_REQUEST request;
-	struct FWCMD_COMMON_ANON_193_RESPONSE response;
-} __packed ;
-
-/*
- *  Command for creating a completion queue. A Completion Queue must span
- *  at least 1 page and  at most 4 pages. Each completion queue entry
- *  is 16 bytes regardless of CQ entry format.  Thus the ring must be
- *  at least 256 entries deep (corresponding to 1 page) and can be at
- *   most 1024 entries deep (corresponding to 4 pages). The number of
- *  pages posted must  contain the CQ ring size as encoded in the context.
- *
- */
-struct FWCMD_COMMON_CQ_CREATE {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_191_PARAMS params;
-} __packed ;
-
-struct FWCMD_COMMON_ANON_198_REQUEST {
-	u16 num_pages;
-	u16 rsvd0;
-	struct EQ_CONTEXT_AMAP context;
-	struct PHYS_ADDR pages[8];
-} __packed ;
-
-struct FWCMD_COMMON_ANON_199_RESPONSE {
-	u16 eq_id;
-} __packed ;
-
-union FWCMD_COMMON_ANON_197_PARAMS {
-	struct FWCMD_COMMON_ANON_198_REQUEST request;
-	struct FWCMD_COMMON_ANON_199_RESPONSE response;
-} __packed ;
-
-/*
- *  Command for creating a event queue. An Event Queue must span at least
- *  1 page and at most  8 pages. The number of pages posted must contain
- *  the EQ ring. The ring is defined by  the size of the EQ entries (encoded
- *  in the context) and the number of EQ entries (also  encoded in the
- *  context).
- */
-struct FWCMD_COMMON_EQ_CREATE {
-	union  FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_197_PARAMS params;
-} __packed ;
-
-struct FWCMD_COMMON_ANON_201_REQUEST {
-	u16 cq_id;
-	u16 bcmc_cq_id;
-	u16 num_pages;
-	u16 rsvd0;
-	struct PHYS_ADDR pages[2];
-} __packed;
-
-struct FWCMD_COMMON_ANON_202_RESPONSE {
-	u16 id;
-} __packed;
-
-union FWCMD_COMMON_ANON_200_PARAMS {
-	struct FWCMD_COMMON_ANON_201_REQUEST request;
-	struct FWCMD_COMMON_ANON_202_RESPONSE response;
-} __packed;
-
-/*
- *  Command for creating Ethernet receive ring.  An ERX ring contains ETH_RX_D
- *  entries (8  bytes each). An ERX ring must be 1024 entries deep
- *  (corresponding to 2 pages).
- */
-struct FWCMD_COMMON_ETH_RX_CREATE {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_200_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_ANON_204_REQUEST {
-	u16 num_pages;
-	u8 ulp_num;
-	u8 type;
-	struct ETX_CONTEXT_AMAP context;
-	struct PHYS_ADDR pages[8];
-} __packed ;
-
-struct FWCMD_COMMON_ANON_205_RESPONSE {
-	u16 cid;
-	u8 ulp_num;
-	u8 rsvd0;
-} __packed ;
-
-union FWCMD_COMMON_ANON_203_PARAMS {
-	struct FWCMD_COMMON_ANON_204_REQUEST request;
-	struct FWCMD_COMMON_ANON_205_RESPONSE response;
-} __packed ;
-
-/*
- *  Command for creating an Ethernet transmit ring.  An ETX ring contains
- *  ETH_WRB entries (16  bytes each). An ETX ring must be at least 256
- *  entries deep (corresponding to 1 page)  and at most 2k entries deep
- *  (corresponding to 8 pages).
- */
-struct FWCMD_COMMON_ETH_TX_CREATE {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_203_PARAMS params;
-} __packed ;
-
-struct FWCMD_COMMON_ANON_222_REQUEST {
-	u16 num_pages;
-	u16 rsvd0;
-	struct MCC_RING_CONTEXT_AMAP context;
-	struct PHYS_ADDR pages[8];
-} __packed ;
-
-struct FWCMD_COMMON_ANON_223_RESPONSE {
-	u16 id;
-} __packed ;
-
-union FWCMD_COMMON_ANON_221_PARAMS {
-	struct FWCMD_COMMON_ANON_222_REQUEST request;
-	struct FWCMD_COMMON_ANON_223_RESPONSE response;
-} __packed ;
-
-/*
- *  Command for creating the MCC ring. An MCC ring must be at least 16
- *  entries deep  (corresponding to 1 page) and at most 128 entries deep
- *  (corresponding to 8 pages).
- */
-struct FWCMD_COMMON_MCC_CREATE {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_221_PARAMS params;
-} __packed ;
-
-struct GET_QOS_IN {
-	u32 qos_params_rsvd;
-} __packed;
-
-struct GET_QOS_OUT {
-	u32 max_bits_per_second_NIC;
-	u32 max_packets_per_second_NIC;
-	u32 max_ios_per_second_iSCSI;
-	u32 max_bytes_per_second_iSCSI;
-	u16 domain_VLAN_tag;
-	u16 fabric_domain_ID;
-	u32 qos_params_oem[4];
-} __packed;
-
-union GET_QOS_PARAMS {
-	struct GET_QOS_IN request;
-	struct GET_QOS_OUT response;
-} __packed;
-
-/* QOS/Bandwidth settings per domain. Applicable only in VMs.  */
-struct FWCMD_COMMON_GET_QOS {
-	union FWCMD_HEADER header;
-	union GET_QOS_PARAMS params;
-} __packed;
-
-struct SET_QOS_IN {
-	u32 valid_flags;
-	u32 max_bits_per_second_NIC;
-	u32 max_packets_per_second_NIC;
-	u32 max_ios_per_second_iSCSI;
-	u32 max_bytes_per_second_iSCSI;
-	u16 domain_VLAN_tag;
-	u16 fabric_domain_ID;
-	u32 qos_params_oem[4];
-} __packed;
-
-struct SET_QOS_OUT {
-	u32 qos_params_rsvd;
-} __packed;
-
-union SET_QOS_PARAMS {
-	struct SET_QOS_IN request;
-	struct SET_QOS_OUT response;
-} __packed;
-
-/* QOS/Bandwidth settings per domain. Applicable only in VMs.  */
-struct FWCMD_COMMON_SET_QOS {
-	union FWCMD_HEADER header;
-	union SET_QOS_PARAMS params;
-} __packed;
-
-struct SET_FRAME_SIZE_IN {
-	u32 max_tx_frame_size;
-	u32 max_rx_frame_size;
-} __packed;
-
-struct SET_FRAME_SIZE_OUT {
-	u32 chip_max_tx_frame_size;
-	u32 chip_max_rx_frame_size;
-} __packed;
-
-union SET_FRAME_SIZE_PARAMS {
-	struct SET_FRAME_SIZE_IN request;
-	struct SET_FRAME_SIZE_OUT response;
-} __packed;
-
-/* Set frame size command. Only host domain may issue this command.  */
-struct FWCMD_COMMON_SET_FRAME_SIZE {
-	union FWCMD_HEADER header;
-	union SET_FRAME_SIZE_PARAMS params;
-} __packed;
-
-struct FORCE_FAILOVER_IN {
-	u32 move_to_port;
-	u32 failover_config;
-} __packed;
-
-struct FWCMD_COMMON_ANON_231_RESPONSE {
-	u32 rsvd0;
-} __packed;
-
-union FWCMD_COMMON_ANON_230_PARAMS {
-	struct FORCE_FAILOVER_IN request;
-	struct FWCMD_COMMON_ANON_231_RESPONSE response;
-} __packed;
-
-/*
- *  Use this command to control failover in BladeEngine. It may be used
- *  to failback to a  restored port or to forcibly move traffic from
- *  one port to another. It may also be used  to enable or disable the
- *  automatic failover feature. This command can only be issued by  domain
- *  0.
- */
-struct FWCMD_COMMON_FORCE_FAILOVER {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_230_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_ANON_240_REQUEST {
-	u64 context;
-} __packed;
-
-struct FWCMD_COMMON_ANON_241_RESPONSE {
-	u64 context;
-} __packed;
-
-union FWCMD_COMMON_ANON_239_PARAMS {
-	struct FWCMD_COMMON_ANON_240_REQUEST request;
-	struct FWCMD_COMMON_ANON_241_RESPONSE response;
-} __packed;
-
-/*
- *  This command can be used by clients as a no-operation request. Typical
- *  uses for drivers  are as a heartbeat mechanism, or deferred processing
- *  catalyst. The ARM will always  complete this command with a good completion.
- *  The 64-bit parameter is not touched by the  ARM processor.
- */
-struct FWCMD_COMMON_NOP {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_239_PARAMS params;
-} __packed;
-
-struct NTWK_RX_FILTER_SETTINGS {
-	u8 promiscuous;
-	u8 ip_cksum;
-	u8 tcp_cksum;
-	u8 udp_cksum;
-	u8 pass_err;
-	u8 pass_ckerr;
-	u8 strip_crc;
-	u8 mcast_en;
-	u8 bcast_en;
-	u8 mcast_promiscuous_en;
-	u8 unicast_en;
-	u8 vlan_promiscuous;
-} __packed;
-
-union FWCMD_COMMON_ANON_242_PARAMS {
-	struct NTWK_RX_FILTER_SETTINGS request;
-	struct NTWK_RX_FILTER_SETTINGS response;
-} __packed;
-
-/*
- *  This command is used to modify the ethernet receive filter configuration.
- *  Only domain 0  network function drivers may issue this command. The
- *  applied configuration is returned in  the response payload. Note:
- *  Some receive packet filter settings are global on  BladeEngine and
- *  can affect both the storage and network function clients that the
- *   BladeEngine hardware and firmware serve. Additionaly, depending
- *  on the revision of  BladeEngine, some ethernet receive filter settings
- *  are dependent on others. If a  dependency exists between settings
- *  for the BladeEngine revision, and the command request  settings do
- *  not meet the dependency requirement, the invalid settings will not
- *  be  applied despite the comand succeeding. For example: a driver may
- *  request to enable  broadcast packets, but not enable multicast packets.
- *  On early revisions of BladeEngine,  there may be no distinction between
- *  broadcast and multicast filters, so broadcast could  not be enabled
- *  without enabling multicast. In this scenario, the comand would still
- *   succeed, but the response payload would indicate the previously
- *  configured broadcast  and multicast setting.
- */
-struct FWCMD_COMMON_NTWK_RX_FILTER {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_242_PARAMS params;
-} __packed;
-
-
-struct FWCMD_COMMON_ANON_244_REQUEST {
-	u32 rsvd0;
-} __packed;
-
-struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD {
-	u8 firmware_version_string[32];
-	u8 fw_on_flash_version_string[32];
-} __packed;
-
-union FWCMD_COMMON_ANON_243_PARAMS {
-	struct FWCMD_COMMON_ANON_244_REQUEST request;
-	struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD response;
-} __packed;
-
-/* This comand retrieves the firmware version.  */
-struct FWCMD_COMMON_GET_FW_VERSION {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_243_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_ANON_246_REQUEST {
-	u16 tx_flow_control;
-	u16 rx_flow_control;
-} __packed;
-
-struct FWCMD_COMMON_ANON_247_RESPONSE {
-	u32 rsvd0;
-} __packed;
-
-union FWCMD_COMMON_ANON_245_PARAMS {
-	struct FWCMD_COMMON_ANON_246_REQUEST request;
-	struct FWCMD_COMMON_ANON_247_RESPONSE response;
-} __packed;
-
-/*
- *  This comand is used to program BladeEngine flow control behavior.
- *  Only the host  networking driver is allowed to use this comand.
- */
-struct FWCMD_COMMON_SET_FLOW_CONTROL {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_245_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_ANON_249_REQUEST {
-	u32 rsvd0;
-} __packed;
-
-struct FWCMD_COMMON_ANON_250_RESPONSE {
-	u16 tx_flow_control;
-	u16 rx_flow_control;
-} __packed;
-
-union FWCMD_COMMON_ANON_248_PARAMS {
-	struct FWCMD_COMMON_ANON_249_REQUEST request;
-	struct FWCMD_COMMON_ANON_250_RESPONSE response;
-} __packed;
-
-/* This comand is used to read BladeEngine flow control settings.  */
-struct FWCMD_COMMON_GET_FLOW_CONTROL {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_248_PARAMS params;
-} __packed;
-
-struct EQ_DELAY_PARAMS {
-	u32 eq_id;
-	u32 delay_in_microseconds;
-} __packed;
-
-struct FWCMD_COMMON_ANON_257_REQUEST {
-	u32 num_eq;
-	u32 rsvd0;
-	struct EQ_DELAY_PARAMS delay[16];
-} __packed;
-
-struct FWCMD_COMMON_ANON_258_RESPONSE {
-	u32 delay_resolution_in_microseconds;
-	u32 delay_max_in_microseconds;
-} __packed;
-
-union MODIFY_EQ_DELAY_PARAMS {
-	struct FWCMD_COMMON_ANON_257_REQUEST request;
-	struct FWCMD_COMMON_ANON_258_RESPONSE response;
-} __packed;
-
-/* This comand changes the EQ delay for a given set of EQs.  */
-struct FWCMD_COMMON_MODIFY_EQ_DELAY {
-	union FWCMD_HEADER header;
-	union MODIFY_EQ_DELAY_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_ANON_260_REQUEST {
-	u32 rsvd0;
-} __packed;
-
-struct BE_FIRMWARE_CONFIG {
-	u16 be_config_number;
-	u16 asic_revision;
-	u32 nic_ulp_mask;
-	u32 tulp_mask;
-	u32 iscsi_ulp_mask;
-	u32 rdma_ulp_mask;
-	u32 rsvd0[4];
-	u32 eth_tx_id_start;
-	u32 eth_tx_id_count;
-	u32 eth_rx_id_start;
-	u32 eth_rx_id_count;
-	u32 tpm_wrbq_id_start;
-	u32 tpm_wrbq_id_count;
-	u32 tpm_defq_id_start;
-	u32 tpm_defq_id_count;
-	u32 iscsi_wrbq_id_start;
-	u32 iscsi_wrbq_id_count;
-	u32 iscsi_defq_id_start;
-	u32 iscsi_defq_id_count;
-	u32 rdma_qp_id_start;
-	u32 rdma_qp_id_count;
-	u32 rsvd1[8];
-} __packed;
-
-union FWCMD_COMMON_ANON_259_PARAMS {
-	struct FWCMD_COMMON_ANON_260_REQUEST request;
-	struct BE_FIRMWARE_CONFIG response;
-} __packed;
-
-/*
- *  This comand queries the current firmware configuration parameters.
- *   The static  configuration type is defined by be_config_number. This
- *  differentiates different  BladeEngine builds, such as iSCSI Initiator
- *  versus iSCSI Target.  For a given static  configuration, the Upper
- *  Layer Protocol (ULP) processors may be reconfigured to support  different
- *  protocols. Each ULP processor supports one or more protocols. The
- *  masks  indicate which processors are configured for each protocol.
- *   For a given static  configuration, the number of TCP connections
- *  supported for each protocol may vary. The  *_id_start and *_id_count
- *  variables define a linear range of IDs that are available for  each
- *  supported protocol. The *_id_count may be used by the driver to allocate
- *  the  appropriate number of connection resources. The *_id_start may
- *  be used to map the  arbitrary range of IDs to a zero-based range
- *  of indices.
- */
-struct FWCMD_COMMON_FIRMWARE_CONFIG {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_259_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS {
-	u32 emph_lev_sel_port0;
-	u32 emph_lev_sel_port1;
-	u8 xaui_vo_sel;
-	u8 xaui_state;
-	u16 rsvd0;
-	u32 xaui_eq_vector;
-} __packed;
-
-struct FWCMD_COMMON_ANON_262_REQUEST {
-	u32 rsvd0;
-} __packed;
-
-union FWCMD_COMMON_ANON_261_PARAMS {
-	struct FWCMD_COMMON_ANON_262_REQUEST request;
-	struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS response;
-} __packed;
-
-/*
- *  This comand can be used to read XAUI equalization parameters. The
- *  ARM firmware applies  default equalization parameters during initialization.
- *  These parameters may be  customer-specific when derived from the
- *  SEEPROM. See SEEPROM_DATA for equalization  specific fields.
- */
-struct FWCMD_COMMON_GET_PORT_EQUALIZATION {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_261_PARAMS params;
-} __packed;
-
-struct FWCMD_COMMON_ANON_264_RESPONSE {
-	u32 rsvd0;
-} __packed;
-
-union FWCMD_COMMON_ANON_263_PARAMS {
-	struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS request;
-	struct FWCMD_COMMON_ANON_264_RESPONSE response;
-} __packed;
-
-/*
- *  This comand can be used to set XAUI equalization parameters. The ARM
- *  firmware applies  default equalization parameters during initialization.
- *  These parameters may be  customer-specific when derived from the
- *  SEEPROM. See SEEPROM_DATA for equalization  specific fields.
- */
-struct FWCMD_COMMON_SET_PORT_EQUALIZATION {
-	union FWCMD_HEADER header;
-	union FWCMD_COMMON_ANON_263_PARAMS params;
-} __packed;
-
-#endif /* __fwcmd_common_bmap_h__ */
diff --git a/drivers/staging/benet/fwcmd_eth_bmap.h b/drivers/staging/benet/fwcmd_eth_bmap.h
deleted file mode 100644
index 234b179..0000000
--- a/drivers/staging/benet/fwcmd_eth_bmap.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __fwcmd_eth_bmap_h__
-#define __fwcmd_eth_bmap_h__
-#include "fwcmd_hdr_bmap.h"
-#include "fwcmd_types_bmap.h"
-
-struct MIB_ETH_STATISTICS_PARAMS_IN {
-	u32 rsvd0;
-} __packed;
-
-struct BE_RXF_STATS {
-	u32 p0recvdtotalbytesLSD;	/* DWORD 0 */
-	u32 p0recvdtotalbytesMSD;	/* DWORD 1 */
-	u32 p0recvdtotalframes;	/* DWORD 2 */
-	u32 p0recvdunicastframes;	/* DWORD 3 */
-	u32 p0recvdmulticastframes;	/* DWORD 4 */
-	u32 p0recvdbroadcastframes;	/* DWORD 5 */
-	u32 p0crcerrors;	/* DWORD 6 */
-	u32 p0alignmentsymerrs;	/* DWORD 7 */
-	u32 p0pauseframesrecvd;	/* DWORD 8 */
-	u32 p0controlframesrecvd;	/* DWORD 9 */
-	u32 p0inrangelenerrors;	/* DWORD 10 */
-	u32 p0outrangeerrors;	/* DWORD 11 */
-	u32 p0frametoolongerrors;	/* DWORD 12 */
-	u32 p0droppedaddressmatch;	/* DWORD 13 */
-	u32 p0droppedvlanmismatch;	/* DWORD 14 */
-	u32 p0ipdroppedtoosmall;	/* DWORD 15 */
-	u32 p0ipdroppedtooshort;	/* DWORD 16 */
-	u32 p0ipdroppedhdrtoosmall;	/* DWORD 17 */
-	u32 p0tcpdroppedlen;	/* DWORD 18 */
-	u32 p0droppedrunt;	/* DWORD 19 */
-	u32 p0recvd64;		/* DWORD 20 */
-	u32 p0recvd65_127;	/* DWORD 21 */
-	u32 p0recvd128_256;	/* DWORD 22 */
-	u32 p0recvd256_511;	/* DWORD 23 */
-	u32 p0recvd512_1023;	/* DWORD 24 */
-	u32 p0recvd1518_1522;	/* DWORD 25 */
-	u32 p0recvd1522_2047;	/* DWORD 26 */
-	u32 p0recvd2048_4095;	/* DWORD 27 */
-	u32 p0recvd4096_8191;	/* DWORD 28 */
-	u32 p0recvd8192_9216;	/* DWORD 29 */
-	u32 p0rcvdipcksmerrs;	/* DWORD 30 */
-	u32 p0recvdtcpcksmerrs;	/* DWORD 31 */
-	u32 p0recvdudpcksmerrs;	/* DWORD 32 */
-	u32 p0recvdnonrsspackets;	/* DWORD 33 */
-	u32 p0recvdippackets;	/* DWORD 34 */
-	u32 p0recvdchute1packets;	/* DWORD 35 */
-	u32 p0recvdchute2packets;	/* DWORD 36 */
-	u32 p0recvdchute3packets;	/* DWORD 37 */
-	u32 p0recvdipsecpackets;	/* DWORD 38 */
-	u32 p0recvdmanagementpackets;	/* DWORD 39 */
-	u32 p0xmitbyteslsd;	/* DWORD 40 */
-	u32 p0xmitbytesmsd;	/* DWORD 41 */
-	u32 p0xmitunicastframes;	/* DWORD 42 */
-	u32 p0xmitmulticastframes;	/* DWORD 43 */
-	u32 p0xmitbroadcastframes;	/* DWORD 44 */
-	u32 p0xmitpauseframes;	/* DWORD 45 */
-	u32 p0xmitcontrolframes;	/* DWORD 46 */
-	u32 p0xmit64;		/* DWORD 47 */
-	u32 p0xmit65_127;	/* DWORD 48 */
-	u32 p0xmit128_256;	/* DWORD 49 */
-	u32 p0xmit256_511;	/* DWORD 50 */
-	u32 p0xmit512_1023;	/* DWORD 51 */
-	u32 p0xmit1518_1522;	/* DWORD 52 */
-	u32 p0xmit1522_2047;	/* DWORD 53 */
-	u32 p0xmit2048_4095;	/* DWORD 54 */
-	u32 p0xmit4096_8191;	/* DWORD 55 */
-	u32 p0xmit8192_9216;	/* DWORD 56 */
-	u32 p0rxfifooverflowdropped;	/* DWORD 57 */
-	u32 p0ipseclookupfaileddropped;	/* DWORD 58 */
-	u32 p1recvdtotalbytesLSD;	/* DWORD 59 */
-	u32 p1recvdtotalbytesMSD;	/* DWORD 60 */
-	u32 p1recvdtotalframes;	/* DWORD 61 */
-	u32 p1recvdunicastframes;	/* DWORD 62 */
-	u32 p1recvdmulticastframes;	/* DWORD 63 */
-	u32 p1recvdbroadcastframes;	/* DWORD 64 */
-	u32 p1crcerrors;	/* DWORD 65 */
-	u32 p1alignmentsymerrs;	/* DWORD 66 */
-	u32 p1pauseframesrecvd;	/* DWORD 67 */
-	u32 p1controlframesrecvd;	/* DWORD 68 */
-	u32 p1inrangelenerrors;	/* DWORD 69 */
-	u32 p1outrangeerrors;	/* DWORD 70 */
-	u32 p1frametoolongerrors;	/* DWORD 71 */
-	u32 p1droppedaddressmatch;	/* DWORD 72 */
-	u32 p1droppedvlanmismatch;	/* DWORD 73 */
-	u32 p1ipdroppedtoosmall;	/* DWORD 74 */
-	u32 p1ipdroppedtooshort;	/* DWORD 75 */
-	u32 p1ipdroppedhdrtoosmall;	/* DWORD 76 */
-	u32 p1tcpdroppedlen;	/* DWORD 77 */
-	u32 p1droppedrunt;	/* DWORD 78 */
-	u32 p1recvd64;		/* DWORD 79 */
-	u32 p1recvd65_127;	/* DWORD 80 */
-	u32 p1recvd128_256;	/* DWORD 81 */
-	u32 p1recvd256_511;	/* DWORD 82 */
-	u32 p1recvd512_1023;	/* DWORD 83 */
-	u32 p1recvd1518_1522;	/* DWORD 84 */
-	u32 p1recvd1522_2047;	/* DWORD 85 */
-	u32 p1recvd2048_4095;	/* DWORD 86 */
-	u32 p1recvd4096_8191;	/* DWORD 87 */
-	u32 p1recvd8192_9216;	/* DWORD 88 */
-	u32 p1rcvdipcksmerrs;	/* DWORD 89 */
-	u32 p1recvdtcpcksmerrs;	/* DWORD 90 */
-	u32 p1recvdudpcksmerrs;	/* DWORD 91 */
-	u32 p1recvdnonrsspackets;	/* DWORD 92 */
-	u32 p1recvdippackets;	/* DWORD 93 */
-	u32 p1recvdchute1packets;	/* DWORD 94 */
-	u32 p1recvdchute2packets;	/* DWORD 95 */
-	u32 p1recvdchute3packets;	/* DWORD 96 */
-	u32 p1recvdipsecpackets;	/* DWORD 97 */
-	u32 p1recvdmanagementpackets;	/* DWORD 98 */
-	u32 p1xmitbyteslsd;	/* DWORD 99 */
-	u32 p1xmitbytesmsd;	/* DWORD 100 */
-	u32 p1xmitunicastframes;	/* DWORD 101 */
-	u32 p1xmitmulticastframes;	/* DWORD 102 */
-	u32 p1xmitbroadcastframes;	/* DWORD 103 */
-	u32 p1xmitpauseframes;	/* DWORD 104 */
-	u32 p1xmitcontrolframes;	/* DWORD 105 */
-	u32 p1xmit64;		/* DWORD 106 */
-	u32 p1xmit65_127;	/* DWORD 107 */
-	u32 p1xmit128_256;	/* DWORD 108 */
-	u32 p1xmit256_511;	/* DWORD 109 */
-	u32 p1xmit512_1023;	/* DWORD 110 */
-	u32 p1xmit1518_1522;	/* DWORD 111 */
-	u32 p1xmit1522_2047;	/* DWORD 112 */
-	u32 p1xmit2048_4095;	/* DWORD 113 */
-	u32 p1xmit4096_8191;	/* DWORD 114 */
-	u32 p1xmit8192_9216;	/* DWORD 115 */
-	u32 p1rxfifooverflowdropped;	/* DWORD 116 */
-	u32 p1ipseclookupfaileddropped;	/* DWORD 117 */
-	u32 pxdroppednopbuf;	/* DWORD 118 */
-	u32 pxdroppednotxpb;	/* DWORD 119 */
-	u32 pxdroppednoipsecbuf;	/* DWORD 120 */
-	u32 pxdroppednoerxdescr;	/* DWORD 121 */
-	u32 pxdroppednotpredescr;	/* DWORD 122 */
-	u32 pxrecvdmanagementportpackets;	/* DWORD 123 */
-	u32 pxrecvdmanagementportbytes;	/* DWORD 124 */
-	u32 pxrecvdmanagementportpauseframes;	/* DWORD 125 */
-	u32 pxrecvdmanagementporterrors;	/* DWORD 126 */
-	u32 pxxmitmanagementportpackets;	/* DWORD 127 */
-	u32 pxxmitmanagementportbytes;	/* DWORD 128 */
-	u32 pxxmitmanagementportpause;	/* DWORD 129 */
-	u32 pxxmitmanagementportrxfifooverflow;	/* DWORD 130 */
-	u32 pxrecvdipsecipcksmerrs;	/* DWORD 131 */
-	u32 pxrecvdtcpsecipcksmerrs;	/* DWORD 132 */
-	u32 pxrecvdudpsecipcksmerrs;	/* DWORD 133 */
-	u32 pxipsecrunt;	/* DWORD 134 */
-	u32 pxipsecaddressmismatchdropped;	/* DWORD 135 */
-	u32 pxipsecrxfifooverflowdropped;	/* DWORD 136 */
-	u32 pxipsecframestoolong;	/* DWORD 137 */
-	u32 pxipsectotalipframes;	/* DWORD 138 */
-	u32 pxipseciptoosmall;	/* DWORD 139 */
-	u32 pxipseciptooshort;	/* DWORD 140 */
-	u32 pxipseciphdrtoosmall;	/* DWORD 141 */
-	u32 pxipsectcphdrbad;	/* DWORD 142 */
-	u32 pxrecvdipsecchute1;	/* DWORD 143 */
-	u32 pxrecvdipsecchute2;	/* DWORD 144 */
-	u32 pxrecvdipsecchute3;	/* DWORD 145 */
-	u32 pxdropped7frags;	/* DWORD 146 */
-	u32 pxdroppedfrags;	/* DWORD 147 */
-	u32 pxdroppedinvalidfragring;	/* DWORD 148 */
-	u32 pxnumforwardedpackets;	/* DWORD 149 */
-} __packed;
-
-union MIB_ETH_STATISTICS_PARAMS {
-	struct MIB_ETH_STATISTICS_PARAMS_IN request;
-	struct BE_RXF_STATS response;
-} __packed;
-
-/*
- *  Query ethernet statistics. All domains may issue this command. The
- *  host domain drivers  may optionally reset internal statistic counters
- *  with a query.
- */
-struct FWCMD_ETH_GET_STATISTICS {
-	union FWCMD_HEADER header;
-	union MIB_ETH_STATISTICS_PARAMS params;
-} __packed;
-
-
-struct FWCMD_ETH_ANON_175_REQUEST {
-	u8 port0_promiscuous;
-	u8 port1_promiscuous;
-	u16 rsvd0;
-} __packed;
-
-struct FWCMD_ETH_ANON_176_RESPONSE {
-	u32 rsvd0;
-} __packed;
-
-union FWCMD_ETH_ANON_174_PARAMS {
-	struct FWCMD_ETH_ANON_175_REQUEST request;
-	struct FWCMD_ETH_ANON_176_RESPONSE response;
-} __packed;
-
-/* Enables/Disables promiscuous ethernet receive mode.  */
-struct FWCMD_ETH_PROMISCUOUS {
-	union FWCMD_HEADER header;
-	union FWCMD_ETH_ANON_174_PARAMS params;
-} __packed;
-
-struct FWCMD_ETH_ANON_178_REQUEST {
-	u32 new_fragsize_log2;
-} __packed;
-
-struct FWCMD_ETH_ANON_179_RESPONSE {
-	u32 actual_fragsize_log2;
-} __packed;
-
-union FWCMD_ETH_ANON_177_PARAMS {
-	struct FWCMD_ETH_ANON_178_REQUEST request;
-	struct FWCMD_ETH_ANON_179_RESPONSE response;
-} __packed;
-
-/*
- *  Sets the Ethernet RX fragment size. Only host (domain 0) networking
- *  drivers may issue  this command.  This call will fail for non-host
- *  protection domains. In this situation the  MCC CQ status will indicate
- *  a failure due to insufficient priviledges. The response  should be
- *  ignored, and the driver should use the FWCMD_ETH_GET_FRAG_SIZE to
- *  query the  existing ethernet receive fragment size. It must use this
- *  fragment size for all  fragments in the ethernet receive ring.  If
- *  the command succeeds, the driver must use the  frag size indicated
- *  in the command response since the requested frag size may not be  applied
- *  until the next reboot. When the requested fragsize matches the response
- *   fragsize, this indicates the request was applied immediately.
- */
-struct FWCMD_ETH_SET_RX_FRAG_SIZE {
-	union FWCMD_HEADER header;
-	union FWCMD_ETH_ANON_177_PARAMS params;
-} __packed;
-
-struct FWCMD_ETH_ANON_181_REQUEST {
-	u32 rsvd0;
-} __packed;
-
-struct FWCMD_ETH_ANON_182_RESPONSE {
-	u32 actual_fragsize_log2;
-} __packed;
-
-union FWCMD_ETH_ANON_180_PARAMS {
-	struct FWCMD_ETH_ANON_181_REQUEST request;
-	struct FWCMD_ETH_ANON_182_RESPONSE response;
-} __packed;
-
-/*
- *  Queries the Ethernet RX fragment size. All domains may issue this
- *  command.  The driver  should call this command to determine the minimum
- *  required fragment size for the ethernet  RX ring buffers. Drivers
- *  may choose to use a larger size for each fragment buffer, but  BladeEngine
- *  will use up to the configured minimum required fragsize in each ethernet
- *   receive fragment buffer. For example, if the ethernet receive fragment
- *  size is  configured to 4kB, and a driver uses 8kB fragments, a 6kB
- *  ethernet packet received by  BladeEngine will be split accross two
- *  of the driver's receive framgents (4kB in one  fragment buffer, and
- *  2kB in the subsequent fragment buffer).
- */
-struct FWCMD_ETH_GET_RX_FRAG_SIZE {
-	union FWCMD_HEADER header;
-	union FWCMD_ETH_ANON_180_PARAMS params;
-} __packed;
-
-#endif /* __fwcmd_eth_bmap_h__ */
diff --git a/drivers/staging/benet/fwcmd_hdr_bmap.h b/drivers/staging/benet/fwcmd_hdr_bmap.h
deleted file mode 100644
index 28b4532..0000000
--- a/drivers/staging/benet/fwcmd_hdr_bmap.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __fwcmd_hdr_bmap_h__
-#define __fwcmd_hdr_bmap_h__
-
-struct FWCMD_REQUEST_HEADER {
-	u8 opcode;
-	u8 subsystem;
-	u8 port_number;
-	u8 domain;
-	u32 timeout;
-	u32 request_length;
-	u32 rsvd0;
-} __packed;
-
-struct FWCMD_RESPONSE_HEADER {
-	u8 opcode;
-	u8 subsystem;
-	u8 rsvd0;
-	u8 domain;
-	u8 status;
-	u8 additional_status;
-	u16 rsvd1;
-	u32 response_length;
-	u32 actual_response_length;
-} __packed;
-
-/*
- *  The firmware/driver overwrites the input FWCMD_REQUEST_HEADER with
- *  the output  FWCMD_RESPONSE_HEADER.
- */
-union FWCMD_HEADER {
-	struct FWCMD_REQUEST_HEADER request;
-	struct FWCMD_RESPONSE_HEADER response;
-} __packed;
-
-#endif /* __fwcmd_hdr_bmap_h__ */
diff --git a/drivers/staging/benet/fwcmd_mcc.h b/drivers/staging/benet/fwcmd_mcc.h
deleted file mode 100644
index 9eeca87..0000000
--- a/drivers/staging/benet/fwcmd_mcc.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __fwcmd_mcc_amap_h__
-#define __fwcmd_mcc_amap_h__
-#include "fwcmd_opcodes.h"
-/*
- * Where applicable, a WRB, may contain a list of Scatter-gather elements.
- * Each element supports a 64 bit address and a 32bit length field.
- */
-struct BE_MCC_SGE_AMAP {
-	u8 pa_lo[32];	/* DWORD 0 */
-	u8 pa_hi[32];	/* DWORD 1 */
-	u8 length[32];	/* DWORD 2 */
-} __packed;
-struct MCC_SGE_AMAP {
-	u32 dw[3];
-};
-/*
- * The design of an MCC_SGE allows up to 19 elements to be embedded
- * in a WRB, supporting 64KB data transfers (assuming a 4KB page size).
- */
-struct BE_MCC_WRB_PAYLOAD_AMAP {
-	union {
-		struct BE_MCC_SGE_AMAP sgl[19];
-		u8 embedded[59][32];	/* DWORD 0 */
-	};
-} __packed;
-struct MCC_WRB_PAYLOAD_AMAP {
-	u32 dw[59];
-};
-
-/*
- * This is the structure of the MCC Command WRB for commands
- * sent to the Management Processing Unit (MPU). See section
- * for usage in embedded and non-embedded modes.
- */
-struct BE_MCC_WRB_AMAP {
-	u8 embedded;	/* DWORD 0 */
-	u8 rsvd0[2];	/* DWORD 0 */
-	u8 sge_count[5];	/* DWORD 0 */
-	u8 rsvd1[16];	/* DWORD 0 */
-	u8 special[8];	/* DWORD 0 */
-	u8 payload_length[32];	/* DWORD 1 */
-	u8 tag[2][32];	/* DWORD 2 */
-	u8 rsvd2[32];	/* DWORD 4 */
-	struct BE_MCC_WRB_PAYLOAD_AMAP payload;
-} __packed;
-struct MCC_WRB_AMAP {
-	u32 dw[64];
-};
-
-/*  This is the structure of the MCC Completion queue entry  */
-struct BE_MCC_CQ_ENTRY_AMAP {
-	u8 completion_status[16];	/* DWORD 0 */
-	u8 extended_status[16];	/* DWORD 0 */
-	u8 mcc_tag[2][32];	/* DWORD 1 */
-	u8 rsvd0[27];	/* DWORD 3 */
-	u8 consumed;	/* DWORD 3 */
-	u8 completed;	/* DWORD 3 */
-	u8 hpi_buffer_completion;	/* DWORD 3 */
-	u8 async_event;	/* DWORD 3 */
-	u8 valid;		/* DWORD 3 */
-} __packed;
-struct MCC_CQ_ENTRY_AMAP {
-	u32 dw[4];
-};
-
-/* Mailbox structures used by the MPU during bootstrap */
-struct BE_MCC_MAILBOX_AMAP {
-	struct BE_MCC_WRB_AMAP wrb;
-	struct BE_MCC_CQ_ENTRY_AMAP cq;
-} __packed;
-struct MCC_MAILBOX_AMAP {
-	u32 dw[68];
-};
-
-#endif /* __fwcmd_mcc_amap_h__ */
diff --git a/drivers/staging/benet/fwcmd_opcodes.h b/drivers/staging/benet/fwcmd_opcodes.h
deleted file mode 100644
index 23d5693..0000000
--- a/drivers/staging/benet/fwcmd_opcodes.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __fwcmd_opcodes_amap_h__
-#define __fwcmd_opcodes_amap_h__
-
-/*
- * --- FWCMD_SUBSYSTEMS ---
- * The commands are grouped into the following subsystems. The subsystem
- * code along with the opcode uniquely identify a particular fwcmd.
- */
-#define FWCMD_SUBSYSTEM_RSVD  (0)	/* This subsystem is reserved. It is */
-						  /* never used. */
-#define FWCMD_SUBSYSTEM_COMMON (1)	/* CMDs in this group are common to
-					* all subsystems. See
-					* COMMON_SUBSYSTEM_OPCODES for opcodes
-					* and Common Host Configuration CMDs
-					* for the FWCMD descriptions.
-					*/
-#define FWCMD_SUBSYSTEM_COMMON_ISCSI    (2) /* CMDs in this group are */
-					/*
-					* common to Initiator and Target. See
-					* COMMON_ISCSI_SUBSYSTEM_OPCODES and
-					* Common iSCSI Initiator and Target
-					* CMDs for the command descriptions.
-					*/
-#define FWCMD_SUBSYSTEM_ETH             (3)	/* This subsystem is used to
-						execute  Ethernet commands.  */
-
-#define FWCMD_SUBSYSTEM_TPM             (4)	/* This subsystem is used
-						 to execute TPM  commands.  */
-#define FWCMD_SUBSYSTEM_PXE_UNDI        (5)	/* This subsystem is used
-						* to execute PXE
-						* and UNDI specific commands.
-						*/
-
-#define FWCMD_SUBSYSTEM_ISCSI_INI       (6)	/* This subsystem is used to
-						execute ISCSI Initiator
-						specific commands.
-						*/
-#define FWCMD_SUBSYSTEM_ISCSI_TGT       (7)	/* This subsystem is used
-						to execute iSCSI Target
-						specific commands.between
-						PTL and ARM firmware.
-						*/
-#define FWCMD_SUBSYSTEM_MILI_PTL        (8)	/* This subsystem is used to
-						execute iSCSI Target specific
-						commands.between MILI
-						and PTL.  */
-#define FWCMD_SUBSYSTEM_MILI_TMD        (9)	/* This subsystem is used to
-						execute iSCSI Target specific
-						commands between MILI
-						and TMD.  */
-#define FWCMD_SUBSYSTEM_PROXY           (11)	/* This subsystem is used
-						to execute proxied commands
-						within the host at the
-						explicit request of a
-						non priviledged domain.
-						This 'subsystem' is entirely
-						virtual from the controller
-						and firmware perspective as
-						it is implemented in host
-						drivers.
-						*/
-
-/*
- * --- COMMON_SUBSYSTEM_OPCODES ---
- * These opcodes are common to both networking and storage PCI
- * functions. They are used to reserve resources and configure
- * BladeEngine. These opcodes all use the FWCMD_SUBSYSTEM_COMMON
- * subsystem code.
- */
-#define OPCODE_COMMON_NTWK_MAC_QUERY    (1)
-#define SUBSYSTEM_COMMON_NTWK_MAC_QUERY (1)
-#define SUBSYSTEM_COMMON_NTWK_MAC_SET   (1)
-#define SUBSYSTEM_COMMON_NTWK_MULTICAST_SET (1)
-#define SUBSYSTEM_COMMON_NTWK_VLAN_CONFIG (1)
-#define SUBSYSTEM_COMMON_NTWK_LINK_STATUS_QUERY (1)
-#define SUBSYSTEM_COMMON_READ_FLASHROM  (1)
-#define SUBSYSTEM_COMMON_WRITE_FLASHROM (1)
-#define SUBSYSTEM_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (1)
-#define SUBSYSTEM_COMMON_ADD_PAGE_TABLES (1)
-#define SUBSYSTEM_COMMON_REMOVE_PAGE_TABLES (1)
-#define SUBSYSTEM_COMMON_RING_DESTROY   (1)
-#define SUBSYSTEM_COMMON_CQ_CREATE      (1)
-#define SUBSYSTEM_COMMON_EQ_CREATE      (1)
-#define SUBSYSTEM_COMMON_ETH_RX_CREATE  (1)
-#define SUBSYSTEM_COMMON_ETH_TX_CREATE  (1)
-#define SUBSYSTEM_COMMON_ISCSI_DEFQ_CREATE (1)
-#define SUBSYSTEM_COMMON_ISCSI_WRBQ_CREATE (1)
-#define SUBSYSTEM_COMMON_MCC_CREATE     (1)
-#define SUBSYSTEM_COMMON_JELL_CONFIG    (1)
-#define SUBSYSTEM_COMMON_FORCE_FAILOVER (1)
-#define SUBSYSTEM_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (1)
-#define SUBSYSTEM_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (1)
-#define SUBSYSTEM_COMMON_POST_ZERO_BUFFER (1)
-#define SUBSYSTEM_COMMON_GET_QOS        (1)
-#define SUBSYSTEM_COMMON_SET_QOS        (1)
-#define SUBSYSTEM_COMMON_TCP_GET_STATISTICS (1)
-#define SUBSYSTEM_COMMON_SEEPROM_READ   (1)
-#define SUBSYSTEM_COMMON_TCP_STATE_QUERY (1)
-#define SUBSYSTEM_COMMON_GET_CNTL_ATTRIBUTES (1)
-#define SUBSYSTEM_COMMON_NOP            (1)
-#define SUBSYSTEM_COMMON_NTWK_RX_FILTER (1)
-#define SUBSYSTEM_COMMON_GET_FW_VERSION (1)
-#define SUBSYSTEM_COMMON_SET_FLOW_CONTROL (1)
-#define SUBSYSTEM_COMMON_GET_FLOW_CONTROL (1)
-#define SUBSYSTEM_COMMON_SET_TCP_PARAMETERS (1)
-#define SUBSYSTEM_COMMON_SET_FRAME_SIZE (1)
-#define SUBSYSTEM_COMMON_GET_FAT        (1)
-#define SUBSYSTEM_COMMON_MODIFY_EQ_DELAY (1)
-#define SUBSYSTEM_COMMON_FIRMWARE_CONFIG (1)
-#define SUBSYSTEM_COMMON_ENABLE_DISABLE_DOMAINS (1)
-#define SUBSYSTEM_COMMON_GET_DOMAIN_CONFIG (1)
-#define SUBSYSTEM_COMMON_SET_VLD_CONFIG (1)
-#define SUBSYSTEM_COMMON_GET_VLD_CONFIG (1)
-#define SUBSYSTEM_COMMON_GET_PORT_EQUALIZATION (1)
-#define SUBSYSTEM_COMMON_SET_PORT_EQUALIZATION (1)
-#define SUBSYSTEM_COMMON_RED_CONFIG     (1)
-#define OPCODE_COMMON_NTWK_MAC_SET      (2)
-#define OPCODE_COMMON_NTWK_MULTICAST_SET (3)
-#define OPCODE_COMMON_NTWK_VLAN_CONFIG  (4)
-#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY (5)
-#define OPCODE_COMMON_READ_FLASHROM     (6)
-#define OPCODE_COMMON_WRITE_FLASHROM    (7)
-#define OPCODE_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (8)
-#define OPCODE_COMMON_ADD_PAGE_TABLES   (9)
-#define OPCODE_COMMON_REMOVE_PAGE_TABLES (10)
-#define OPCODE_COMMON_RING_DESTROY      (11)
-#define OPCODE_COMMON_CQ_CREATE         (12)
-#define OPCODE_COMMON_EQ_CREATE         (13)
-#define OPCODE_COMMON_ETH_RX_CREATE     (14)
-#define OPCODE_COMMON_ETH_TX_CREATE     (15)
-#define OPCODE_COMMON_NET_RESERVED0     (16)	/* Reserved */
-#define OPCODE_COMMON_NET_RESERVED1     (17)	/* Reserved */
-#define OPCODE_COMMON_NET_RESERVED2     (18)	/* Reserved */
-#define OPCODE_COMMON_ISCSI_DEFQ_CREATE (19)
-#define OPCODE_COMMON_ISCSI_WRBQ_CREATE (20)
-#define OPCODE_COMMON_MCC_CREATE        (21)
-#define OPCODE_COMMON_JELL_CONFIG       (22)
-#define OPCODE_COMMON_FORCE_FAILOVER    (23)
-#define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (24)
-#define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (25)
-#define OPCODE_COMMON_POST_ZERO_BUFFER  (26)
-#define OPCODE_COMMON_GET_QOS           (27)
-#define OPCODE_COMMON_SET_QOS           (28)
-#define OPCODE_COMMON_TCP_GET_STATISTICS (29)
-#define OPCODE_COMMON_SEEPROM_READ      (30)
-#define OPCODE_COMMON_TCP_STATE_QUERY   (31)
-#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES (32)
-#define OPCODE_COMMON_NOP               (33)
-#define OPCODE_COMMON_NTWK_RX_FILTER    (34)
-#define OPCODE_COMMON_GET_FW_VERSION    (35)
-#define OPCODE_COMMON_SET_FLOW_CONTROL  (36)
-#define OPCODE_COMMON_GET_FLOW_CONTROL  (37)
-#define OPCODE_COMMON_SET_TCP_PARAMETERS (38)
-#define OPCODE_COMMON_SET_FRAME_SIZE    (39)
-#define OPCODE_COMMON_GET_FAT           (40)
-#define OPCODE_COMMON_MODIFY_EQ_DELAY   (41)
-#define OPCODE_COMMON_FIRMWARE_CONFIG   (42)
-#define OPCODE_COMMON_ENABLE_DISABLE_DOMAINS (43)
-#define OPCODE_COMMON_GET_DOMAIN_CONFIG (44)
-#define OPCODE_COMMON_SET_VLD_CONFIG    (45)
-#define OPCODE_COMMON_GET_VLD_CONFIG    (46)
-#define OPCODE_COMMON_GET_PORT_EQUALIZATION (47)
-#define OPCODE_COMMON_SET_PORT_EQUALIZATION (48)
-#define OPCODE_COMMON_RED_CONFIG        (49)
-
-
-
-/*
- * --- ETH_SUBSYSTEM_OPCODES ---
- * These opcodes are used for configuring the Ethernet interfaces. These
- * opcodes all use the FWCMD_SUBSYSTEM_ETH subsystem code.
- */
-#define OPCODE_ETH_RSS_CONFIG           (1)
-#define OPCODE_ETH_ACPI_CONFIG          (2)
-#define SUBSYSTEM_ETH_RSS_CONFIG        (3)
-#define SUBSYSTEM_ETH_ACPI_CONFIG       (3)
-#define OPCODE_ETH_PROMISCUOUS          (3)
-#define SUBSYSTEM_ETH_PROMISCUOUS       (3)
-#define SUBSYSTEM_ETH_GET_STATISTICS    (3)
-#define SUBSYSTEM_ETH_GET_RX_FRAG_SIZE  (3)
-#define SUBSYSTEM_ETH_SET_RX_FRAG_SIZE  (3)
-#define OPCODE_ETH_GET_STATISTICS       (4)
-#define OPCODE_ETH_GET_RX_FRAG_SIZE     (5)
-#define OPCODE_ETH_SET_RX_FRAG_SIZE     (6)
-
-
-
-
-
-/*
- * --- MCC_STATUS_CODE ---
- * These are the global status codes used by all subsystems
- */
-#define MCC_STATUS_SUCCESS              (0)	/* Indicates a successful
-						completion of  the command */
-#define MCC_STATUS_INSUFFICIENT_PRIVILEGES (1)	/* The client does not have
-						sufficient privileges to
-						execute the command */
-#define MCC_STATUS_INVALID_PARAMETER    (2)	/* A parameter in the command
-						was invalid. The extended
-						status contains the index
-						of the parameter */
-#define MCC_STATUS_INSUFFICIENT_RESOURCES (3)	/* There are insufficient
-						chip resources to execute
-						the command */
-#define MCC_STATUS_QUEUE_FLUSHING       (4)	/* The command is completing
-						because the queue was
-						getting flushed */
-#define MCC_STATUS_DMA_FAILED           (5)	/* The command is completing
-						with a DMA error */
-
-/*
- * --- MGMT_ERROR_CODES ---
- * Error Codes returned in the status field of the FWCMD response header
- */
-#define MGMT_STATUS_SUCCESS             (0)	/* The FWCMD completed
-						without errors */
-#define MGMT_STATUS_FAILED              (1)	/* Error status in the Status
-						field of  the
-						struct FWCMD_RESPONSE_HEADER */
-#define MGMT_STATUS_ILLEGAL_REQUEST     (2)	/* Invalid FWCMD opcode */
-#define MGMT_STATUS_ILLEGAL_FIELD       (3)	/* Invalid parameter in
-						the FWCMD  payload */
-
-#endif /* __fwcmd_opcodes_amap_h__ */
diff --git a/drivers/staging/benet/fwcmd_types_bmap.h b/drivers/staging/benet/fwcmd_types_bmap.h
deleted file mode 100644
index 92217af..0000000
--- a/drivers/staging/benet/fwcmd_types_bmap.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __fwcmd_types_bmap_h__
-#define __fwcmd_types_bmap_h__
-
-/* MAC address format  */
-struct MAC_ADDRESS_FORMAT {
-	u16 SizeOfStructure;
-	u8 MACAddress[6];
-} __packed;
-
-#endif /* __fwcmd_types_bmap_h__ */
diff --git a/drivers/staging/benet/host_struct.h b/drivers/staging/benet/host_struct.h
deleted file mode 100644
index 3de6722..0000000
--- a/drivers/staging/benet/host_struct.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __host_struct_amap_h__
-#define __host_struct_amap_h__
-#include "be_cm.h"
-#include "be_common.h"
-#include "descriptors.h"
-
-/* --- EQ_COMPLETION_MAJOR_CODE_ENUM --- */
-#define EQ_MAJOR_CODE_COMPLETION        (0)	/* Completion event on a */
-						  /* qcompletion ueue. */
-#define EQ_MAJOR_CODE_ETH               (1)	/* Affiliated Ethernet Event. */
-#define EQ_MAJOR_CODE_RESERVED          (2)	/* Reserved */
-#define EQ_MAJOR_CODE_RDMA              (3)	/* Affiliated RDMA Event. */
-#define EQ_MAJOR_CODE_ISCSI             (4)	/* Affiliated ISCSI Event */
-#define EQ_MAJOR_CODE_UNAFFILIATED      (5)	/* Unaffiliated Event */
-
-/* --- EQ_COMPLETION_MINOR_CODE_ENUM --- */
-#define EQ_MINOR_CODE_COMPLETION        (0)	/* Completion event on a */
-						  /* completion queue. */
-#define EQ_MINOR_CODE_OTHER             (1)	/* Other Event (TBD). */
-
-/* Queue Entry Definition for all 4 byte event queue types. */
-struct BE_EQ_ENTRY_AMAP {
-	u8 Valid;		/* DWORD 0 */
-	u8 MajorCode[3];	/* DWORD 0 */
-	u8 MinorCode[12];	/* DWORD 0 */
-	u8 ResourceID[16];	/* DWORD 0 */
-} __packed;
-struct EQ_ENTRY_AMAP {
-	u32 dw[1];
-};
-
-/*
- * --- ETH_EVENT_CODE ---
- * These codes are returned by the MPU when one of these events has occurred,
- * and the event is configured to report to an Event Queue when an event
- * is detected.
- */
-#define ETH_EQ_LINK_STATUS              (0)	/* Link status change event */
-						  /* detected. */
-#define ETH_EQ_WATERMARK                (1)	/* watermark event detected. */
-#define ETH_EQ_MAGIC_PKT                (2)	/* magic pkt event detected. */
-#define ETH_EQ_ACPI_PKT0                (3)	/* ACPI interesting packet */
-						  /* detected. */
-#define ETH_EQ_ACPI_PKT1                (3)	/* ACPI interesting packet */
-						  /* detected. */
-#define ETH_EQ_ACPI_PKT2                (3)	/* ACPI interesting packet */
-						  /* detected. */
-#define ETH_EQ_ACPI_PKT3                (3)	/* ACPI interesting packet */
-						  /* detected. */
-
-/*
- * --- ETH_TX_COMPL_STATUS_ENUM ---
- * Status codes contained in Ethernet TX completion descriptors.
- */
-#define ETH_COMP_VALID                  (0)
-#define ETH_COMP_ERROR                  (1)
-#define ETH_COMP_INVALID                (15)
-
-/*
- * --- ETH_TX_COMPL_PORT_ENUM ---
- * Port indicator contained in Ethernet TX completion descriptors.
- */
-#define ETH_COMP_PORT0                  (0)
-#define ETH_COMP_PORT1                  (1)
-#define ETH_COMP_MGMT                   (2)
-
-/*
- * --- ETH_TX_COMPL_CT_ENUM ---
- * Completion type indicator contained in Ethernet TX completion descriptors.
- */
-#define ETH_COMP_ETH                    (0)
-
-/*
- * Work request block that the driver issues to the chip for
- * Ethernet transmissions. All control fields must be valid in each WRB for
- * a message. The controller, as specified by the flags, optionally writes
- * an entry to the Completion Ring and generate an event.
- */
-struct BE_ETH_WRB_AMAP {
-	u8 frag_pa_hi[32];	/* DWORD 0 */
-	u8 frag_pa_lo[32];	/* DWORD 1 */
-	u8 complete;	/* DWORD 2 */
-	u8 event;		/* DWORD 2 */
-	u8 crc;		/* DWORD 2 */
-	u8 forward;		/* DWORD 2 */
-	u8 ipsec;		/* DWORD 2 */
-	u8 mgmt;		/* DWORD 2 */
-	u8 ipcs;		/* DWORD 2 */
-	u8 udpcs;		/* DWORD 2 */
-	u8 tcpcs;		/* DWORD 2 */
-	u8 lso;		/* DWORD 2 */
-	u8 last;		/* DWORD 2 */
-	u8 vlan;		/* DWORD 2 */
-	u8 dbg[3];		/* DWORD 2 */
-	u8 hash_val[3];	/* DWORD 2 */
-	u8 lso_mss[14];	/* DWORD 2 */
-	u8 frag_len[16];	/* DWORD 3 */
-	u8 vlan_tag[16];	/* DWORD 3 */
-} __packed;
-struct ETH_WRB_AMAP {
-	u32 dw[4];
-};
-
-/* This is an Ethernet transmit completion descriptor */
-struct BE_ETH_TX_COMPL_AMAP {
-	u8 user_bytes[16];	/* DWORD 0 */
-	u8 nwh_bytes[8];	/* DWORD 0 */
-	u8 lso;		/* DWORD 0 */
-	u8 rsvd0[7];	/* DWORD 0 */
-	u8 wrb_index[16];	/* DWORD 1 */
-	u8 ct[2];		/* DWORD 1 */
-	u8 port[2];		/* DWORD 1 */
-	u8 rsvd1[8];	/* DWORD 1 */
-	u8 status[4];	/* DWORD 1 */
-	u8 rsvd2[16];	/* DWORD 2 */
-	u8 ringid[11];	/* DWORD 2 */
-	u8 hash_val[4];	/* DWORD 2 */
-	u8 valid;		/* DWORD 2 */
-	u8 rsvd3[32];	/* DWORD 3 */
-} __packed;
-struct ETH_TX_COMPL_AMAP {
-	u32 dw[4];
-};
-
-/* Ethernet Receive Buffer descriptor */
-struct BE_ETH_RX_D_AMAP {
-	u8 fragpa_hi[32];	/* DWORD 0 */
-	u8 fragpa_lo[32];	/* DWORD 1 */
-} __packed;
-struct ETH_RX_D_AMAP {
-	u32 dw[2];
-};
-
-/* This is an Ethernet Receive Completion Descriptor */
-struct BE_ETH_RX_COMPL_AMAP {
-	u8 vlan_tag[16];	/* DWORD 0 */
-	u8 pktsize[14];	/* DWORD 0 */
-	u8 port;		/* DWORD 0 */
-	u8 rsvd0;		/* DWORD 0 */
-	u8 err;		/* DWORD 1 */
-	u8 rsshp;		/* DWORD 1 */
-	u8 ipf;		/* DWORD 1 */
-	u8 tcpf;		/* DWORD 1 */
-	u8 udpf;		/* DWORD 1 */
-	u8 ipcksm;		/* DWORD 1 */
-	u8 tcpcksm;		/* DWORD 1 */
-	u8 udpcksm;		/* DWORD 1 */
-	u8 macdst[6];	/* DWORD 1 */
-	u8 vtp;		/* DWORD 1 */
-	u8 vtm;		/* DWORD 1 */
-	u8 fragndx[10];	/* DWORD 1 */
-	u8 ct[2];		/* DWORD 1 */
-	u8 ipsec;		/* DWORD 1 */
-	u8 numfrags[3];	/* DWORD 1 */
-	u8 rsvd1[31];	/* DWORD 2 */
-	u8 valid;		/* DWORD 2 */
-	u8 rsshash[32];	/* DWORD 3 */
-} __packed;
-struct ETH_RX_COMPL_AMAP {
-	u32 dw[4];
-};
-
-#endif /* __host_struct_amap_h__ */
diff --git a/drivers/staging/benet/hwlib.h b/drivers/staging/benet/hwlib.h
deleted file mode 100644
index afedf4d..0000000
--- a/drivers/staging/benet/hwlib.h
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#ifndef __hwlib_h__
-#define __hwlib_h__
-
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-#include "regmap.h"		/* srcgen array map output */
-
-#include "asyncmesg.h"
-#include "fwcmd_opcodes.h"
-#include "post_codes.h"
-#include "fwcmd_mcc.h"
-
-#include "fwcmd_types_bmap.h"
-#include "fwcmd_common_bmap.h"
-#include "fwcmd_eth_bmap.h"
-#include "bestatus.h"
-/*
- *
- * Macros for reading/writing a protection domain or CSR registers
- * in BladeEngine.
- */
-#define PD_READ(fo, field)	ioread32((fo)->db_va + \
-		offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8)
-
-#define PD_WRITE(fo, field, val) iowrite32(val, (fo)->db_va + \
-		offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8)
-
-#define CSR_READ(fo, field)	ioread32((fo)->csr_va + \
-		offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8)
-
-#define CSR_WRITE(fo, field, val)	iowrite32(val, (fo)->csr_va + \
-		offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8)
-
-#define PCICFG0_READ(fo, field)	ioread32((fo)->pci_va + \
-		offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8)
-
-#define PCICFG0_WRITE(fo, field, val)	iowrite32(val, (fo)->pci_va + \
-		offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8)
-
-#define PCICFG1_READ(fo, field)	ioread32((fo)->pci_va + \
-		offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8)
-
-#define PCICFG1_WRITE(fo, field, val)	iowrite32(val, (fo)->pci_va + \
-		offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8)
-
-#ifdef BE_DEBUG
-#define ASSERT(c)       BUG_ON(!(c));
-#else
-#define ASSERT(c)
-#endif
-
-/* debug levels */
-enum BE_DEBUG_LEVELS {
-	DL_ALWAYS = 0,		/* cannot be masked */
-	DL_ERR = 0x1,		/* errors that should never happen */
-	DL_WARN = 0x2,		/* something questionable.
-				   recoverable errors */
-	DL_NOTE = 0x4,		/* infrequent, important debug info */
-	DL_INFO = 0x8,		/* debug information */
-	DL_VERBOSE = 0x10,	/* detailed info, such as buffer traces */
-	BE_DL_MIN_VALUE = 0x1,	/* this is the min value used */
-	BE_DL_MAX_VALUE = 0x80	/* this is the higheset value used */
-} ;
-
-extern unsigned int trace_level;
-
-#define TRACE(lm, fmt, args...)  {				\
-		if (trace_level & lm) {				\
-			printk(KERN_NOTICE "BE: %s:%d \n" fmt,	\
-			__FILE__ , __LINE__ , ## args);		\
-		}						\
-	}
-
-static inline unsigned int be_trace_set_level(unsigned int level)
-{
-	unsigned int old_level = trace_level;
-	trace_level = level;
-	return old_level;
-}
-
-#define be_trace_get_level() 	trace_level
-/*
- * Returns number of pages spanned by the size of data
- * starting at the given address.
- */
-#define PAGES_SPANNED(_address, _size) \
-   ((u32)((((size_t)(_address) & (PAGE_SIZE - 1)) + \
-		(_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
-/* Byte offset into the page corresponding to given address */
-#define OFFSET_IN_PAGE(_addr_) ((size_t)(_addr_) & (PAGE_SIZE-1))
-
-/*
- * circular subtract.
- * Returns a - b assuming a circular number system, where a and b are
- * in range (0, maxValue-1). If a==b, zero is returned so the
- * highest value possible with this subtraction is maxValue-1.
- */
-static inline u32 be_subc(u32 a, u32 b, u32 max)
-{
-	ASSERT(a <= max && b <= max);
-	ASSERT(max > 0);
-	return a >= b ? (a - b) : (max - b + a);
-}
-
-static inline u32 be_addc(u32 a, u32 b, u32 max)
-{
-	ASSERT(a < max);
-	ASSERT(max > 0);
-	return (max - a > b) ? (a + b) : (b + a - max);
-}
-
-/* descriptor for a physically contiguous memory used for ring */
-struct ring_desc {
-	u32 length;	/* length in bytes */
-	void *va; 	/* virtual address */
-	u64 pa;		/* bus address */
-} ;
-
-/*
- * This structure stores information about a ring shared between hardware
- * and software.  Each ring is allocated by the driver in the uncached
- * extension and mapped into BladeEngine's unified table.
- */
-struct mp_ring {
-	u32 pages;		/* queue size in pages */
-	u32 id;			/* queue id assigned by beklib */
-	u32 num;		/* number of elements in queue */
-	u32 cidx;		/* consumer index */
-	u32 pidx;		/* producer index -- not used by most rings */
-	u32 itemSize;		/* size in bytes of one object */
-
-	void *va;		/* The virtual address of the ring.
-				   This should be last to allow 32 & 64
-				   bit debugger extensions to work. */
-} ;
-
-/*-----------  amap bit filed get / set macros and functions -----*/
-/*
- * Structures defined in the map header files (under fw/amap/) with names
- * in the format BE_<name>_AMAP are pseudo structures with members
- * of type u8. These structures are templates that are used in
- * conjuntion with the structures with names in the format
- * <name>_AMAP to calculate the bit masks and bit offsets to get or set
- * bit fields in structures. The structures <name>_AMAP are arrays
- * of 32 bits words and have the correct size.  The following macros
- * provide convenient ways to get and set the various members
- * in the structures without using strucctures with bit fields.
- * Always use the macros AMAP_GET_BITS_PTR and AMAP_SET_BITS_PTR
- * macros to extract and set various members.
- */
-
-/*
- * Returns the a bit mask for the register that is NOT shifted into location.
- * That means return values always look like: 0x1, 0xFF, 0x7FF, etc...
- */
-static inline u32 amap_mask(u32 bit_size)
-{
-	return bit_size == 32 ? 0xFFFFFFFF : (1 << bit_size) - 1;
-}
-
-#define AMAP_BIT_MASK(_struct_, field)       \
-	amap_mask(AMAP_BIT_SIZE(_struct_, field))
-
-/*
- * non-optimized set bits function. First clears the bits and then assigns them.
- * This does not require knowledge of the particular DWORD you are setting.
- * e.g. AMAP_SET_BITS_PTR (struct, field1, &contextMemory, 123);
- */
-static inline void
-amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value)
-{
-	u32 *dw = (u32 *)ptr;
-	*(dw + dw_offset) &= ~(mask << offset);
-	*(dw + dw_offset) |= (mask & value) << offset;
-}
-
-#define AMAP_SET_BITS_PTR(_struct_, field, _structPtr_, val)	\
-	amap_set(_structPtr_, AMAP_WORD_OFFSET(_struct_, field),\
-		AMAP_BIT_MASK(_struct_, field),			\
-		AMAP_BIT_OFFSET(_struct_, field), val)
-/*
- * Non-optimized routine that gets the bits without knowing the correct DWORD.
- * e.g. fieldValue = AMAP_GET_BITS_PTR (struct, field1, &contextMemory);
- */
-static inline u32
-amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset)
-{
-	u32 *dw = (u32 *)ptr;
-	return mask & (*(dw + dw_offset) >> offset);
-}
-#define AMAP_GET_BITS_PTR(_struct_, field, _structPtr_)			\
-	amap_get(_structPtr_, AMAP_WORD_OFFSET(_struct_, field),	\
-		AMAP_BIT_MASK(_struct_, field),				\
-		AMAP_BIT_OFFSET(_struct_, field))
-
-/* Returns 0-31 representing bit offset within a DWORD of a bitfield. */
-#define AMAP_BIT_OFFSET(_struct_, field)                  \
-	(offsetof(struct BE_ ## _struct_ ## _AMAP, field) % 32)
-
-/* Returns 0-n representing DWORD offset of bitfield within the structure. */
-#define AMAP_WORD_OFFSET(_struct_, field)  \
-		  (offsetof(struct BE_ ## _struct_ ## _AMAP, field)/32)
-
-/* Returns size of bitfield in bits. */
-#define AMAP_BIT_SIZE(_struct_, field) \
-		sizeof(((struct BE_ ## _struct_ ## _AMAP*)0)->field)
-
-struct be_mcc_wrb_response_copy {
-	u16 length;		/* bytes in response */
-	u16 fwcmd_offset;	/* offset within the wrb of the response */
-	void *va;		/* user's va to copy response into */
-
-} ;
-typedef void (*mcc_wrb_cqe_callback) (void *context, int status,
-				struct MCC_WRB_AMAP *optional_wrb);
-struct be_mcc_wrb_context {
-
-	mcc_wrb_cqe_callback internal_cb;	/* Function to call on
-						completion */
-	void *internal_cb_context;	/* Parameter to pass
-						   to completion function */
-
-	mcc_wrb_cqe_callback cb;	/* Function to call on completion */
-	void *cb_context;	/* Parameter to pass to completion function */
-
-	int *users_final_status;	/* pointer to a local
-						variable for synchronous
-						commands */
-	struct MCC_WRB_AMAP *wrb;	/* pointer to original wrb for embedded
-						commands only */
-	struct list_head next;	/* links context structs together in
-				   free list */
-
-	struct be_mcc_wrb_response_copy copy;	/* Optional parameters to copy
-					   embedded response to user's va */
-
-#if defined(BE_DEBUG)
-	u16 subsystem, opcode;	/* Track this FWCMD for debug builds. */
-	struct MCC_WRB_AMAP *ring_wrb;
-	u32 consumed_count;
-#endif
-} ;
-
-/*
-    Represents a function object for network or storage.  This
-    is used to manage per-function resources like MCC CQs, etc.
-*/
-struct be_function_object {
-
-	u32 magic;		/*!< magic for detecting memory corruption. */
-
-	/* PCI BAR mapped addresses */
-	u8 __iomem *csr_va;	/* CSR */
-	u8 __iomem *db_va;	/* Door Bell */
-	u8 __iomem *pci_va;	/* PCI config space */
-	u32 emulate;		/* if set, MPU is not available.
-				  Emulate everything.     */
-	u32 pend_queue_driving;	/* if set, drive the queued WRBs
-				   after releasing the WRB lock */
-
-	spinlock_t post_lock;	/* lock for verifying one thread posting wrbs */
-	spinlock_t cq_lock;	/* lock for verifying one thread
-				   processing cq */
-	spinlock_t mcc_context_lock;	/* lock for protecting mcc
-					   context free list */
-	unsigned long post_irq;
-	unsigned long cq_irq;
-
-	u32 type;
-	u32 pci_function_number;
-
-	struct be_mcc_object *mcc;	/* mcc rings. */
-
-	struct {
-		struct MCC_MAILBOX_AMAP *va;	/* VA to the mailbox */
-		u64 pa;	/* PA to the mailbox */
-		u32 length;	/* byte length of mailbox */
-
-		/* One default context struct used for posting at
-		 * least one MCC_WRB
-		 */
-		struct be_mcc_wrb_context default_context;
-		bool default_context_allocated;
-	} mailbox;
-
-	struct {
-
-		/* Wake on lans configured. */
-		u32 wol_bitmask;	/* bits 0,1,2,3 are set if
-					   corresponding index is enabled */
-	} config;
-
-
-	struct BE_FIRMWARE_CONFIG fw_config;
-} ;
-
-/*
-      Represents an Event Queue
-*/
-struct be_eq_object {
-	u32 magic;
-	atomic_t ref_count;
-
-	struct be_function_object *parent_function;
-
-	struct list_head eq_list;
-	struct list_head cq_list_head;
-
-	u32 eq_id;
-	void *cb_context;
-
-} ;
-
-/*
-    Manages a completion queue
-*/
-struct be_cq_object {
-	u32 magic;
-	atomic_t ref_count;
-
-	struct be_function_object *parent_function;
-	struct be_eq_object *eq_object;
-
-	struct list_head cq_list;
-	struct list_head cqlist_for_eq;
-
-	void *va;
-	u32 num_entries;
-
-	void *cb_context;
-
-	u32 cq_id;
-
-} ;
-
-/*
-    Manages an ethernet send queue
-*/
-struct be_ethsq_object {
-	u32 magic;
-
-	struct list_head list;
-
-	struct be_function_object *parent_function;
-	struct be_cq_object *cq_object;
-	u32 bid;
-
-} ;
-
-/*
-@brief
-    Manages an ethernet receive queue
-*/
-struct be_ethrq_object {
-	u32 magic;
-	struct list_head list;
-	struct be_function_object *parent_function;
-	u32 rid;
-	struct be_cq_object *cq_object;
-	struct be_cq_object *rss_cq_object[4];
-
-} ;
-
-/*
-    Manages an MCC
-*/
-typedef void (*mcc_async_event_callback) (void *context, u32 event_code,
-				void *event);
-struct be_mcc_object {
-	u32 magic;
-
-	struct be_function_object *parent_function;
-	struct list_head mcc_list;
-
-	struct be_cq_object *cq_object;
-
-	/* Async event callback for MCC CQ. */
-	mcc_async_event_callback async_cb;
-	void *async_context;
-
-	struct {
-		struct be_mcc_wrb_context *base;
-		u32 num;
-		struct list_head list_head;
-	} wrb_context;
-
-	struct {
-		struct ring_desc *rd;
-		struct mp_ring ring;
-	} sq;
-
-	struct {
-		struct mp_ring ring;
-	} cq;
-
-	u32 processing;		/* flag indicating that one thread
-				   is processing CQ */
-	u32 rearm;		/* doorbell rearm setting to make
-				   sure the active processing thread */
-	/* rearms the CQ if any of the threads requested it. */
-
-	struct list_head backlog;
-	u32 backlog_length;
-	u32 driving_backlog;
-	u32 consumed_index;
-
-} ;
-
-
-/* Queue context header -- the required software information for
- * queueing a WRB.
- */
-struct be_queue_driver_context {
-	mcc_wrb_cqe_callback internal_cb;	/* Function to call on
-						   completion */
-	void *internal_cb_context;	/* Parameter to pass
-						   to completion function */
-
-	mcc_wrb_cqe_callback cb;	/* Function to call on completion */
-	void *cb_context;	/* Parameter to pass to completion function */
-
-	struct be_mcc_wrb_response_copy copy;	/* Optional parameters to copy
-					   embedded response to user's va */
-	void *optional_fwcmd_va;
-	struct list_head list;
-	u32 bytes;
-} ;
-
-/*
- * Common MCC WRB header that all commands require.
- */
-struct be_mcc_wrb_header {
-	u8 rsvd[offsetof(struct BE_MCC_WRB_AMAP, payload)/8];
-} ;
-
-/*
- * All non embedded commands supported by hwlib functions only allow
- * 1 SGE.  This queue context handles them all.
- */
-struct be_nonembedded_q_ctxt {
-	struct be_queue_driver_context context;
-	struct be_mcc_wrb_header wrb_header;
-	struct MCC_SGE_AMAP sge[1];
-} ;
-
-/*
- * ------------------------------------------------------------------------
- *  This section contains the specific queue struct for each command.
- *  The user could always provide a be_generic_q_ctxt but this is a
- *  rather large struct.  By using the specific struct, memory consumption
- *  can be reduced.
- * ------------------------------------------------------------------------
- */
-
-struct be_link_status_q_ctxt {
-	struct be_queue_driver_context context;
-	struct be_mcc_wrb_header wrb_header;
-	struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY fwcmd;
-} ;
-
-struct be_multicast_q_ctxt {
-	struct be_queue_driver_context context;
-	struct be_mcc_wrb_header wrb_header;
-	struct FWCMD_COMMON_NTWK_MULTICAST_SET fwcmd;
-} ;
-
-
-struct be_vlan_q_ctxt {
-	struct be_queue_driver_context context;
-	struct be_mcc_wrb_header wrb_header;
-	struct FWCMD_COMMON_NTWK_VLAN_CONFIG fwcmd;
-} ;
-
-struct be_promiscuous_q_ctxt {
-	struct be_queue_driver_context context;
-	struct be_mcc_wrb_header wrb_header;
-	struct FWCMD_ETH_PROMISCUOUS fwcmd;
-} ;
-
-struct be_force_failover_q_ctxt {
-	struct be_queue_driver_context context;
-	struct be_mcc_wrb_header wrb_header;
-	struct FWCMD_COMMON_FORCE_FAILOVER fwcmd;
-} ;
-
-
-struct be_rxf_filter_q_ctxt {
-	struct be_queue_driver_context context;
-	struct be_mcc_wrb_header wrb_header;
-	struct FWCMD_COMMON_NTWK_RX_FILTER fwcmd;
-} ;
-
-struct be_eq_modify_delay_q_ctxt {
-	struct be_queue_driver_context context;
-	struct be_mcc_wrb_header wrb_header;
-	struct FWCMD_COMMON_MODIFY_EQ_DELAY fwcmd;
-} ;
-
-/*
- * The generic context is the largest size that would be required.
- * It is the software context plus an entire WRB.
- */
-struct be_generic_q_ctxt {
-	struct be_queue_driver_context context;
-	struct be_mcc_wrb_header wrb_header;
-	struct MCC_WRB_PAYLOAD_AMAP payload;
-} ;
-
-/*
- * Types for the BE_QUEUE_CONTEXT object.
- */
-#define BE_QUEUE_INVALID	(0)
-#define BE_QUEUE_LINK_STATUS	(0xA006)
-#define BE_QUEUE_ETH_STATS	(0xA007)
-#define BE_QUEUE_TPM_STATS	(0xA008)
-#define BE_QUEUE_TCP_STATS	(0xA009)
-#define BE_QUEUE_MULTICAST	(0xA00A)
-#define BE_QUEUE_VLAN		(0xA00B)
-#define BE_QUEUE_RSS		(0xA00C)
-#define BE_QUEUE_FORCE_FAILOVER	(0xA00D)
-#define BE_QUEUE_PROMISCUOUS	(0xA00E)
-#define BE_QUEUE_WAKE_ON_LAN	(0xA00F)
-#define BE_QUEUE_NOP		(0xA010)
-
-/* --- BE_FUNCTION_ENUM --- */
-#define BE_FUNCTION_TYPE_ISCSI          (0)
-#define BE_FUNCTION_TYPE_NETWORK        (1)
-#define BE_FUNCTION_TYPE_ARM            (2)
-
-/* --- BE_ETH_TX_RING_TYPE_ENUM --- */
-#define BE_ETH_TX_RING_TYPE_FORWARDING  (1) 	/* Ether ring for forwarding */
-#define BE_ETH_TX_RING_TYPE_STANDARD    (2)	/* Ether ring for sending */
-						/* network packets. */
-#define BE_ETH_TX_RING_TYPE_BOUND       (3)	/* Ethernet ring for sending */
-						/* network packets, bound */
-						/* to a physical port. */
-/*
- * ----------------------------------------------------------------------
- *   API MACROS
- * ----------------------------------------------------------------------
- */
-#define BE_FWCMD_NAME(_short_name_)     struct FWCMD_##_short_name_
-#define BE_OPCODE_NAME(_short_name_)    OPCODE_##_short_name_
-#define BE_SUBSYSTEM_NAME(_short_name_) SUBSYSTEM_##_short_name_
-
-
-#define BE_PREPARE_EMBEDDED_FWCMD(_pfob_, _wrb_, _short_name_)	\
-	((BE_FWCMD_NAME(_short_name_) *)				\
-	be_function_prepare_embedded_fwcmd(_pfob_, _wrb_,	\
-		sizeof(BE_FWCMD_NAME(_short_name_)),		\
-		FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \
-		FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \
-		BE_OPCODE_NAME(_short_name_),				\
-		BE_SUBSYSTEM_NAME(_short_name_)));
-
-#define BE_PREPARE_NONEMBEDDED_FWCMD(_pfob_, _wrb_, _iva_, _ipa_, _short_name_)\
-	((BE_FWCMD_NAME(_short_name_) *)				\
-	be_function_prepare_nonembedded_fwcmd(_pfob_, _wrb_, (_iva_), (_ipa_), \
-		sizeof(BE_FWCMD_NAME(_short_name_)),		\
-		FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \
-		FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \
-		BE_OPCODE_NAME(_short_name_),				\
-		BE_SUBSYSTEM_NAME(_short_name_)));
-
-int be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va,
-	u8 __iomem *pci_va, u32 function_type, struct ring_desc *mailbox_rd,
-	  struct be_function_object *pfob);
-
-int be_function_object_destroy(struct be_function_object *pfob);
-int be_function_cleanup(struct be_function_object *pfob);
-
-
-int be_function_get_fw_version(struct be_function_object *pfob,
-	struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fw_version,
-	mcc_wrb_cqe_callback cb, void *cb_context);
-
-
-int be_eq_modify_delay(struct be_function_object *pfob,
-		   u32 num_eq, struct be_eq_object **eq_array,
-		   u32 *eq_delay_array, mcc_wrb_cqe_callback cb,
-		   void *cb_context,
-		   struct be_eq_modify_delay_q_ctxt *q_ctxt);
-
-
-
-int be_eq_create(struct be_function_object *pfob,
-	     struct ring_desc *rd, u32 eqe_size, u32 num_entries,
-	     u32 watermark, u32 timer_delay, struct be_eq_object *eq_object);
-
-int be_eq_destroy(struct be_eq_object *eq);
-
-int be_cq_create(struct be_function_object *pfob,
-	struct ring_desc *rd, u32 length,
-	bool solicited_eventable, bool no_delay,
-	u32 wm_thresh, struct be_eq_object *eq_object,
-	struct be_cq_object *cq_object);
-
-int be_cq_destroy(struct be_cq_object *cq);
-
-int be_mcc_ring_create(struct be_function_object *pfob,
-		   struct ring_desc *rd, u32 length,
-		   struct be_mcc_wrb_context *context_array,
-		   u32 num_context_entries,
-		   struct be_cq_object *cq, struct be_mcc_object *mcc);
-int be_mcc_ring_destroy(struct be_mcc_object *mcc_object);
-
-int be_mcc_process_cq(struct be_mcc_object *mcc_object, bool rearm);
-
-int be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object,
-		mcc_async_event_callback cb, void *cb_context);
-
-int be_pci_soft_reset(struct be_function_object *pfob);
-
-
-int be_drive_POST(struct be_function_object *pfob);
-
-
-int be_eth_sq_create(struct be_function_object *pfob,
-		struct ring_desc *rd, u32 length_in_bytes,
-		u32 type, u32 ulp, struct be_cq_object *cq_object,
-		struct be_ethsq_object *eth_sq);
-
-struct be_eth_sq_parameters {
-	u32 port;
-	u32 rsvd0[2];
-} ;
-
-int be_eth_sq_create_ex(struct be_function_object *pfob,
-		    struct ring_desc *rd, u32 length_in_bytes,
-		    u32 type, u32 ulp, struct be_cq_object *cq_object,
-		    struct be_eth_sq_parameters *ex_parameters,
-		    struct be_ethsq_object *eth_sq);
-int be_eth_sq_destroy(struct be_ethsq_object *eth_sq);
-
-int be_eth_set_flow_control(struct be_function_object *pfob,
-			bool txfc_enable, bool rxfc_enable);
-
-int be_eth_get_flow_control(struct be_function_object *pfob,
-			bool *txfc_enable, bool *rxfc_enable);
-int be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps);
-
-int be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps);
-
-int be_eth_set_frame_size(struct be_function_object *pfob,
-		      u32 *tx_frame_size, u32 *rx_frame_size);
-
-int be_eth_rq_create(struct be_function_object *pfob,
-		 struct ring_desc *rd, struct be_cq_object *cq_object,
-		 struct be_cq_object *bcmc_cq_object,
-		 struct be_ethrq_object *eth_rq);
-
-int be_eth_rq_destroy(struct be_ethrq_object *eth_rq);
-
-int be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush,
-		mcc_wrb_cqe_callback cb, void *cb_context);
-int be_eth_rq_set_frag_size(struct be_function_object *pfob,
-		u32 new_frag_size_bytes, u32 *actual_frag_size_bytes);
-int be_eth_rq_get_frag_size(struct be_function_object *pfob,
-						u32 *frag_size_bytes);
-
-void *be_function_prepare_embedded_fwcmd(struct be_function_object *pfob,
-		   struct MCC_WRB_AMAP *wrb,
-		   u32 payload_length, u32 request_length,
-		   u32 response_length, u32 opcode, u32 subsystem);
-void *be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob,
-	struct MCC_WRB_AMAP *wrb, void *fwcmd_header_va, u64 fwcmd_header_pa,
-	u32 payload_length, u32 request_length, u32 response_length,
-	u32 opcode, u32 subsystem);
-
-
-struct MCC_WRB_AMAP *
-be_function_peek_mcc_wrb(struct be_function_object *pfob);
-
-int be_rxf_mac_address_read_write(struct be_function_object *pfob,
-	      bool port1, bool mac1, bool mgmt,
-	      bool write, bool permanent, u8 *mac_address,
-	      mcc_wrb_cqe_callback cb,
-	      void *cb_context);
-
-int be_rxf_multicast_config(struct be_function_object *pfob,
-			bool promiscuous, u32 num, u8 *mac_table,
-			mcc_wrb_cqe_callback cb,
-			void *cb_context,
-			struct be_multicast_q_ctxt *q_ctxt);
-
-int be_rxf_vlan_config(struct be_function_object *pfob,
-	   bool promiscuous, u32 num, u16 *vlan_tag_array,
-	   mcc_wrb_cqe_callback cb, void *cb_context,
-	   struct be_vlan_q_ctxt *q_ctxt);
-
-
-int be_rxf_link_status(struct be_function_object *pfob,
-		   struct BE_LINK_STATUS *link_status,
-		   mcc_wrb_cqe_callback cb,
-		   void *cb_context,
-		   struct be_link_status_q_ctxt *q_ctxt);
-
-
-int be_rxf_query_eth_statistics(struct be_function_object *pfob,
-		struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd,
-		u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb,
-		void *cb_context,
-		struct be_nonembedded_q_ctxt *q_ctxt);
-
-int be_rxf_promiscuous(struct be_function_object *pfob,
-		   bool enable_port0, bool enable_port1,
-		   mcc_wrb_cqe_callback cb, void *cb_context,
-		   struct be_promiscuous_q_ctxt *q_ctxt);
-
-
-int be_rxf_filter_config(struct be_function_object *pfob,
-		     struct NTWK_RX_FILTER_SETTINGS *settings,
-		     mcc_wrb_cqe_callback cb,
-		     void *cb_context,
-		     struct be_rxf_filter_q_ctxt *q_ctxt);
-
-/*
- * ------------------------------------------------------
- *  internal functions used by hwlib
- * ------------------------------------------------------
- */
-
-
-int be_function_ring_destroy(struct be_function_object *pfob,
-		       u32 id, u32 ring_type, mcc_wrb_cqe_callback cb,
-		       void *cb_context,
-		       mcc_wrb_cqe_callback internal_cb,
-		       void *internal_callback_context);
-
-int be_function_post_mcc_wrb(struct be_function_object *pfob,
-		struct MCC_WRB_AMAP *wrb,
-		struct be_generic_q_ctxt *q_ctxt,
-		mcc_wrb_cqe_callback cb, void *cb_context,
-		mcc_wrb_cqe_callback internal_cb,
-		void *internal_cb_context, void *optional_fwcmd_va,
-		struct be_mcc_wrb_response_copy *response_copy);
-
-int be_function_queue_mcc_wrb(struct be_function_object *pfob,
-			  struct be_generic_q_ctxt *q_ctxt);
-
-/*
- * ------------------------------------------------------
- *  MCC QUEUE
- * ------------------------------------------------------
- */
-
-int be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *rd);
-
-
-struct MCC_WRB_AMAP *
-_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue);
-
-struct be_mcc_wrb_context *
-_be_mcc_allocate_wrb_context(struct be_function_object *pfob);
-
-void _be_mcc_free_wrb_context(struct be_function_object *pfob,
-			 struct be_mcc_wrb_context *context);
-
-int _be_mpu_post_wrb_mailbox(struct be_function_object *pfob,
-	 struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context);
-
-int _be_mpu_post_wrb_ring(struct be_mcc_object *mcc,
-	struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context);
-
-void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc);
-
-
-/*
- * ------------------------------------------------------
- *  Ring Sizes
- * ------------------------------------------------------
- */
-static inline u32 be_ring_encoding_to_length(u32 encoding, u32 object_size)
-{
-
-	ASSERT(encoding != 1);	/* 1 is rsvd */
-	ASSERT(encoding < 16);
-	ASSERT(object_size > 0);
-
-	if (encoding == 0)	/* 32k deep */
-		encoding = 16;
-
-	return (1 << (encoding - 1)) * object_size;
-}
-
-static inline
-u32 be_ring_length_to_encoding(u32 length_in_bytes, u32 object_size)
-{
-
-	u32 count, encoding;
-
-	ASSERT(object_size > 0);
-	ASSERT(length_in_bytes % object_size == 0);
-
-	count = length_in_bytes / object_size;
-
-	ASSERT(count > 1);
-	ASSERT(count <= 32 * 1024);
-	ASSERT(length_in_bytes <= 8 * PAGE_SIZE); /* max ring size in UT */
-
-	encoding = __ilog2_u32(count) + 1;
-
-	if (encoding == 16)
-		encoding = 0;	/* 32k deep */
-
-	return encoding;
-}
-
-void be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list,
-						u32 max_num);
-#endif /* __hwlib_h__ */
diff --git a/drivers/staging/benet/mpu.c b/drivers/staging/benet/mpu.c
deleted file mode 100644
index 269cc11..0000000
--- a/drivers/staging/benet/mpu.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-#include <linux/delay.h>
-#include "hwlib.h"
-#include "bestatus.h"
-
-static
-inline void mp_ring_create(struct mp_ring *ring, u32 num, u32 size, void *va)
-{
-	ASSERT(ring);
-	memset(ring, 0, sizeof(struct mp_ring));
-	ring->num = num;
-	ring->pages = DIV_ROUND_UP(num * size, PAGE_SIZE);
-	ring->itemSize = size;
-	ring->va = va;
-}
-
-/*
- * -----------------------------------------------------------------------
- * Interface for 2 index rings. i.e. consumer/producer rings
- * --------------------------------------------------------------------------
- */
-
-/* Returns number items pending on ring. */
-static inline u32 mp_ring_num_pending(struct mp_ring *ring)
-{
-	ASSERT(ring);
-	if (ring->num == 0)
-		return 0;
-	return be_subc(ring->pidx, ring->cidx, ring->num);
-}
-
-/* Returns number items free on ring. */
-static inline u32 mp_ring_num_empty(struct mp_ring *ring)
-{
-	ASSERT(ring);
-	return ring->num - 1 - mp_ring_num_pending(ring);
-}
-
-/* Consume 1 item */
-static inline void mp_ring_consume(struct mp_ring *ring)
-{
-	ASSERT(ring);
-	ASSERT(ring->pidx != ring->cidx);
-
-	ring->cidx = be_addc(ring->cidx, 1, ring->num);
-}
-
-/* Produce 1 item */
-static inline void mp_ring_produce(struct mp_ring *ring)
-{
-	ASSERT(ring);
-	ring->pidx = be_addc(ring->pidx, 1, ring->num);
-}
-
-/* Consume count items */
-static inline void mp_ring_consume_multiple(struct mp_ring *ring, u32 count)
-{
-	ASSERT(ring);
-	ASSERT(mp_ring_num_pending(ring) >= count);
-	ring->cidx = be_addc(ring->cidx, count, ring->num);
-}
-
-static inline void *mp_ring_item(struct mp_ring *ring, u32 index)
-{
-	ASSERT(ring);
-	ASSERT(index < ring->num);
-	ASSERT(ring->itemSize > 0);
-	return (u8 *) ring->va + index * ring->itemSize;
-}
-
-/* Ptr to produce item */
-static inline void *mp_ring_producer_ptr(struct mp_ring *ring)
-{
-	ASSERT(ring);
-	return mp_ring_item(ring, ring->pidx);
-}
-
-/*
- * Returns a pointer to the current location in the ring.
- * This is used for rings with 1 index.
- */
-static inline void *mp_ring_current(struct mp_ring *ring)
-{
-	ASSERT(ring);
-	ASSERT(ring->pidx == 0);	/* not used */
-
-	return mp_ring_item(ring, ring->cidx);
-}
-
-/*
- * Increment index for rings with only 1 index.
- * This is used for rings with 1 index.
- */
-static inline void *mp_ring_next(struct mp_ring *ring)
-{
-	ASSERT(ring);
-	ASSERT(ring->num > 0);
-	ASSERT(ring->pidx == 0);	/* not used */
-
-	ring->cidx = be_addc(ring->cidx, 1, ring->num);
-	return mp_ring_current(ring);
-}
-
-/*
-    This routine waits for a previously posted mailbox WRB to be completed.
-    Specifically it waits for the mailbox to say that it's ready to accept
-    more data by setting the LSB of the mailbox pd register to 1.
-
-    pcontroller      - The function object to post this data to
-
-    IRQL < DISPATCH_LEVEL
-*/
-static void be_mcc_mailbox_wait(struct be_function_object *pfob)
-{
-	struct MPU_MAILBOX_DB_AMAP mailbox_db;
-	u32 i = 0;
-	u32 ready;
-
-	if (pfob->emulate) {
-		/* No waiting for mailbox in emulated mode. */
-		return;
-	}
-
-	mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db);
-	ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db);
-
-	while (ready == false) {
-		if ((++i & 0x3FFFF) == 0) {
-			TRACE(DL_WARN, "Waiting for mailbox ready - %dk polls",
-								i / 1000);
-		}
-		udelay(1);
-		mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db);
-		ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db);
-	}
-}
-
-/*
-    This routine tells the MCC mailbox that there is data to processed
-    in the mailbox. It does this by setting the physical address for the
-    mailbox location and clearing the LSB.  This routine returns immediately
-    and does not wait for the WRB to be processed.
-
-    pcontroller      - The function object to post this data to
-
-    IRQL < DISPATCH_LEVEL
-
-*/
-static void be_mcc_mailbox_notify(struct be_function_object *pfob)
-{
-	struct MPU_MAILBOX_DB_AMAP mailbox_db;
-	u32 pa;
-
-	ASSERT(pfob->mailbox.pa);
-	ASSERT(pfob->mailbox.va);
-
-	/* If emulated, do not ring the mailbox */
-	if (pfob->emulate) {
-		TRACE(DL_WARN, "MPU disabled. Skipping mailbox notify.");
-		return;
-	}
-
-	/* form the higher bits in the address */
-	mailbox_db.dw[0] = 0;	/* init */
-	AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 1);
-	AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0);
-
-	/* bits 34 to 63 */
-	pa = (u32) (pfob->mailbox.pa >> 34);
-	AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa);
-
-	/* Wait for the MPU to be ready */
-	be_mcc_mailbox_wait(pfob);
-
-	/* Ring doorbell 1st time */
-	PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]);
-
-	/* Wait for 1st write to be acknowledged. */
-	be_mcc_mailbox_wait(pfob);
-
-	/* lower bits 30 bits from 4th bit (bits 4 to 33)*/
-	pa = (u32) (pfob->mailbox.pa >> 4) & 0x3FFFFFFF;
-
-	AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 0);
-	AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0);
-	AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa);
-
-	/* Ring doorbell 2nd time */
-	PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]);
-}
-
-/*
-    This routine tells the MCC mailbox that there is data to processed
-    in the mailbox. It does this by setting the physical address for the
-    mailbox location and clearing the LSB.  This routine spins until the
-    MPU writes a 1 into the LSB indicating that the data has been received
-    and is ready to be processed.
-
-    pcontroller      - The function object to post this data to
-
-    IRQL < DISPATCH_LEVEL
-*/
-static void
-be_mcc_mailbox_notify_and_wait(struct be_function_object *pfob)
-{
-	/*
-	 * Notify it
-	 */
-	be_mcc_mailbox_notify(pfob);
-	/*
-	 * Now wait for completion of WRB
-	 */
-	be_mcc_mailbox_wait(pfob);
-}
-
-void
-be_mcc_process_cqe(struct be_function_object *pfob,
-				struct MCC_CQ_ENTRY_AMAP *cqe)
-{
-	struct be_mcc_wrb_context *wrb_context = NULL;
-	u32 offset, status;
-	u8 *p;
-
-	ASSERT(cqe);
-	/*
-	 * A command completed.  Commands complete out-of-order.
-	 * Determine which command completed from the TAG.
-	 */
-	offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8;
-	p = (u8 *) cqe + offset;
-	wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p);
-	ASSERT(wrb_context);
-
-	/*
-	 * Perform a response copy if requested.
-	 * Only copy data if the FWCMD is successful.
-	 */
-	status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, cqe);
-	if (status == MGMT_STATUS_SUCCESS && wrb_context->copy.length > 0) {
-		ASSERT(wrb_context->wrb);
-		ASSERT(wrb_context->copy.va);
-		p = (u8 *)wrb_context->wrb +
-				offsetof(struct BE_MCC_WRB_AMAP, payload)/8;
-		memcpy(wrb_context->copy.va,
-			  (u8 *)p + wrb_context->copy.fwcmd_offset,
-			  wrb_context->copy.length);
-	}
-
-	if (status)
-		status = BE_NOT_OK;
-	/* internal callback */
-	if (wrb_context->internal_cb) {
-		wrb_context->internal_cb(wrb_context->internal_cb_context,
-						status, wrb_context->wrb);
-	}
-
-	/* callback */
-	if (wrb_context->cb) {
-		wrb_context->cb(wrb_context->cb_context,
-					      status, wrb_context->wrb);
-	}
-	/* Free the context structure */
-	_be_mcc_free_wrb_context(pfob, wrb_context);
-}
-
-void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc)
-{
-	struct be_function_object *pfob = NULL;
-	int status = BE_PENDING;
-	struct be_generic_q_ctxt *q_ctxt;
-	struct MCC_WRB_AMAP *wrb;
-	struct MCC_WRB_AMAP *queue_wrb;
-	u32 length, payload_length, sge_count, embedded;
-	unsigned long irql;
-
-	BUILD_BUG_ON((sizeof(struct be_generic_q_ctxt) <
-			  sizeof(struct be_queue_driver_context) +
-					sizeof(struct MCC_WRB_AMAP)));
-	pfob = mcc->parent_function;
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	if (mcc->driving_backlog) {
-		spin_unlock_irqrestore(&pfob->post_lock, irql);
-		if (pfob->pend_queue_driving && pfob->mcc) {
-			pfob->pend_queue_driving = 0;
-			be_drive_mcc_wrb_queue(pfob->mcc);
-		}
-		return;
-	}
-	/* Acquire the flag to limit 1 thread to redrive posts. */
-	mcc->driving_backlog = 1;
-
-	while (!list_empty(&mcc->backlog)) {
-		wrb = _be_mpu_peek_ring_wrb(mcc, true);	/* Driving the queue */
-		if (!wrb)
-			break;	/* No space in the ring yet. */
-		/* Get the next queued entry to process. */
-		q_ctxt = list_first_entry(&mcc->backlog,
-				struct be_generic_q_ctxt, context.list);
-		list_del(&q_ctxt->context.list);
-		pfob->mcc->backlog_length--;
-		/*
-		 * Compute the required length of the WRB.
-		 * Since the queue element may be smaller than
-		 * the complete WRB, copy only the required number of bytes.
-		 */
-		queue_wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
-		embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, queue_wrb);
-		if (embedded) {
-			payload_length = AMAP_GET_BITS_PTR(MCC_WRB,
-						payload_length, queue_wrb);
-			length = sizeof(struct be_mcc_wrb_header) +
-								payload_length;
-		} else {
-			sge_count = AMAP_GET_BITS_PTR(MCC_WRB, sge_count,
-								queue_wrb);
-			ASSERT(sge_count == 1); /* only 1 frag. */
-			length = sizeof(struct be_mcc_wrb_header) +
-			    sge_count * sizeof(struct MCC_SGE_AMAP);
-		}
-
-		/*
-		 * Truncate the length based on the size of the
-		 * queue element.  Some elements that have output parameters
-		 * can be smaller than the payload_length field would
-		 * indicate.  We really only need to copy the request
-		 * parameters, not the response.
-		 */
-		length = min(length, (u32) (q_ctxt->context.bytes -
-			offsetof(struct be_generic_q_ctxt, wrb_header)));
-
-		/* Copy the queue element WRB into the ring. */
-		memcpy(wrb, &q_ctxt->wrb_header, length);
-
-		/* Post the wrb.  This should not fail assuming we have
-		 * enough context structs. */
-		status = be_function_post_mcc_wrb(pfob, wrb, NULL,
-			   q_ctxt->context.cb, q_ctxt->context.cb_context,
-			   q_ctxt->context.internal_cb,
-			   q_ctxt->context.internal_cb_context,
-			   q_ctxt->context.optional_fwcmd_va,
-			   &q_ctxt->context.copy);
-
-		if (status == BE_SUCCESS) {
-			/*
-			 * Synchronous completion. Since it was queued,
-			 * we will invoke the callback.
-			 * To the user, this is an asynchronous request.
-			 */
-			spin_unlock_irqrestore(&pfob->post_lock, irql);
-			if (pfob->pend_queue_driving && pfob->mcc) {
-				pfob->pend_queue_driving = 0;
-				be_drive_mcc_wrb_queue(pfob->mcc);
-			}
-
-			ASSERT(q_ctxt->context.cb);
-
-			q_ctxt->context.cb(
-				q_ctxt->context.cb_context,
-						BE_SUCCESS, NULL);
-
-			spin_lock_irqsave(&pfob->post_lock, irql);
-
-		} else if (status != BE_PENDING) {
-			/*
-			 * Another resource failed.  Should never happen
-			 * if we have sufficient MCC_WRB_CONTEXT structs.
-			 * Return to head of the queue.
-			 */
-			TRACE(DL_WARN, "Failed to post a queued WRB. 0x%x",
-			      status);
-			list_add(&q_ctxt->context.list, &mcc->backlog);
-			pfob->mcc->backlog_length++;
-			break;
-		}
-	}
-
-	/* Free the flag to limit 1 thread to redrive posts. */
-	mcc->driving_backlog = 0;
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-}
-
-/* This function asserts that the WRB was consumed in order. */
-#ifdef BE_DEBUG
-u32 be_mcc_wrb_consumed_in_order(struct be_mcc_object *mcc,
-					struct MCC_CQ_ENTRY_AMAP *cqe)
-{
-	struct be_mcc_wrb_context *wrb_context = NULL;
-	u32 wrb_index;
-	u32 wrb_consumed_in_order;
-	u32 offset;
-	u8 *p;
-
-	ASSERT(cqe);
-	/*
-	 * A command completed.  Commands complete out-of-order.
-	 * Determine which command completed from the TAG.
-	 */
-	offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8;
-	p = (u8 *) cqe + offset;
-	wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p);
-
-	ASSERT(wrb_context);
-
-	wrb_index = (u32) (((u64)(size_t)wrb_context->ring_wrb -
-		(u64)(size_t)mcc->sq.ring.va) / sizeof(struct MCC_WRB_AMAP));
-
-	ASSERT(wrb_index < mcc->sq.ring.num);
-
-	wrb_consumed_in_order = (u32) (wrb_index == mcc->consumed_index);
-	mcc->consumed_index = be_addc(mcc->consumed_index, 1, mcc->sq.ring.num);
-	return wrb_consumed_in_order;
-}
-#endif
-
-int be_mcc_process_cq(struct be_mcc_object *mcc, bool rearm)
-{
-	struct be_function_object *pfob = NULL;
-	struct MCC_CQ_ENTRY_AMAP *cqe;
-	struct CQ_DB_AMAP db;
-	struct mp_ring *cq_ring = &mcc->cq.ring;
-	struct mp_ring *mp_ring = &mcc->sq.ring;
-	u32 num_processed = 0;
-	u32 consumed = 0, valid, completed, cqe_consumed, async_event;
-
-	pfob = mcc->parent_function;
-
-	spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq);
-
-	/*
-	 * Verify that only one thread is processing the CQ at once.
-	 * We cannot hold the lock while processing the CQ due to
-	 * the callbacks into the OS.  Therefore, this flag is used
-	 * to control it.  If any of the threads want to
-	 * rearm the CQ, we need to honor that.
-	 */
-	if (mcc->processing != 0) {
-		mcc->rearm = mcc->rearm || rearm;
-		goto Error;
-	} else {
-		mcc->processing = 1;	/* lock processing for this thread. */
-		mcc->rearm = rearm;	/* set our rearm setting */
-	}
-
-	spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq);
-
-	cqe = mp_ring_current(cq_ring);
-	valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe);
-	while (valid) {
-
-		if (num_processed >= 8) {
-			/* coalesce doorbells, but free space in cq
-			 * ring while processing. */
-			db.dw[0] = 0;	/* clear */
-			AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id);
-			AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, false);
-			AMAP_SET_BITS_PTR(CQ_DB, event, &db, false);
-			AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db,
-							num_processed);
-			num_processed = 0;
-
-			PD_WRITE(pfob, cq_db, db.dw[0]);
-		}
-
-		async_event = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, async_event, cqe);
-		if (async_event) {
-			/* This is an asynchronous event. */
-			struct ASYNC_EVENT_TRAILER_AMAP *async_trailer =
-			    (struct ASYNC_EVENT_TRAILER_AMAP *)
-			    ((u8 *) cqe + sizeof(struct MCC_CQ_ENTRY_AMAP) -
-			     sizeof(struct ASYNC_EVENT_TRAILER_AMAP));
-			u32 event_code;
-			async_event = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER,
-						async_event, async_trailer);
-			ASSERT(async_event == 1);
-
-
-			valid = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER,
-						valid, async_trailer);
-			ASSERT(valid == 1);
-
-			/* Call the async event handler if it is installed. */
-			if (mcc->async_cb) {
-				event_code =
-					AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER,
-						event_code, async_trailer);
-				mcc->async_cb(mcc->async_context,
-					    (u32) event_code, (void *) cqe);
-			}
-
-		} else {
-			/* This is a completion entry. */
-
-			/* No vm forwarding in this driver. */
-
-			cqe_consumed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY,
-						consumed, cqe);
-			if (cqe_consumed) {
-				/*
-				 * A command on the MCC ring was consumed.
-				 * Update the consumer index.
-				 * These occur in order.
-				 */
-				ASSERT(be_mcc_wrb_consumed_in_order(mcc, cqe));
-				consumed++;
-			}
-
-			completed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY,
-					completed, cqe);
-			if (completed) {
-				/* A command completed.  Use tag to
-				 * determine which command.  */
-				be_mcc_process_cqe(pfob, cqe);
-			}
-		}
-
-		/* Reset the CQE */
-		AMAP_SET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe, false);
-		num_processed++;
-
-		/* Update our tracking for the CQ ring. */
-		cqe = mp_ring_next(cq_ring);
-		valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe);
-	}
-
-	TRACE(DL_INFO, "num_processed:0x%x, and consumed:0x%x",
-	      num_processed, consumed);
-	/*
-	 * Grab the CQ lock to synchronize the "rearm" setting for
-	 * the doorbell, and for clearing the "processing" flag.
-	 */
-	spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq);
-
-	/*
-	 * Rearm the cq.  This is done based on the global mcc->rearm
-	 * flag which combines the rearm parameter from the current
-	 * call to process_cq and any other threads
-	 * that tried to process the CQ while this one was active.
-	 * This handles the situation where a sync. fwcmd was processing
-	 * the CQ while the interrupt/dpc tries to process it.
-	 * The sync process gets to continue -- but it is now
-	 * responsible for the rearming.
-	 */
-	if (num_processed > 0 || mcc->rearm == true) {
-		db.dw[0] = 0;	/* clear */
-		AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id);
-		AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, mcc->rearm);
-		AMAP_SET_BITS_PTR(CQ_DB, event, &db, false);
-		AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, num_processed);
-
-		PD_WRITE(pfob, cq_db, db.dw[0]);
-	}
-	/*
-	 * Update the consumer index after ringing the CQ doorbell.
-	 * We don't want another thread to post more WRBs before we
-	 * have CQ space available.
-	 */
-	mp_ring_consume_multiple(mp_ring, consumed);
-
-	/* Clear the processing flag. */
-	mcc->processing = 0;
-
-Error:
-	spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq);
-	/*
-	 * Use the local variable to detect if the current thread
-	 * holds the WRB post lock.  If rearm is false, this is
-	 * either a synchronous command, or the upper layer driver is polling
-	 * from a thread.  We do not drive the queue from that
-	 * context since the driver may hold the
-	 * wrb post lock already.
-	 */
-	if (rearm)
-		be_drive_mcc_wrb_queue(mcc);
-	else
-		pfob->pend_queue_driving = 1;
-
-	return BE_SUCCESS;
-}
-
-/*
- *============================================================================
- *                  P U B L I C  R O U T I N E S
- *============================================================================
- */
-
-/*
-    This routine creates an MCC object.  This object contains an MCC send queue
-    and a CQ private to the MCC.
-
-    pcontroller      - Handle to a function object
-
-    EqObject            - EQ object that will be used to dispatch this MCC
-
-    ppMccObject         - Pointer to an internal Mcc Object returned.
-
-    Returns BE_SUCCESS if successfull,, otherwise a useful error code
-	is returned.
-
-    IRQL < DISPATCH_LEVEL
-
-*/
-int
-be_mcc_ring_create(struct be_function_object *pfob,
-		   struct ring_desc *rd, u32 length,
-		   struct be_mcc_wrb_context *context_array,
-		   u32 num_context_entries,
-		   struct be_cq_object *cq, struct be_mcc_object *mcc)
-{
-	int status = 0;
-
-	struct FWCMD_COMMON_MCC_CREATE *fwcmd = NULL;
-	struct MCC_WRB_AMAP *wrb = NULL;
-	u32 num_entries_encoded, n, i;
-	void *va = NULL;
-	unsigned long irql;
-
-	if (length < sizeof(struct MCC_WRB_AMAP) * 2) {
-		TRACE(DL_ERR, "Invalid MCC ring length:%d", length);
-		return BE_NOT_OK;
-	}
-	/*
-	 * Reduce the actual ring size to be less than the number
-	 * of context entries.  This ensures that we run out of
-	 * ring WRBs first so the queuing works correctly.  We never
-	 * queue based on context structs.
-	 */
-	if (num_context_entries + 1 <
-			length / sizeof(struct MCC_WRB_AMAP) - 1) {
-
-		u32 max_length =
-		    (num_context_entries + 2) * sizeof(struct MCC_WRB_AMAP);
-
-		if (is_power_of_2(max_length))
-			length = __roundup_pow_of_two(max_length+1) / 2;
-		else
-			length = __roundup_pow_of_two(max_length) / 2;
-
-		ASSERT(length <= max_length);
-
-		TRACE(DL_WARN,
-			"MCC ring length reduced based on context entries."
-			" length:%d wrbs:%d context_entries:%d", length,
-			(int) (length / sizeof(struct MCC_WRB_AMAP)),
-			num_context_entries);
-	}
-
-	spin_lock_irqsave(&pfob->post_lock, irql);
-
-	num_entries_encoded =
-	    be_ring_length_to_encoding(length, sizeof(struct MCC_WRB_AMAP));
-
-	/* Init MCC object. */
-	memset(mcc, 0, sizeof(*mcc));
-	mcc->parent_function = pfob;
-	mcc->cq_object = cq;
-
-	INIT_LIST_HEAD(&mcc->backlog);
-
-	wrb = be_function_peek_mcc_wrb(pfob);
-	if (!wrb) {
-		ASSERT(wrb);
-		TRACE(DL_ERR, "No free MCC WRBs in create EQ.");
-		status = BE_STATUS_NO_MCC_WRB;
-		goto error;
-	}
-	/* Prepares an embedded fwcmd, including request/response sizes. */
-	fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MCC_CREATE);
-
-	fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE);
-	/*
-	 * Program MCC ring context
-	 */
-	AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, pdid,
-			&fwcmd->params.request.context, 0);
-	AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, invalid,
-			&fwcmd->params.request.context, false);
-	AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, ring_size,
-			&fwcmd->params.request.context, num_entries_encoded);
-
-	n = cq->cq_id;
-	AMAP_SET_BITS_PTR(MCC_RING_CONTEXT,
-				cq_id, &fwcmd->params.request.context, n);
-	be_rd_to_pa_list(rd, fwcmd->params.request.pages,
-				ARRAY_SIZE(fwcmd->params.request.pages));
-	/* Post the f/w command */
-	status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
-						NULL, NULL, fwcmd, NULL);
-	if (status != BE_SUCCESS) {
-		TRACE(DL_ERR, "MCC to create CQ failed.");
-		goto error;
-	}
-	/*
-	 * Create a linked list of context structures
-	 */
-	mcc->wrb_context.base = context_array;
-	mcc->wrb_context.num = num_context_entries;
-	INIT_LIST_HEAD(&mcc->wrb_context.list_head);
-	memset(context_array, 0,
-		    sizeof(struct be_mcc_wrb_context) * num_context_entries);
-	for (i = 0; i < mcc->wrb_context.num; i++) {
-		list_add_tail(&context_array[i].next,
-					&mcc->wrb_context.list_head);
-	}
-
-	/*
-	 *
-	 * Create an mcc_ring for tracking WRB hw ring
-	 */
-	va = rd->va;
-	ASSERT(va);
-	mp_ring_create(&mcc->sq.ring, length / sizeof(struct MCC_WRB_AMAP),
-				sizeof(struct MCC_WRB_AMAP), va);
-	mcc->sq.ring.id = fwcmd->params.response.id;
-	/*
-	 * Init a mcc_ring for tracking the MCC CQ.
-	 */
-	ASSERT(cq->va);
-	mp_ring_create(&mcc->cq.ring, cq->num_entries,
-		       sizeof(struct MCC_CQ_ENTRY_AMAP), cq->va);
-	mcc->cq.ring.id = cq->cq_id;
-
-	/* Force zeroing of CQ. */
-	memset(cq->va, 0, cq->num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP));
-
-	/* Initialize debug index. */
-	mcc->consumed_index = 0;
-
-	atomic_inc(&cq->ref_count);
-	pfob->mcc = mcc;
-
-	TRACE(DL_INFO, "MCC ring created. id:%d bytes:%d cq_id:%d cq_entries:%d"
-	      " num_context:%d", mcc->sq.ring.id, length,
-	      cq->cq_id, cq->num_entries, num_context_entries);
-
-error:
-	spin_unlock_irqrestore(&pfob->post_lock, irql);
-	if (pfob->pend_queue_driving && pfob->mcc) {
-		pfob->pend_queue_driving = 0;
-		be_drive_mcc_wrb_queue(pfob->mcc);
-	}
-	return status;
-}
-
-/*
-    This routine destroys an MCC send queue
-
-    MccObject         - Internal Mcc Object to be destroyed.
-
-    Returns BE_SUCCESS if successfull, otherwise an error code is returned.
-
-    IRQL < DISPATCH_LEVEL
-
-    The caller of this routine must ensure that no other WRB may be posted
-    until this routine returns.
-
-*/
-int be_mcc_ring_destroy(struct be_mcc_object *mcc)
-{
-	int status = 0;
-	struct be_function_object *pfob = mcc->parent_function;
-
-
-	ASSERT(mcc->processing == 0);
-
-	/*
-	 * Remove the ring from the function object.
-	 * This transitions back to mailbox mode.
-	 */
-	pfob->mcc = NULL;
-
-	/* Send fwcmd to destroy the queue.  (Using the mailbox.) */
-	status = be_function_ring_destroy(mcc->parent_function, mcc->sq.ring.id,
-			     FWCMD_RING_TYPE_MCC, NULL, NULL, NULL, NULL);
-	ASSERT(status == 0);
-
-	/* Release the SQ reference to the CQ */
-	atomic_dec(&mcc->cq_object->ref_count);
-
-	return status;
-}
-
-static void
-mcc_wrb_sync_cb(void *context, int staus, struct MCC_WRB_AMAP *wrb)
-{
-	struct be_mcc_wrb_context *wrb_context =
-				(struct be_mcc_wrb_context *) context;
-	ASSERT(wrb_context);
-	*wrb_context->users_final_status = staus;
-}
-
-/*
-    This routine posts a command to the MCC send queue
-
-    mcc       - Internal Mcc Object to be destroyed.
-
-    wrb             - wrb to post.
-
-    Returns BE_SUCCESS if successfull, otherwise an error code is returned.
-
-    IRQL < DISPATCH_LEVEL if CompletionCallback is not NULL
-    IRQL <=DISPATCH_LEVEL if CompletionCallback is  NULL
-
-    If this routine is called with CompletionCallback != NULL the
-    call is considered to be asynchronous and will return as soon
-    as the WRB is posted to the MCC with BE_PENDING.
-
-    If CompletionCallback is NULL, then this routine will not return until
-    a completion for this MCC command has been processed.
-    If called at DISPATCH_LEVEL the CompletionCallback must be NULL.
-
-    This routine should only be called if the MPU has been boostraped past
-    mailbox mode.
-
-
-*/
-int
-_be_mpu_post_wrb_ring(struct be_mcc_object *mcc, struct MCC_WRB_AMAP *wrb,
-				struct be_mcc_wrb_context *wrb_context)
-{
-
-	struct MCC_WRB_AMAP *ring_wrb = NULL;
-	int status = BE_PENDING;
-	int final_status = BE_PENDING;
-	mcc_wrb_cqe_callback cb = NULL;
-	struct MCC_DB_AMAP mcc_db;
-	u32 embedded;
-
-	ASSERT(mp_ring_num_empty(&mcc->sq.ring) > 0);
-	/*
-	 * Input wrb is most likely the next wrb in the ring, since the client
-	 * can peek at the address.
-	 */
-	ring_wrb = mp_ring_producer_ptr(&mcc->sq.ring);
-	if (wrb != ring_wrb) {
-		/* If not equal, copy it into the ring. */
-		memcpy(ring_wrb, wrb, sizeof(struct MCC_WRB_AMAP));
-	}
-#ifdef BE_DEBUG
-	wrb_context->ring_wrb = ring_wrb;
-#endif
-	embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, ring_wrb);
-	if (embedded) {
-		/* embedded commands will have the response within the WRB. */
-		wrb_context->wrb = ring_wrb;
-	} else {
-		/*
-		 * non-embedded commands will not have the response
-		 * within the WRB, and they may complete out-of-order.
-		 * The WRB will not be valid to inspect
-		 * during the completion.
-		 */
-		wrb_context->wrb = NULL;
-	}
-	cb = wrb_context->cb;
-
-	if (cb == NULL) {
-		/* Assign our internal callback if this is a
-		 * synchronous call. */
-		wrb_context->cb = mcc_wrb_sync_cb;
-		wrb_context->cb_context = wrb_context;
-		wrb_context->users_final_status = &final_status;
-	}
-	/* Increment producer index */
-
-	mcc_db.dw[0] = 0;		/* initialize */
-	AMAP_SET_BITS_PTR(MCC_DB, rid, &mcc_db, mcc->sq.ring.id);
-	AMAP_SET_BITS_PTR(MCC_DB, numPosted, &mcc_db, 1);
-
-	mp_ring_produce(&mcc->sq.ring);
-	PD_WRITE(mcc->parent_function, mpu_mcc_db, mcc_db.dw[0]);
-	TRACE(DL_INFO, "pidx: %x and cidx: %x.", mcc->sq.ring.pidx,
-	      mcc->sq.ring.cidx);
-
-	if (cb == NULL) {
-		int polls = 0;	/* At >= 1 us per poll   */
-		/* Wait until this command completes, polling the CQ. */
-		do {
-			TRACE(DL_INFO, "FWCMD submitted in the poll mode.");
-			/* Do not rearm CQ in this context. */
-			be_mcc_process_cq(mcc, false);
-
-			if (final_status == BE_PENDING) {
-				if ((++polls & 0x7FFFF) == 0) {
-					TRACE(DL_WARN,
-					      "Warning : polling MCC CQ for %d"
-					      "ms.", polls / 1000);
-				}
-
-				udelay(1);
-			}
-
-			/* final_status changed when the command completes */
-		} while (final_status == BE_PENDING);
-
-		status = final_status;
-	}
-
-	return status;
-}
-
-struct MCC_WRB_AMAP *
-_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue)
-{
-	/* If we have queued items, do not allow a post to bypass the queue. */
-	if (!driving_queue && !list_empty(&mcc->backlog))
-		return NULL;
-
-	if (mp_ring_num_empty(&mcc->sq.ring) <= 0)
-		return NULL;
-	return (struct MCC_WRB_AMAP *) mp_ring_producer_ptr(&mcc->sq.ring);
-}
-
-int
-be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *mailbox)
-{
-	ASSERT(mailbox);
-	pfob->mailbox.va = mailbox->va;
-	pfob->mailbox.pa =  cpu_to_le64(mailbox->pa);
-	pfob->mailbox.length = mailbox->length;
-
-	ASSERT(((u32)(size_t)pfob->mailbox.va & 0xf) == 0);
-	ASSERT(((u32)(size_t)pfob->mailbox.pa & 0xf) == 0);
-	/*
-	 * Issue the WRB to set MPU endianness
-	 */
-	{
-		u64 *endian_check = (u64 *) (pfob->mailbox.va +
-				offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8);
-		*endian_check = 0xFF1234FFFF5678FFULL;
-	}
-
-	be_mcc_mailbox_notify_and_wait(pfob);
-
-	return BE_SUCCESS;
-}
-
-
-/*
-    This routine posts a command to the MCC mailbox.
-
-    FuncObj         - Function Object to post the WRB on behalf of.
-    wrb             - wrb to post.
-    CompletionCallback  - Address of a callback routine to invoke once the WRB
-				is completed.
-    CompletionCallbackContext - Opaque context to be passed during the call to
-				the CompletionCallback.
-    Returns BE_SUCCESS if successfull, otherwise an error code is returned.
-
-    IRQL <=DISPATCH_LEVEL if CompletionCallback is  NULL
-
-    This routine will block until a completion for this MCC command has been
-    processed. If called at DISPATCH_LEVEL the CompletionCallback must be NULL.
-
-    This routine should only be called if the MPU has not been boostraped past
-    mailbox mode.
-*/
-int
-_be_mpu_post_wrb_mailbox(struct be_function_object *pfob,
-	 struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context)
-{
-	struct MCC_MAILBOX_AMAP *mailbox = NULL;
-	struct MCC_WRB_AMAP *mb_wrb;
-	struct MCC_CQ_ENTRY_AMAP *mb_cq;
-	u32 offset, status;
-
-	ASSERT(pfob->mcc == NULL);
-	mailbox = pfob->mailbox.va;
-	ASSERT(mailbox);
-
-	offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8;
-	mb_wrb = (struct MCC_WRB_AMAP *) (u8 *)mailbox + offset;
-	if (mb_wrb != wrb) {
-		memset(mailbox, 0, sizeof(*mailbox));
-		memcpy(mb_wrb, wrb, sizeof(struct MCC_WRB_AMAP));
-	}
-	/* The callback can inspect the final WRB to get output parameters. */
-	wrb_context->wrb = mb_wrb;
-
-	be_mcc_mailbox_notify_and_wait(pfob);
-
-	/* A command completed.  Use tag to determine which command. */
-	offset = offsetof(struct BE_MCC_MAILBOX_AMAP, cq)/8;
-	mb_cq = (struct MCC_CQ_ENTRY_AMAP *) ((u8 *)mailbox + offset);
-	be_mcc_process_cqe(pfob, mb_cq);
-
-	status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, mb_cq);
-	if (status)
-		status = BE_NOT_OK;
-	return status;
-}
-
-struct be_mcc_wrb_context *
-_be_mcc_allocate_wrb_context(struct be_function_object *pfob)
-{
-	struct be_mcc_wrb_context *context = NULL;
-	unsigned long irq;
-
-	spin_lock_irqsave(&pfob->mcc_context_lock, irq);
-
-	if (!pfob->mailbox.default_context_allocated) {
-		/* Use the single default context that we
-		 * always have allocated. */
-		pfob->mailbox.default_context_allocated = true;
-		context = &pfob->mailbox.default_context;
-	} else if (pfob->mcc) {
-		/* Get a context from the free list. If any are available. */
-		if (!list_empty(&pfob->mcc->wrb_context.list_head)) {
-			context = list_first_entry(
-				&pfob->mcc->wrb_context.list_head,
-					 struct be_mcc_wrb_context, next);
-		}
-	}
-
-	spin_unlock_irqrestore(&pfob->mcc_context_lock, irq);
-
-	return context;
-}
-
-void
-_be_mcc_free_wrb_context(struct be_function_object *pfob,
-			 struct be_mcc_wrb_context *context)
-{
-	unsigned long irq;
-
-	ASSERT(context);
-	/*
-	 * Zero during free to try and catch any bugs where the context
-	 * is accessed after a free.
-	 */
-	memset(context, 0, sizeof(context));
-
-	spin_lock_irqsave(&pfob->mcc_context_lock, irq);
-
-	if (context == &pfob->mailbox.default_context) {
-		/* Free the default context. */
-		ASSERT(pfob->mailbox.default_context_allocated);
-		pfob->mailbox.default_context_allocated = false;
-	} else {
-		/* Add to free list. */
-		ASSERT(pfob->mcc);
-		list_add_tail(&context->next,
-				&pfob->mcc->wrb_context.list_head);
-	}
-
-	spin_unlock_irqrestore(&pfob->mcc_context_lock, irq);
-}
-
-int
-be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object,
-		mcc_async_event_callback cb, void *cb_context)
-{
-	/* Lock against anyone trying to change the callback/context pointers
-	 * while being used. */
-	spin_lock_irqsave(&mcc_object->parent_function->cq_lock,
-		mcc_object->parent_function->cq_irq);
-
-	/* Assign the async callback. */
-	mcc_object->async_context = cb_context;
-	mcc_object->async_cb = cb;
-
-	spin_unlock_irqrestore(&mcc_object->parent_function->cq_lock,
-					mcc_object->parent_function->cq_irq);
-
-	return BE_SUCCESS;
-}
-
-#define MPU_EP_CONTROL 0
-#define MPU_EP_SEMAPHORE 0xac
-
-/*
- *-------------------------------------------------------------------
- * Function: be_wait_for_POST_complete
- *   Waits until the BladeEngine POST completes (either in error or success).
- * pfob -
- * return status   - BE_SUCCESS (0) on success. Negative error code on failure.
- *-------------------------------------------------------------------
- */
-static int be_wait_for_POST_complete(struct be_function_object *pfob)
-{
-	struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status;
-	int s;
-	u32 post_error, post_stage;
-
-	const u32 us_per_loop = 1000;	/* 1000us */
-	const u32 print_frequency_loops = 1000000 / us_per_loop;
-	const u32 max_loops = 60 * print_frequency_loops;
-	u32 loops = 0;
-
-	/*
-	 * Wait for arm fw indicating it is done or a fatal error happened.
-	 * Note: POST can take some time to complete depending on configuration
-	 * settings (consider ARM attempts to acquire an IP address
-	 * over DHCP!!!).
-	 *
-	 */
-	do {
-		status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE);
-		post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT,
-						error, &status);
-		post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT,
-						stage, &status);
-		if (0 == (loops % print_frequency_loops)) {
-			/* Print current status */
-			TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)",
-				status.dw[0], post_stage);
-		}
-		udelay(us_per_loop);
-	} while ((post_error != 1) &&
-		 (post_stage != POST_STAGE_ARMFW_READY) &&
-		 (++loops < max_loops));
-
-	if (post_error == 1) {
-		TRACE(DL_ERR, "POST error! Status = 0x%x (stage = 0x%x)",
-		      status.dw[0], post_stage);
-		s = BE_NOT_OK;
-	} else if (post_stage != POST_STAGE_ARMFW_READY) {
-		TRACE(DL_ERR, "POST time-out! Status = 0x%x (stage = 0x%x)",
-		      status.dw[0], post_stage);
-		s = BE_NOT_OK;
-	} else {
-		s = BE_SUCCESS;
-	}
-	return s;
-}
-
-/*
- *-------------------------------------------------------------------
- * Function: be_kickoff_and_wait_for_POST
- *   Interacts with the BladeEngine management processor to initiate POST, and
- *   subsequently waits until POST completes (either in error or success).
- *   The caller must acquire the reset semaphore before initiating POST
- *   to prevent multiple drivers interacting with the management processor.
- *   Once POST is complete the caller must release the reset semaphore.
- *   Callers who only want to wait for POST complete may call
- *   be_wait_for_POST_complete.
- * pfob -
- * return status   - BE_SUCCESS (0) on success. Negative error code on failure.
- *-------------------------------------------------------------------
- */
-static int
-be_kickoff_and_wait_for_POST(struct be_function_object *pfob)
-{
-	struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status;
-	int s;
-
-	const u32 us_per_loop = 1000;	/* 1000us */
-	const u32 print_frequency_loops = 1000000 / us_per_loop;
-	const u32 max_loops = 5 * print_frequency_loops;
-	u32 loops = 0;
-	u32 post_error, post_stage;
-
-	/* Wait for arm fw awaiting host ready or a fatal error happened. */
-	TRACE(DL_INFO, "Wait for BladeEngine ready to POST");
-	do {
-		status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE);
-		post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT,
-						error, &status);
-		post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT,
-						stage, &status);
-		if (0 == (loops % print_frequency_loops)) {
-			/* Print current status */
-			TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)",
-			      status.dw[0], post_stage);
-		}
-		udelay(us_per_loop);
-	} while ((post_error != 1) &&
-		 (post_stage < POST_STAGE_AWAITING_HOST_RDY) &&
-		 (++loops < max_loops));
-
-	if (post_error == 1) {
-		TRACE(DL_ERR, "Pre-POST error! Status = 0x%x (stage = 0x%x)",
-		      status.dw[0], post_stage);
-		s = BE_NOT_OK;
-	} else if (post_stage == POST_STAGE_AWAITING_HOST_RDY) {
-		iowrite32(POST_STAGE_HOST_RDY, pfob->csr_va + MPU_EP_SEMAPHORE);
-
-		/* Wait for POST to complete */
-		s = be_wait_for_POST_complete(pfob);
-	} else {
-		/*
-		 * Either a timeout waiting for host ready signal or POST has
-		 * moved ahead without requiring a host ready signal.
-		 * Might as well give POST a chance to complete
-		 * (or timeout again).
-		 */
-		s = be_wait_for_POST_complete(pfob);
-	}
-	return s;
-}
-
-/*
- *-------------------------------------------------------------------
- * Function: be_pci_soft_reset
- *   This function is called to issue a BladeEngine soft reset.
- *   Callers should acquire the soft reset semaphore before calling this
- *   function. Additionaly, callers should ensure they cannot be pre-empted
- *   while the routine executes. Upon completion of this routine, callers
- *   should release the reset semaphore. This routine implicitly waits
- *   for BladeEngine POST to complete.
- * pfob -
- * return status   - BE_SUCCESS (0) on success. Negative error code on failure.
- *-------------------------------------------------------------------
- */
-int be_pci_soft_reset(struct be_function_object *pfob)
-{
-	struct PCICFG_SOFT_RESET_CSR_AMAP soft_reset;
-	struct PCICFG_ONLINE0_CSR_AMAP pciOnline0;
-	struct PCICFG_ONLINE1_CSR_AMAP pciOnline1;
-	struct EP_CONTROL_CSR_AMAP epControlCsr;
-	int status = BE_SUCCESS;
-	u32 i, soft_reset_bit;
-
-	TRACE(DL_NOTE, "PCI reset...");
-
-	/* Issue soft reset #1 to get BladeEngine into a known state. */
-	soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset);
-	AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1);
-	PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]);
-	/*
-	 * wait til soft reset is deasserted - hardware
-	 * deasserts after some time.
-	 */
-	i = 0;
-	do {
-		udelay(50);
-		soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset);
-		soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR,
-					softreset, soft_reset.dw);
-	} while (soft_reset_bit  && (i++ < 1024));
-	if (soft_reset_bit != 0) {
-		TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected.");
-		status = BE_NOT_OK;
-		goto Error_label;
-	}
-	/* Mask everything  */
-	PCICFG0_WRITE(pfob, ue_status_low_mask, 0xFFFFFFFF);
-	PCICFG0_WRITE(pfob, ue_status_hi_mask, 0xFFFFFFFF);
-	/*
-	 * Set everything offline except MPU IRAM (it is offline with
-	 * the soft-reset, but soft-reset does not reset the PCICFG registers!)
-	 */
-	pciOnline0.dw[0] = 0;
-	pciOnline1.dw[0] = 0;
-	AMAP_SET_BITS_PTR(PCICFG_ONLINE1_CSR, mpu_iram_online,
-				pciOnline1.dw, 1);
-	PCICFG0_WRITE(pfob, online0, pciOnline0.dw[0]);
-	PCICFG0_WRITE(pfob, online1, pciOnline1.dw[0]);
-
-	udelay(20000);
-
-	/* Issue soft reset #2. */
-	AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1);
-	PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]);
-	/*
-	 * wait til soft reset is deasserted - hardware
-	 * deasserts after some time.
-	 */
-	i = 0;
-	do {
-		udelay(50);
-		soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset);
-		soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR,
-					softreset, soft_reset.dw);
-	} while (soft_reset_bit  && (i++ < 1024));
-	if (soft_reset_bit != 0) {
-		TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected.");
-		status = BE_NOT_OK;
-		goto Error_label;
-	}
-
-
-	udelay(20000);
-
-	/* Take MPU out of reset. */
-
-	epControlCsr.dw[0] = ioread32(pfob->csr_va + MPU_EP_CONTROL);
-	AMAP_SET_BITS_PTR(EP_CONTROL_CSR, CPU_reset, &epControlCsr, 0);
-	iowrite32((u32)epControlCsr.dw[0], pfob->csr_va + MPU_EP_CONTROL);
-
-	/* Kickoff BE POST and wait for completion */
-	status = be_kickoff_and_wait_for_POST(pfob);
-
-Error_label:
-	return status;
-}
-
-
-/*
- *-------------------------------------------------------------------
- * Function: be_pci_reset_required
- *   This private function is called to detect if a host entity is
- *   required to issue a PCI soft reset and subsequently drive
- *   BladeEngine POST. Scenarios where this is required:
- *   1) BIOS-less configuration
- *   2) Hot-swap/plug/power-on
- * pfob -
- * return   true if a reset is required, false otherwise
- *-------------------------------------------------------------------
- */
-static bool be_pci_reset_required(struct be_function_object *pfob)
-{
-	struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status;
-	bool do_reset = false;
-	u32 post_error, post_stage;
-
-	/*
-	 * Read the POST status register
-	 */
-	status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE);
-	post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, error,
-								&status);
-	post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, stage,
-								&status);
-	if (post_stage <= POST_STAGE_AWAITING_HOST_RDY) {
-		/*
-		 * If BladeEngine is waiting for host ready indication,
-		 * we want to do a PCI reset.
-		 */
-		do_reset = true;
-	}
-
-	return do_reset;
-}
-
-/*
- *-------------------------------------------------------------------
- * Function: be_drive_POST
- *   This function is called to drive BladeEngine POST. The
- *   caller should ensure they cannot be pre-empted while this routine executes.
- * pfob -
- * return status   - BE_SUCCESS (0) on success. Negative error code on failure.
- *-------------------------------------------------------------------
- */
-int be_drive_POST(struct be_function_object *pfob)
-{
-	int status;
-
-	if (false != be_pci_reset_required(pfob)) {
-		/* PCI reset is needed (implicitly starts and waits for POST) */
-		status = be_pci_soft_reset(pfob);
-	} else {
-		/* No PCI reset is needed, start POST */
-		status = be_kickoff_and_wait_for_POST(pfob);
-	}
-
-	return status;
-}
diff --git a/drivers/staging/benet/mpu.h b/drivers/staging/benet/mpu.h
deleted file mode 100644
index 41f3f87..0000000
--- a/drivers/staging/benet/mpu.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __mpu_amap_h__
-#define __mpu_amap_h__
-#include "ep.h"
-
-/* Provide control parameters for the Managment Processor Unit. */
-struct BE_MPU_CSRMAP_AMAP {
-	struct BE_EP_CSRMAP_AMAP ep;
-	u8 rsvd0[128];	/* DWORD 64 */
-	u8 rsvd1[32];	/* DWORD 68 */
-	u8 rsvd2[192];	/* DWORD 69 */
-	u8 rsvd3[192];	/* DWORD 75 */
-	u8 rsvd4[32];	/* DWORD 81 */
-	u8 rsvd5[32];	/* DWORD 82 */
-	u8 rsvd6[32];	/* DWORD 83 */
-	u8 rsvd7[32];	/* DWORD 84 */
-	u8 rsvd8[32];	/* DWORD 85 */
-	u8 rsvd9[32];	/* DWORD 86 */
-	u8 rsvd10[32];	/* DWORD 87 */
-	u8 rsvd11[32];	/* DWORD 88 */
-	u8 rsvd12[32];	/* DWORD 89 */
-	u8 rsvd13[32];	/* DWORD 90 */
-	u8 rsvd14[32];	/* DWORD 91 */
-	u8 rsvd15[32];	/* DWORD 92 */
-	u8 rsvd16[32];	/* DWORD 93 */
-	u8 rsvd17[32];	/* DWORD 94 */
-	u8 rsvd18[32];	/* DWORD 95 */
-	u8 rsvd19[32];	/* DWORD 96 */
-	u8 rsvd20[32];	/* DWORD 97 */
-	u8 rsvd21[32];	/* DWORD 98 */
-	u8 rsvd22[32];	/* DWORD 99 */
-	u8 rsvd23[32];	/* DWORD 100 */
-	u8 rsvd24[32];	/* DWORD 101 */
-	u8 rsvd25[32];	/* DWORD 102 */
-	u8 rsvd26[32];	/* DWORD 103 */
-	u8 rsvd27[32];	/* DWORD 104 */
-	u8 rsvd28[96];	/* DWORD 105 */
-	u8 rsvd29[32];	/* DWORD 108 */
-	u8 rsvd30[32];	/* DWORD 109 */
-	u8 rsvd31[32];	/* DWORD 110 */
-	u8 rsvd32[32];	/* DWORD 111 */
-	u8 rsvd33[32];	/* DWORD 112 */
-	u8 rsvd34[96];	/* DWORD 113 */
-	u8 rsvd35[32];	/* DWORD 116 */
-	u8 rsvd36[32];	/* DWORD 117 */
-	u8 rsvd37[32];	/* DWORD 118 */
-	u8 rsvd38[32];	/* DWORD 119 */
-	u8 rsvd39[32];	/* DWORD 120 */
-	u8 rsvd40[32];	/* DWORD 121 */
-	u8 rsvd41[134][32];	/* DWORD 122 */
-} __packed;
-struct MPU_CSRMAP_AMAP {
-	u32 dw[256];
-};
-
-#endif /* __mpu_amap_h__ */
diff --git a/drivers/staging/benet/mpu_context.h b/drivers/staging/benet/mpu_context.h
deleted file mode 100644
index 8ce90f9..0000000
--- a/drivers/staging/benet/mpu_context.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __mpu_context_amap_h__
-#define __mpu_context_amap_h__
-
-/*
- * Management command and control ring context. The MPUs BTLR_CTRL1 CSR
- * controls the writeback behavior of the producer and consumer index values.
- */
-struct BE_MCC_RING_CONTEXT_AMAP {
-	u8 con_index[16];	/* DWORD 0 */
-	u8 ring_size[4];	/* DWORD 0 */
-	u8 cq_id[11];	/* DWORD 0 */
-	u8 rsvd0;		/* DWORD 0 */
-	u8 prod_index[16];	/* DWORD 1 */
-	u8 pdid[15];	/* DWORD 1 */
-	u8 invalid;		/* DWORD 1 */
-	u8 cmd_pending_current[7];	/* DWORD 2 */
-	u8 rsvd1[25];	/* DWORD 2 */
-	u8 hpi_port_cq_id[11];	/* DWORD 3 */
-	u8 rsvd2[5];	/* DWORD 3 */
-	u8 cmd_pending_max[7];	/* DWORD 3 */
-	u8 rsvd3[9];	/* DWORD 3 */
-} __packed;
-struct MCC_RING_CONTEXT_AMAP {
-	u32 dw[4];
-};
-
-#endif /* __mpu_context_amap_h__ */
diff --git a/drivers/staging/benet/pcicfg.h b/drivers/staging/benet/pcicfg.h
deleted file mode 100644
index 7c15684..0000000
--- a/drivers/staging/benet/pcicfg.h
+++ /dev/null
@@ -1,825 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __pcicfg_amap_h__
-#define __pcicfg_amap_h__
-
-/* Vendor and Device ID Register. */
-struct BE_PCICFG_ID_CSR_AMAP {
-	u8 vendorid[16];	/* DWORD 0 */
-	u8 deviceid[16];	/* DWORD 0 */
-} __packed;
-struct PCICFG_ID_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* IO Bar Register. */
-struct BE_PCICFG_IOBAR_CSR_AMAP {
-	u8 iospace;		/* DWORD 0 */
-	u8 rsvd0[7];	/* DWORD 0 */
-	u8 iobar[24];	/* DWORD 0 */
-} __packed;
-struct PCICFG_IOBAR_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Memory BAR 0 Register. */
-struct BE_PCICFG_MEMBAR0_CSR_AMAP {
-	u8 memspace;	/* DWORD 0 */
-	u8 type[2];		/* DWORD 0 */
-	u8 pf;		/* DWORD 0 */
-	u8 rsvd0[10];	/* DWORD 0 */
-	u8 membar0[18];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MEMBAR0_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Memory BAR 1 - Low Address Register. */
-struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP {
-	u8 memspace;	/* DWORD 0 */
-	u8 type[2];		/* DWORD 0 */
-	u8 pf;		/* DWORD 0 */
-	u8 rsvd0[13];	/* DWORD 0 */
-	u8 membar1lo[15];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MEMBAR1_LO_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Memory BAR 1 - High Address Register. */
-struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP {
-	u8 membar1hi[32];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MEMBAR1_HI_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Memory BAR 2 - Low Address Register. */
-struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP {
-	u8 memspace;	/* DWORD 0 */
-	u8 type[2];		/* DWORD 0 */
-	u8 pf;		/* DWORD 0 */
-	u8 rsvd0[17];	/* DWORD 0 */
-	u8 membar2lo[11];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MEMBAR2_LO_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Memory BAR 2 - High Address Register. */
-struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP {
-	u8 membar2hi[32];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MEMBAR2_HI_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Subsystem Vendor and ID (Function 0) Register. */
-struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP {
-	u8 subsys_vendor_id[16];	/* DWORD 0 */
-	u8 subsys_id[16];	/* DWORD 0 */
-} __packed;
-struct PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Subsystem Vendor and ID (Function 1) Register. */
-struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP {
-	u8 subsys_vendor_id[16];	/* DWORD 0 */
-	u8 subsys_id[16];	/* DWORD 0 */
-} __packed;
-struct PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Semaphore Register. */
-struct BE_PCICFG_SEMAPHORE_CSR_AMAP {
-	u8 locked;		/* DWORD 0 */
-	u8 rsvd0[31];	/* DWORD 0 */
-} __packed;
-struct PCICFG_SEMAPHORE_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Soft Reset Register. */
-struct BE_PCICFG_SOFT_RESET_CSR_AMAP {
-	u8 rsvd0[7];	/* DWORD 0 */
-	u8 softreset;	/* DWORD 0 */
-	u8 rsvd1[16];	/* DWORD 0 */
-	u8 nec_ll_rcvdetect_i[8];	/* DWORD 0 */
-} __packed;
-struct PCICFG_SOFT_RESET_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Unrecoverable Error Status (Low) Register. Each bit corresponds to
- * an internal Unrecoverable Error.  These are set by hardware and may be
- * cleared by writing a one to the respective bit(s) to be cleared.  Any
- * bit being set that is also unmasked will result in Unrecoverable Error
- * interrupt notification to the host CPU and/or Server Management chip
- * and the transitioning of BladeEngine to an Offline state.
- */
-struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP {
-	u8 cev_ue_status;	/* DWORD 0 */
-	u8 ctx_ue_status;	/* DWORD 0 */
-	u8 dbuf_ue_status;	/* DWORD 0 */
-	u8 erx_ue_status;	/* DWORD 0 */
-	u8 host_ue_status;	/* DWORD 0 */
-	u8 mpu_ue_status;	/* DWORD 0 */
-	u8 ndma_ue_status;	/* DWORD 0 */
-	u8 ptc_ue_status;	/* DWORD 0 */
-	u8 rdma_ue_status;	/* DWORD 0 */
-	u8 rxf_ue_status;	/* DWORD 0 */
-	u8 rxips_ue_status;	/* DWORD 0 */
-	u8 rxulp0_ue_status;	/* DWORD 0 */
-	u8 rxulp1_ue_status;	/* DWORD 0 */
-	u8 rxulp2_ue_status;	/* DWORD 0 */
-	u8 tim_ue_status;	/* DWORD 0 */
-	u8 tpost_ue_status;	/* DWORD 0 */
-	u8 tpre_ue_status;	/* DWORD 0 */
-	u8 txips_ue_status;	/* DWORD 0 */
-	u8 txulp0_ue_status;	/* DWORD 0 */
-	u8 txulp1_ue_status;	/* DWORD 0 */
-	u8 uc_ue_status;	/* DWORD 0 */
-	u8 wdma_ue_status;	/* DWORD 0 */
-	u8 txulp2_ue_status;	/* DWORD 0 */
-	u8 host1_ue_status;	/* DWORD 0 */
-	u8 p0_ob_link_ue_status;	/* DWORD 0 */
-	u8 p1_ob_link_ue_status;	/* DWORD 0 */
-	u8 host_gpio_ue_status;	/* DWORD 0 */
-	u8 mbox_netw_ue_status;	/* DWORD 0 */
-	u8 mbox_stor_ue_status;	/* DWORD 0 */
-	u8 axgmac0_ue_status;	/* DWORD 0 */
-	u8 axgmac1_ue_status;	/* DWORD 0 */
-	u8 mpu_intpend_ue_status;	/* DWORD 0 */
-} __packed;
-struct PCICFG_UE_STATUS_LOW_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Unrecoverable Error Status (High) Register. Each bit corresponds to
- * an internal Unrecoverable Error.  These are set by hardware and may be
- * cleared by writing a one to the respective bit(s) to be cleared.  Any
- * bit being set that is also unmasked will result in Unrecoverable Error
- * interrupt notification to the host CPU and/or Server Management chip;
- * and the transitioning of BladeEngine to an Offline state.
- */
-struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP {
-	u8 jtag_ue_status;	/* DWORD 0 */
-	u8 lpcmemhost_ue_status;	/* DWORD 0 */
-	u8 mgmt_mac_ue_status;	/* DWORD 0 */
-	u8 mpu_iram_ue_status;	/* DWORD 0 */
-	u8 pcs0online_ue_status;	/* DWORD 0 */
-	u8 pcs1online_ue_status;	/* DWORD 0 */
-	u8 pctl0_ue_status;	/* DWORD 0 */
-	u8 pctl1_ue_status;	/* DWORD 0 */
-	u8 pmem_ue_status;	/* DWORD 0 */
-	u8 rr_ue_status;	/* DWORD 0 */
-	u8 rxpp_ue_status;	/* DWORD 0 */
-	u8 txpb_ue_status;	/* DWORD 0 */
-	u8 txp_ue_status;	/* DWORD 0 */
-	u8 xaui_ue_status;	/* DWORD 0 */
-	u8 arm_ue_status;	/* DWORD 0 */
-	u8 ipc_ue_status;	/* DWORD 0 */
-	u8 rsvd0[16];	/* DWORD 0 */
-} __packed;
-struct PCICFG_UE_STATUS_HI_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Unrecoverable Error Mask (Low) Register. Each bit, when set to one,
- * will mask the associated Unrecoverable  Error status bit from notification
- * of Unrecoverable Error to the host CPU and/or Server Managment chip and the
- * transitioning of all BladeEngine units to an Offline state.
- */
-struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP {
-	u8 cev_ue_mask;	/* DWORD 0 */
-	u8 ctx_ue_mask;	/* DWORD 0 */
-	u8 dbuf_ue_mask;	/* DWORD 0 */
-	u8 erx_ue_mask;	/* DWORD 0 */
-	u8 host_ue_mask;	/* DWORD 0 */
-	u8 mpu_ue_mask;	/* DWORD 0 */
-	u8 ndma_ue_mask;	/* DWORD 0 */
-	u8 ptc_ue_mask;	/* DWORD 0 */
-	u8 rdma_ue_mask;	/* DWORD 0 */
-	u8 rxf_ue_mask;	/* DWORD 0 */
-	u8 rxips_ue_mask;	/* DWORD 0 */
-	u8 rxulp0_ue_mask;	/* DWORD 0 */
-	u8 rxulp1_ue_mask;	/* DWORD 0 */
-	u8 rxulp2_ue_mask;	/* DWORD 0 */
-	u8 tim_ue_mask;	/* DWORD 0 */
-	u8 tpost_ue_mask;	/* DWORD 0 */
-	u8 tpre_ue_mask;	/* DWORD 0 */
-	u8 txips_ue_mask;	/* DWORD 0 */
-	u8 txulp0_ue_mask;	/* DWORD 0 */
-	u8 txulp1_ue_mask;	/* DWORD 0 */
-	u8 uc_ue_mask;	/* DWORD 0 */
-	u8 wdma_ue_mask;	/* DWORD 0 */
-	u8 txulp2_ue_mask;	/* DWORD 0 */
-	u8 host1_ue_mask;	/* DWORD 0 */
-	u8 p0_ob_link_ue_mask;	/* DWORD 0 */
-	u8 p1_ob_link_ue_mask;	/* DWORD 0 */
-	u8 host_gpio_ue_mask;	/* DWORD 0 */
-	u8 mbox_netw_ue_mask;	/* DWORD 0 */
-	u8 mbox_stor_ue_mask;	/* DWORD 0 */
-	u8 axgmac0_ue_mask;	/* DWORD 0 */
-	u8 axgmac1_ue_mask;	/* DWORD 0 */
-	u8 mpu_intpend_ue_mask;	/* DWORD 0 */
-} __packed;
-struct PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Unrecoverable Error Mask (High) Register. Each bit, when set to one,
- * will mask the associated Unrecoverable Error status bit from notification
- * of Unrecoverable Error to the host CPU and/or Server Managment chip and the
- * transitioning of all BladeEngine units to an Offline state.
- */
-struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP {
-	u8 jtag_ue_mask;	/* DWORD 0 */
-	u8 lpcmemhost_ue_mask;	/* DWORD 0 */
-	u8 mgmt_mac_ue_mask;	/* DWORD 0 */
-	u8 mpu_iram_ue_mask;	/* DWORD 0 */
-	u8 pcs0online_ue_mask;	/* DWORD 0 */
-	u8 pcs1online_ue_mask;	/* DWORD 0 */
-	u8 pctl0_ue_mask;	/* DWORD 0 */
-	u8 pctl1_ue_mask;	/* DWORD 0 */
-	u8 pmem_ue_mask;	/* DWORD 0 */
-	u8 rr_ue_mask;	/* DWORD 0 */
-	u8 rxpp_ue_mask;	/* DWORD 0 */
-	u8 txpb_ue_mask;	/* DWORD 0 */
-	u8 txp_ue_mask;	/* DWORD 0 */
-	u8 xaui_ue_mask;	/* DWORD 0 */
-	u8 arm_ue_mask;	/* DWORD 0 */
-	u8 ipc_ue_mask;	/* DWORD 0 */
-	u8 rsvd0[16];	/* DWORD 0 */
-} __packed;
-struct PCICFG_UE_STATUS_HI_MASK_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Online Control Register 0. This register controls various units within
- * BladeEngine being in an Online or Offline state.
- */
-struct BE_PCICFG_ONLINE0_CSR_AMAP {
-	u8 cev_online;	/* DWORD 0 */
-	u8 ctx_online;	/* DWORD 0 */
-	u8 dbuf_online;	/* DWORD 0 */
-	u8 erx_online;	/* DWORD 0 */
-	u8 host_online;	/* DWORD 0 */
-	u8 mpu_online;	/* DWORD 0 */
-	u8 ndma_online;	/* DWORD 0 */
-	u8 ptc_online;	/* DWORD 0 */
-	u8 rdma_online;	/* DWORD 0 */
-	u8 rxf_online;	/* DWORD 0 */
-	u8 rxips_online;	/* DWORD 0 */
-	u8 rxulp0_online;	/* DWORD 0 */
-	u8 rxulp1_online;	/* DWORD 0 */
-	u8 rxulp2_online;	/* DWORD 0 */
-	u8 tim_online;	/* DWORD 0 */
-	u8 tpost_online;	/* DWORD 0 */
-	u8 tpre_online;	/* DWORD 0 */
-	u8 txips_online;	/* DWORD 0 */
-	u8 txulp0_online;	/* DWORD 0 */
-	u8 txulp1_online;	/* DWORD 0 */
-	u8 uc_online;	/* DWORD 0 */
-	u8 wdma_online;	/* DWORD 0 */
-	u8 txulp2_online;	/* DWORD 0 */
-	u8 host1_online;	/* DWORD 0 */
-	u8 p0_ob_link_online;	/* DWORD 0 */
-	u8 p1_ob_link_online;	/* DWORD 0 */
-	u8 host_gpio_online;	/* DWORD 0 */
-	u8 mbox_netw_online;	/* DWORD 0 */
-	u8 mbox_stor_online;	/* DWORD 0 */
-	u8 axgmac0_online;	/* DWORD 0 */
-	u8 axgmac1_online;	/* DWORD 0 */
-	u8 mpu_intpend_online;	/* DWORD 0 */
-} __packed;
-struct PCICFG_ONLINE0_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Online Control Register 1. This register controls various units within
- * BladeEngine being in an Online or Offline state.
- */
-struct BE_PCICFG_ONLINE1_CSR_AMAP {
-	u8 jtag_online;	/* DWORD 0 */
-	u8 lpcmemhost_online;	/* DWORD 0 */
-	u8 mgmt_mac_online;	/* DWORD 0 */
-	u8 mpu_iram_online;	/* DWORD 0 */
-	u8 pcs0online_online;	/* DWORD 0 */
-	u8 pcs1online_online;	/* DWORD 0 */
-	u8 pctl0_online;	/* DWORD 0 */
-	u8 pctl1_online;	/* DWORD 0 */
-	u8 pmem_online;	/* DWORD 0 */
-	u8 rr_online;	/* DWORD 0 */
-	u8 rxpp_online;	/* DWORD 0 */
-	u8 txpb_online;	/* DWORD 0 */
-	u8 txp_online;	/* DWORD 0 */
-	u8 xaui_online;	/* DWORD 0 */
-	u8 arm_online;	/* DWORD 0 */
-	u8 ipc_online;	/* DWORD 0 */
-	u8 rsvd0[16];	/* DWORD 0 */
-} __packed;
-struct PCICFG_ONLINE1_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Host Timer Register. */
-struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP {
-	u8 hosttimer[24];	/* DWORD 0 */
-	u8 hostintr;	/* DWORD 0 */
-	u8 rsvd0[7];	/* DWORD 0 */
-} __packed;
-struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* Scratchpad Register (for software use). */
-struct BE_PCICFG_SCRATCHPAD_CSR_AMAP {
-	u8 scratchpad[32];	/* DWORD 0 */
-} __packed;
-struct PCICFG_SCRATCHPAD_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express Capabilities Register. */
-struct BE_PCICFG_PCIE_CAP_CSR_AMAP {
-	u8 capid[8];	/* DWORD 0 */
-	u8 nextcap[8];	/* DWORD 0 */
-	u8 capver[4];	/* DWORD 0 */
-	u8 devport[4];	/* DWORD 0 */
-	u8 rsvd0[6];	/* DWORD 0 */
-	u8 rsvd1[2];	/* DWORD 0 */
-} __packed;
-struct PCICFG_PCIE_CAP_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express Device Capabilities Register. */
-struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP {
-	u8 payload[3];	/* DWORD 0 */
-	u8 rsvd0[3];	/* DWORD 0 */
-	u8 lo_lat[3];	/* DWORD 0 */
-	u8 l1_lat[3];	/* DWORD 0 */
-	u8 rsvd1[3];	/* DWORD 0 */
-	u8 rsvd2[3];	/* DWORD 0 */
-	u8 pwr_value[8];	/* DWORD 0 */
-	u8 pwr_scale[2];	/* DWORD 0 */
-	u8 rsvd3[4];	/* DWORD 0 */
-} __packed;
-struct PCICFG_PCIE_DEVCAP_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express Device Control/Status Registers. */
-struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP {
-	u8 CorrErrReportEn;	/* DWORD 0 */
-	u8 NonFatalErrReportEn;	/* DWORD 0 */
-	u8 FatalErrReportEn;	/* DWORD 0 */
-	u8 UnsuppReqReportEn;	/* DWORD 0 */
-	u8 EnableRelaxOrder;	/* DWORD 0 */
-	u8 Max_Payload_Size[3];	/* DWORD 0 */
-	u8 ExtendTagFieldEnable;	/* DWORD 0 */
-	u8 PhantomFnEnable;	/* DWORD 0 */
-	u8 AuxPwrPMEnable;	/* DWORD 0 */
-	u8 EnableNoSnoop;	/* DWORD 0 */
-	u8 Max_Read_Req_Size[3];	/* DWORD 0 */
-	u8 rsvd0;		/* DWORD 0 */
-	u8 CorrErrDetect;	/* DWORD 0 */
-	u8 NonFatalErrDetect;	/* DWORD 0 */
-	u8 FatalErrDetect;	/* DWORD 0 */
-	u8 UnsuppReqDetect;	/* DWORD 0 */
-	u8 AuxPwrDetect;	/* DWORD 0 */
-	u8 TransPending;	/* DWORD 0 */
-	u8 rsvd1[10];	/* DWORD 0 */
-} __packed;
-struct PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express Link Capabilities Register. */
-struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP {
-	u8 MaxLinkSpeed[4];	/* DWORD 0 */
-	u8 MaxLinkWidth[6];	/* DWORD 0 */
-	u8 ASPMSupport[2];	/* DWORD 0 */
-	u8 L0sExitLat[3];	/* DWORD 0 */
-	u8 L1ExitLat[3];	/* DWORD 0 */
-	u8 rsvd0[6];	/* DWORD 0 */
-	u8 PortNum[8];	/* DWORD 0 */
-} __packed;
-struct PCICFG_PCIE_LINK_CAP_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express Link Status Register. */
-struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP {
-	u8 ASPMCtl[2];	/* DWORD 0 */
-	u8 rsvd0;		/* DWORD 0 */
-	u8 ReadCmplBndry;	/* DWORD 0 */
-	u8 LinkDisable;	/* DWORD 0 */
-	u8 RetrainLink;	/* DWORD 0 */
-	u8 CommonClkConfig;	/* DWORD 0 */
-	u8 ExtendSync;	/* DWORD 0 */
-	u8 rsvd1[8];	/* DWORD 0 */
-	u8 LinkSpeed[4];	/* DWORD 0 */
-	u8 NegLinkWidth[6];	/* DWORD 0 */
-	u8 LinkTrainErr;	/* DWORD 0 */
-	u8 LinkTrain;	/* DWORD 0 */
-	u8 SlotClkConfig;	/* DWORD 0 */
-	u8 rsvd2[3];	/* DWORD 0 */
-} __packed;
-struct PCICFG_PCIE_LINK_STATUS_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express MSI Configuration Register. */
-struct BE_PCICFG_MSI_CSR_AMAP {
-	u8 capid[8];	/* DWORD 0 */
-	u8 nextptr[8];	/* DWORD 0 */
-	u8 tablesize[11];	/* DWORD 0 */
-	u8 rsvd0[3];	/* DWORD 0 */
-	u8 funcmask;	/* DWORD 0 */
-	u8 en;		/* DWORD 0 */
-} __packed;
-struct PCICFG_MSI_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* MSI-X Table Offset Register. */
-struct BE_PCICFG_MSIX_TABLE_CSR_AMAP {
-	u8 tablebir[3];	/* DWORD 0 */
-	u8 offset[29];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MSIX_TABLE_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* MSI-X PBA Offset Register. */
-struct BE_PCICFG_MSIX_PBA_CSR_AMAP {
-	u8 pbabir[3];	/* DWORD 0 */
-	u8 offset[29];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MSIX_PBA_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express MSI-X Message Vector Control Register. */
-struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP {
-	u8 vector_control;	/* DWORD 0 */
-	u8 rsvd0[31];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express MSI-X Message Data Register. */
-struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP {
-	u8 data[16];	/* DWORD 0 */
-	u8 rsvd0[16];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MSIX_MSG_DATA_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express MSI-X Message Address Register - High Part. */
-struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP {
-	u8 addr[32];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP {
-	u32 dw[1];
-};
-
-/* PCI Express MSI-X Message Address Register - Low Part. */
-struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP {
-	u8 rsvd0[2];	/* DWORD 0 */
-	u8 addr[30];	/* DWORD 0 */
-} __packed;
-struct PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP {
-	u32 dw[1];
-};
-
-struct BE_PCICFG_ANON_18_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-} __packed;
-struct PCICFG_ANON_18_RSVD_AMAP {
-	u32 dw[1];
-};
-
-struct BE_PCICFG_ANON_19_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-} __packed;
-struct PCICFG_ANON_19_RSVD_AMAP {
-	u32 dw[1];
-};
-
-struct BE_PCICFG_ANON_20_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-	u8 rsvd1[25][32];	/* DWORD 1 */
-} __packed;
-struct PCICFG_ANON_20_RSVD_AMAP {
-	u32 dw[26];
-};
-
-struct BE_PCICFG_ANON_21_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-	u8 rsvd1[1919][32];	/* DWORD 1 */
-} __packed;
-struct PCICFG_ANON_21_RSVD_AMAP {
-	u32 dw[1920];
-};
-
-struct BE_PCICFG_ANON_22_MESSAGE_AMAP {
-	struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl;
-	struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data;
-	struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi;
-	struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low;
-} __packed;
-struct PCICFG_ANON_22_MESSAGE_AMAP {
-	u32 dw[4];
-};
-
-struct BE_PCICFG_ANON_23_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-	u8 rsvd1[895][32];	/* DWORD 1 */
-} __packed;
-struct PCICFG_ANON_23_RSVD_AMAP {
-	u32 dw[896];
-};
-
-/* These PCI Configuration Space registers are for the Storage  Function of
- * BladeEngine (Function 0). In the memory map of the registers below their
- * table,
- */
-struct BE_PCICFG0_CSRMAP_AMAP {
-	struct BE_PCICFG_ID_CSR_AMAP id;
-	u8 rsvd0[32];	/* DWORD 1 */
-	u8 rsvd1[32];	/* DWORD 2 */
-	u8 rsvd2[32];	/* DWORD 3 */
-	struct BE_PCICFG_IOBAR_CSR_AMAP iobar;
-	struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0;
-	struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo;
-	struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi;
-	struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo;
-	struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi;
-	u8 rsvd3[32];	/* DWORD 10 */
-	struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP subsystem_id;
-	u8 rsvd4[32];	/* DWORD 12 */
-	u8 rsvd5[32];	/* DWORD 13 */
-	u8 rsvd6[32];	/* DWORD 14 */
-	u8 rsvd7[32];	/* DWORD 15 */
-	struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4];
-	struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset;
-	u8 rsvd8[32];	/* DWORD 21 */
-	struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad;
-	u8 rsvd9[32];	/* DWORD 23 */
-	u8 rsvd10[32];	/* DWORD 24 */
-	u8 rsvd11[32];	/* DWORD 25 */
-	u8 rsvd12[32];	/* DWORD 26 */
-	u8 rsvd13[32];	/* DWORD 27 */
-	u8 rsvd14[2][32];	/* DWORD 28 */
-	u8 rsvd15[32];	/* DWORD 30 */
-	u8 rsvd16[32];	/* DWORD 31 */
-	u8 rsvd17[8][32];	/* DWORD 32 */
-	struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low;
-	struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi;
-	struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask;
-	struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask;
-	struct BE_PCICFG_ONLINE0_CSR_AMAP online0;
-	struct BE_PCICFG_ONLINE1_CSR_AMAP online1;
-	u8 rsvd18[32];	/* DWORD 46 */
-	u8 rsvd19[32];	/* DWORD 47 */
-	u8 rsvd20[32];	/* DWORD 48 */
-	u8 rsvd21[32];	/* DWORD 49 */
-	struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl;
-	u8 rsvd22[32];	/* DWORD 51 */
-	struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap;
-	struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap;
-	struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status;
-	struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap;
-	struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status;
-	struct BE_PCICFG_MSI_CSR_AMAP msi;
-	struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset;
-	struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset;
-	u8 rsvd23[32];	/* DWORD 60 */
-	u8 rsvd24[32];	/* DWORD 61 */
-	u8 rsvd25[32];	/* DWORD 62 */
-	u8 rsvd26[32];	/* DWORD 63 */
-	u8 rsvd27[32];	/* DWORD 64 */
-	u8 rsvd28[32];	/* DWORD 65 */
-	u8 rsvd29[32];	/* DWORD 66 */
-	u8 rsvd30[32];	/* DWORD 67 */
-	u8 rsvd31[32];	/* DWORD 68 */
-	u8 rsvd32[32];	/* DWORD 69 */
-	u8 rsvd33[32];	/* DWORD 70 */
-	u8 rsvd34[32];	/* DWORD 71 */
-	u8 rsvd35[32];	/* DWORD 72 */
-	u8 rsvd36[32];	/* DWORD 73 */
-	u8 rsvd37[32];	/* DWORD 74 */
-	u8 rsvd38[32];	/* DWORD 75 */
-	u8 rsvd39[32];	/* DWORD 76 */
-	u8 rsvd40[32];	/* DWORD 77 */
-	u8 rsvd41[32];	/* DWORD 78 */
-	u8 rsvd42[32];	/* DWORD 79 */
-	u8 rsvd43[32];	/* DWORD 80 */
-	u8 rsvd44[32];	/* DWORD 81 */
-	u8 rsvd45[32];	/* DWORD 82 */
-	u8 rsvd46[32];	/* DWORD 83 */
-	u8 rsvd47[32];	/* DWORD 84 */
-	u8 rsvd48[32];	/* DWORD 85 */
-	u8 rsvd49[32];	/* DWORD 86 */
-	u8 rsvd50[32];	/* DWORD 87 */
-	u8 rsvd51[32];	/* DWORD 88 */
-	u8 rsvd52[32];	/* DWORD 89 */
-	u8 rsvd53[32];	/* DWORD 90 */
-	u8 rsvd54[32];	/* DWORD 91 */
-	u8 rsvd55[32];	/* DWORD 92 */
-	u8 rsvd56[832];	/* DWORD 93 */
-	u8 rsvd57[32];	/* DWORD 119 */
-	u8 rsvd58[32];	/* DWORD 120 */
-	u8 rsvd59[32];	/* DWORD 121 */
-	u8 rsvd60[32];	/* DWORD 122 */
-	u8 rsvd61[32];	/* DWORD 123 */
-	u8 rsvd62[32];	/* DWORD 124 */
-	u8 rsvd63[32];	/* DWORD 125 */
-	u8 rsvd64[32];	/* DWORD 126 */
-	u8 rsvd65[32];	/* DWORD 127 */
-	u8 rsvd66[61440];	/* DWORD 128 */
-	struct BE_PCICFG_ANON_22_MESSAGE_AMAP message[32];
-	u8 rsvd67[28672];	/* DWORD 2176 */
-	u8 rsvd68[32];	/* DWORD 3072 */
-	u8 rsvd69[1023][32];	/* DWORD 3073 */
-} __packed;
-struct PCICFG0_CSRMAP_AMAP {
-	u32 dw[4096];
-};
-
-struct BE_PCICFG_ANON_24_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-} __packed;
-struct PCICFG_ANON_24_RSVD_AMAP {
-	u32 dw[1];
-};
-
-struct BE_PCICFG_ANON_25_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-} __packed;
-struct PCICFG_ANON_25_RSVD_AMAP {
-	u32 dw[1];
-};
-
-struct BE_PCICFG_ANON_26_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-} __packed;
-struct PCICFG_ANON_26_RSVD_AMAP {
-	u32 dw[1];
-};
-
-struct BE_PCICFG_ANON_27_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-	u8 rsvd1[32];	/* DWORD 1 */
-} __packed;
-struct PCICFG_ANON_27_RSVD_AMAP {
-	u32 dw[2];
-};
-
-struct BE_PCICFG_ANON_28_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-	u8 rsvd1[3][32];	/* DWORD 1 */
-} __packed;
-struct PCICFG_ANON_28_RSVD_AMAP {
-	u32 dw[4];
-};
-
-struct BE_PCICFG_ANON_29_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-	u8 rsvd1[36][32];	/* DWORD 1 */
-} __packed;
-struct PCICFG_ANON_29_RSVD_AMAP {
-	u32 dw[37];
-};
-
-struct BE_PCICFG_ANON_30_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-	u8 rsvd1[1930][32];	/* DWORD 1 */
-} __packed;
-struct PCICFG_ANON_30_RSVD_AMAP {
-	u32 dw[1931];
-};
-
-struct BE_PCICFG_ANON_31_MESSAGE_AMAP {
-	struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl;
-	struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data;
-	struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi;
-	struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low;
-} __packed;
-struct PCICFG_ANON_31_MESSAGE_AMAP {
-	u32 dw[4];
-};
-
-struct BE_PCICFG_ANON_32_RSVD_AMAP {
-	u8 rsvd0[32];	/* DWORD 0 */
-	u8 rsvd1[895][32];	/* DWORD 1 */
-} __packed;
-struct PCICFG_ANON_32_RSVD_AMAP {
-	u32 dw[896];
-};
-
-/* This PCI configuration space register map is for the  Networking Function of
- * BladeEngine (Function 1).
- */
-struct BE_PCICFG1_CSRMAP_AMAP {
-	struct BE_PCICFG_ID_CSR_AMAP id;
-	u8 rsvd0[32];	/* DWORD 1 */
-	u8 rsvd1[32];	/* DWORD 2 */
-	u8 rsvd2[32];	/* DWORD 3 */
-	struct BE_PCICFG_IOBAR_CSR_AMAP iobar;
-	struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0;
-	struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo;
-	struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi;
-	struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo;
-	struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi;
-	u8 rsvd3[32];	/* DWORD 10 */
-	struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP subsystem_id;
-	u8 rsvd4[32];	/* DWORD 12 */
-	u8 rsvd5[32];	/* DWORD 13 */
-	u8 rsvd6[32];	/* DWORD 14 */
-	u8 rsvd7[32];	/* DWORD 15 */
-	struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4];
-	struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset;
-	u8 rsvd8[32];	/* DWORD 21 */
-	struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad;
-	u8 rsvd9[32];	/* DWORD 23 */
-	u8 rsvd10[32];	/* DWORD 24 */
-	u8 rsvd11[32];	/* DWORD 25 */
-	u8 rsvd12[32];	/* DWORD 26 */
-	u8 rsvd13[32];	/* DWORD 27 */
-	u8 rsvd14[2][32];	/* DWORD 28 */
-	u8 rsvd15[32];	/* DWORD 30 */
-	u8 rsvd16[32];	/* DWORD 31 */
-	u8 rsvd17[8][32];	/* DWORD 32 */
-	struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low;
-	struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi;
-	struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask;
-	struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask;
-	struct BE_PCICFG_ONLINE0_CSR_AMAP online0;
-	struct BE_PCICFG_ONLINE1_CSR_AMAP online1;
-	u8 rsvd18[32];	/* DWORD 46 */
-	u8 rsvd19[32];	/* DWORD 47 */
-	u8 rsvd20[32];	/* DWORD 48 */
-	u8 rsvd21[32];	/* DWORD 49 */
-	struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl;
-	u8 rsvd22[32];	/* DWORD 51 */
-	struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap;
-	struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap;
-	struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status;
-	struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap;
-	struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status;
-	struct BE_PCICFG_MSI_CSR_AMAP msi;
-	struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset;
-	struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset;
-	u8 rsvd23[64];	/* DWORD 60 */
-	u8 rsvd24[32];	/* DWORD 62 */
-	u8 rsvd25[32];	/* DWORD 63 */
-	u8 rsvd26[32];	/* DWORD 64 */
-	u8 rsvd27[32];	/* DWORD 65 */
-	u8 rsvd28[32];	/* DWORD 66 */
-	u8 rsvd29[32];	/* DWORD 67 */
-	u8 rsvd30[32];	/* DWORD 68 */
-	u8 rsvd31[32];	/* DWORD 69 */
-	u8 rsvd32[32];	/* DWORD 70 */
-	u8 rsvd33[32];	/* DWORD 71 */
-	u8 rsvd34[32];	/* DWORD 72 */
-	u8 rsvd35[32];	/* DWORD 73 */
-	u8 rsvd36[32];	/* DWORD 74 */
-	u8 rsvd37[128];	/* DWORD 75 */
-	u8 rsvd38[32];	/* DWORD 79 */
-	u8 rsvd39[1184];	/* DWORD 80 */
-	u8 rsvd40[61792];	/* DWORD 117 */
-	struct BE_PCICFG_ANON_31_MESSAGE_AMAP message[32];
-	u8 rsvd41[28672];	/* DWORD 2176 */
-	u8 rsvd42[32];	/* DWORD 3072 */
-	u8 rsvd43[1023][32];	/* DWORD 3073 */
-} __packed;
-struct PCICFG1_CSRMAP_AMAP {
-	u32 dw[4096];
-};
-
-#endif /* __pcicfg_amap_h__ */
diff --git a/drivers/staging/benet/post_codes.h b/drivers/staging/benet/post_codes.h
deleted file mode 100644
index 6d1621f..0000000
--- a/drivers/staging/benet/post_codes.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __post_codes_amap_h__
-#define __post_codes_amap_h__
-
-/* --- MGMT_HBA_POST_STAGE_ENUM --- */
-#define POST_STAGE_POWER_ON_RESET   (0)	/* State after a cold or warm boot. */
-#define POST_STAGE_AWAITING_HOST_RDY (1)	/* ARM boot code awaiting a
-						go-ahed from  the host. */
-#define POST_STAGE_HOST_RDY (2)	/* Host has given go-ahed to ARM. */
-#define POST_STAGE_BE_RESET (3)	/* Host wants to reset chip, this is a  chip
-						workaround  */
-#define POST_STAGE_SEEPROM_CS_START (256)	/* SEEPROM checksum
-						test start. */
-#define POST_STAGE_SEEPROM_CS_DONE  (257)	/* SEEPROM checksum test
-							done. */
-#define POST_STAGE_DDR_CONFIG_START (512)	/* DDR configuration start. */
-#define POST_STAGE_DDR_CONFIG_DONE  (513)	/* DDR configuration done. */
-#define POST_STAGE_DDR_CALIBRATE_START  (768)	/* DDR calibration start. */
-#define POST_STAGE_DDR_CALIBRATE_DONE   (769)	/* DDR calibration done. */
-#define POST_STAGE_DDR_TEST_START   (1024)	/* DDR memory test start. */
-#define POST_STAGE_DDR_TEST_DONE    (1025)	/* DDR memory test done. */
-#define POST_STAGE_REDBOOT_INIT_START   (1536)	/* Redboot starts execution. */
-#define POST_STAGE_REDBOOT_INIT_DONE (1537)	/* Redboot done execution. */
-#define POST_STAGE_FW_IMAGE_LOAD_START (1792)	/* Firmware image load to
-							DDR start. */
-#define POST_STAGE_FW_IMAGE_LOAD_DONE   (1793)	/* Firmware image load
-							to DDR done. */
-#define POST_STAGE_ARMFW_START          (2048)	/* ARMfw runtime code
-						starts execution. */
-#define POST_STAGE_DHCP_QUERY_START     (2304)	/* DHCP server query start. */
-#define POST_STAGE_DHCP_QUERY_DONE      (2305)	/* DHCP server query done. */
-#define POST_STAGE_BOOT_TARGET_DISCOVERY_START (2560)	/* Boot Target
-						Discovery Start. */
-#define POST_STAGE_BOOT_TARGET_DISCOVERY_DONE (2561)	/* Boot Target
-						Discovery Done. */
-#define POST_STAGE_RC_OPTION_SET        (2816)	/* Remote configuration
-						option is set in  SEEPROM  */
-#define POST_STAGE_SWITCH_LINK          (2817)	/* Wait for link up on switch */
-#define POST_STAGE_SEND_ICDS_MESSAGE    (2818)	/* Send the ICDS message
-						to switch */
-#define POST_STAGE_PERFROM_TFTP         (2819)	/* Download xml using TFTP */
-#define POST_STAGE_PARSE_XML            (2820)	/* Parse XML file */
-#define POST_STAGE_DOWNLOAD_IMAGE       (2821)	/* Download IMAGE from
-						TFTP server */
-#define POST_STAGE_FLASH_IMAGE          (2822)	/* Flash the IMAGE */
-#define POST_STAGE_RC_DONE              (2823)	/* Remote configuration
-						complete */
-#define POST_STAGE_REBOOT_SYSTEM        (2824)	/* Upgrade IMAGE done,
-						reboot required */
-#define POST_STAGE_MAC_ADDRESS          (3072)	/* MAC Address Check */
-#define POST_STAGE_ARMFW_READY          (49152)	/* ARMfw is done with POST
-						and ready. */
-#define POST_STAGE_ARMFW_UE             (61440)	/* ARMfw has asserted an
-						unrecoverable error. The
-						lower 3 hex digits of the
-						stage code identify the
-						unique error code.
-						*/
-
-/* This structure defines the format of the MPU semaphore
- * register when used for POST.
- */
-struct BE_MGMT_HBA_POST_STATUS_STRUCT_AMAP {
-	u8 stage[16];	/* DWORD 0 */
-	u8 rsvd0[10];	/* DWORD 0 */
-	u8 iscsi_driver_loaded;	/* DWORD 0 */
-	u8 option_rom_installed;	/* DWORD 0 */
-	u8 iscsi_ip_conflict;	/* DWORD 0 */
-	u8 iscsi_no_ip;	/* DWORD 0 */
-	u8 backup_fw;	/* DWORD 0 */
-	u8 error;		/* DWORD 0 */
-} __packed;
-struct MGMT_HBA_POST_STATUS_STRUCT_AMAP {
-	u32 dw[1];
-};
-
-/* --- MGMT_HBA_POST_DUMMY_BITS_ENUM --- */
-#define POST_BIT_ISCSI_LOADED           (26)
-#define POST_BIT_OPTROM_INST            (27)
-#define POST_BIT_BAD_IP_ADDR            (28)
-#define POST_BIT_NO_IP_ADDR             (29)
-#define POST_BIT_BACKUP_FW              (30)
-#define POST_BIT_ERROR                  (31)
-
-/* --- MGMT_HBA_POST_DUMMY_VALUES_ENUM --- */
-#define POST_ISCSI_DRIVER_LOADED        (67108864)
-#define POST_OPTROM_INSTALLED           (134217728)
-#define POST_ISCSI_IP_ADDRESS_CONFLICT  (268435456)
-#define POST_ISCSI_NO_IP_ADDRESS        (536870912)
-#define POST_BACKUP_FW_LOADED           (1073741824)
-#define POST_FATAL_ERROR                (2147483648)
-
-#endif /* __post_codes_amap_h__ */
diff --git a/drivers/staging/benet/regmap.h b/drivers/staging/benet/regmap.h
deleted file mode 100644
index e816ba2..0000000
--- a/drivers/staging/benet/regmap.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2005 - 2008 ServerEngines
- * All 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@serverengines.com
- *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
- */
-/*
- * Autogenerated by srcgen version: 0127
- */
-#ifndef __regmap_amap_h__
-#define __regmap_amap_h__
-#include "pcicfg.h"
-#include "ep.h"
-#include "cev.h"
-#include "mpu.h"
-#include "doorbells.h"
-
-/*
- * This is the control and status register map for BladeEngine, showing
- * the relative size and offset of each sub-module. The CSR registers
- * are identical for the network and storage PCI functions. The
- * CSR map is shown below, followed by details of each block,
- * in sub-sections.  The sub-sections begin with a description
- * of CSRs that are instantiated in multiple blocks.
- */
-struct BE_BLADE_ENGINE_CSRMAP_AMAP {
-	struct BE_MPU_CSRMAP_AMAP mpu;
-	u8 rsvd0[8192];	/* DWORD 256 */
-	u8 rsvd1[8192];	/* DWORD 512 */
-	struct BE_CEV_CSRMAP_AMAP cev;
-	u8 rsvd2[8192];	/* DWORD 1024 */
-	u8 rsvd3[8192];	/* DWORD 1280 */
-	u8 rsvd4[8192];	/* DWORD 1536 */
-	u8 rsvd5[8192];	/* DWORD 1792 */
-	u8 rsvd6[8192];	/* DWORD 2048 */
-	u8 rsvd7[8192];	/* DWORD 2304 */
-	u8 rsvd8[8192];	/* DWORD 2560 */
-	u8 rsvd9[8192];	/* DWORD 2816 */
-	u8 rsvd10[8192];	/* DWORD 3072 */
-	u8 rsvd11[8192];	/* DWORD 3328 */
-	u8 rsvd12[8192];	/* DWORD 3584 */
-	u8 rsvd13[8192];	/* DWORD 3840 */
-	u8 rsvd14[8192];	/* DWORD 4096 */
-	u8 rsvd15[8192];	/* DWORD 4352 */
-	u8 rsvd16[8192];	/* DWORD 4608 */
-	u8 rsvd17[8192];	/* DWORD 4864 */
-	u8 rsvd18[8192];	/* DWORD 5120 */
-	u8 rsvd19[8192];	/* DWORD 5376 */
-	u8 rsvd20[8192];	/* DWORD 5632 */
-	u8 rsvd21[8192];	/* DWORD 5888 */
-	u8 rsvd22[8192];	/* DWORD 6144 */
-	u8 rsvd23[17152][32];	/* DWORD 6400 */
-} __packed;
-struct BLADE_ENGINE_CSRMAP_AMAP {
-	u32 dw[23552];
-};
-
-#endif /* __regmap_amap_h__ */
diff --git a/drivers/staging/go7007/snd-go7007.c b/drivers/staging/go7007/snd-go7007.c
index a7de401..cd19be6 100644
--- a/drivers/staging/go7007/snd-go7007.c
+++ b/drivers/staging/go7007/snd-go7007.c
@@ -248,10 +248,11 @@
 	spin_lock_init(&gosnd->lock);
 	gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
 	gosnd->capturing = 0;
-	gosnd->card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (gosnd->card == NULL) {
+	ret = snd_card_create(index[dev], id[dev], THIS_MODULE, 0,
+			      &gosnd->card);
+	if (ret < 0) {
 		kfree(gosnd);
-		return -ENOMEM;
+		return ret;
 	}
 	ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go,
 			&go7007_snd_device_ops);
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c
index f77f62a..e5bd447 100644
--- a/drivers/tc/tc.c
+++ b/drivers/tc/tc.c
@@ -86,7 +86,7 @@
 			       slot);
 			goto out_err;
 		}
-		sprintf(tdev->dev.bus_id, "tc%x", slot);
+		dev_set_name(&tdev->dev, "tc%x", slot);
 		tdev->bus = tbus;
 		tdev->dev.parent = &tbus->dev;
 		tdev->dev.bus = &tc_bus_type;
@@ -104,7 +104,7 @@
 		tdev->vendor[8] = 0;
 		tdev->name[8] = 0;
 
-		pr_info("%s: %s %s %s\n", tdev->dev.bus_id, tdev->vendor,
+		pr_info("%s: %s %s %s\n", dev_name(&tdev->dev), tdev->vendor,
 			tdev->name, tdev->firmware);
 
 		devsize = readb(module + offset + TC_SLOT_SIZE);
@@ -118,7 +118,7 @@
 		} else {
 			printk(KERN_ERR "%s: Cannot provide slot space "
 			       "(%dMiB required, up to %dMiB supported)\n",
-			       tdev->dev.bus_id, devsize >> 20,
+			       dev_name(&tdev->dev), devsize >> 20,
 			       max(slotsize, extslotsize) >> 20);
 			kfree(tdev);
 			goto out_err;
@@ -146,7 +146,7 @@
 		return 0;
 
 	INIT_LIST_HEAD(&tc_bus.devices);
-	strcpy(tc_bus.dev.bus_id, "tc");
+	dev_set_name(&tc_bus.dev, "tc");
 	device_register(&tc_bus.dev);
 
 	if (tc_bus.info.slot_size) {
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 04b954c..7f86534 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -58,6 +58,24 @@
 
 	  If you compile this as a module, it will be called uio_smx.
 
+config UIO_AEC
+	tristate "AEC video timestamp device"
+	depends on PCI
+	default n
+	help
+
+	  UIO driver for the Adrienne Electronics Corporation PCI time
+	  code device.
+
+	  This device differs from other UIO devices since it uses I/O
+	  ports instead of memory mapped I/O. In order to make it
+	  possible for UIO to work with this device a utility, uioport,
+	  can be used to read and write the ports:
+
+	    git clone git://ifup.org/philips/uioport.git
+
+	  If you compile this as a module, it will be called uio_aec.
+
 config UIO_SERCOS3
 	tristate "Automata Sercos III PCI card driver"
 	default n
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index e695581..5c2586d 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -3,4 +3,5 @@
 obj-$(CONFIG_UIO_PDRV)	+= uio_pdrv.o
 obj-$(CONFIG_UIO_PDRV_GENIRQ)	+= uio_pdrv_genirq.o
 obj-$(CONFIG_UIO_SMX)	+= uio_smx.o
+obj-$(CONFIG_UIO_AEC)	+= uio_aec.o
 obj-$(CONFIG_UIO_SERCOS3)	+= uio_sercos3.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 4ca85a1..03efb06 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -61,6 +61,14 @@
 };
 #define to_map(map) container_of(map, struct uio_map, kobj)
 
+static ssize_t map_name_show(struct uio_mem *mem, char *buf)
+{
+	if (unlikely(!mem->name))
+		mem->name = "";
+
+	return sprintf(buf, "%s\n", mem->name);
+}
+
 static ssize_t map_addr_show(struct uio_mem *mem, char *buf)
 {
 	return sprintf(buf, "0x%lx\n", mem->addr);
@@ -82,6 +90,8 @@
 	ssize_t (*store)(struct uio_mem *, const char *, size_t);
 };
 
+static struct map_sysfs_entry name_attribute =
+	__ATTR(name, S_IRUGO, map_name_show, NULL);
 static struct map_sysfs_entry addr_attribute =
 	__ATTR(addr, S_IRUGO, map_addr_show, NULL);
 static struct map_sysfs_entry size_attribute =
@@ -90,6 +100,7 @@
 	__ATTR(offset, S_IRUGO, map_offset_show, NULL);
 
 static struct attribute *attrs[] = {
+	&name_attribute.attr,
 	&addr_attribute.attr,
 	&size_attribute.attr,
 	&offset_attribute.attr,
@@ -133,6 +144,14 @@
 };
 #define to_portio(portio) container_of(portio, struct uio_portio, kobj)
 
+static ssize_t portio_name_show(struct uio_port *port, char *buf)
+{
+	if (unlikely(!port->name))
+		port->name = "";
+
+	return sprintf(buf, "%s\n", port->name);
+}
+
 static ssize_t portio_start_show(struct uio_port *port, char *buf)
 {
 	return sprintf(buf, "0x%lx\n", port->start);
@@ -159,6 +178,8 @@
 	ssize_t (*store)(struct uio_port *, const char *, size_t);
 };
 
+static struct portio_sysfs_entry portio_name_attribute =
+	__ATTR(name, S_IRUGO, portio_name_show, NULL);
 static struct portio_sysfs_entry portio_start_attribute =
 	__ATTR(start, S_IRUGO, portio_start_show, NULL);
 static struct portio_sysfs_entry portio_size_attribute =
@@ -167,6 +188,7 @@
 	__ATTR(porttype, S_IRUGO, portio_porttype_show, NULL);
 
 static struct attribute *portio_attrs[] = {
+	&portio_name_attribute.attr,
 	&portio_start_attribute.attr,
 	&portio_size_attribute.attr,
 	&portio_porttype_attribute.attr,
@@ -686,7 +708,8 @@
 		return -EINVAL;
 
 	requested_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-	actual_pages = (idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT;
+	actual_pages = ((idev->info->mem[mi].addr & ~PAGE_MASK)
+			+ idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT;
 	if (requested_pages > actual_pages)
 		return -EINVAL;
 
diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c
new file mode 100644
index 0000000..b7830e9
--- /dev/null
+++ b/drivers/uio/uio_aec.c
@@ -0,0 +1,175 @@
+/*
+ * uio_aec.c -- simple driver for Adrienne Electronics Corp time code PCI device
+ *
+ * Copyright (C) 2008 Brandon Philips <brandon@ifup.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License version 2 as published
+ *   by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License along
+ *   with this program; if not, write to the Free Software Foundation, Inc., 59
+ *   Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/uio_driver.h>
+
+#define PCI_VENDOR_ID_AEC 0xaecb
+#define PCI_DEVICE_ID_AEC_VITCLTC 0x6250
+
+#define INT_ENABLE_ADDR		0xFC
+#define INT_ENABLE		0x10
+#define INT_DISABLE		0x0
+
+#define INT_MASK_ADDR		0x2E
+#define INT_MASK_ALL		0x3F
+
+#define INTA_DRVR_ADDR		0xFE
+#define INTA_ENABLED_FLAG	0x08
+#define INTA_FLAG		0x01
+
+#define MAILBOX			0x0F
+
+static struct pci_device_id ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AEC, PCI_DEVICE_ID_AEC_VITCLTC), },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, ids);
+
+static irqreturn_t aectc_irq(int irq, struct uio_info *dev_info)
+{
+	void __iomem *int_flag = dev_info->priv + INTA_DRVR_ADDR;
+	unsigned char status = ioread8(int_flag);
+
+
+	if ((status & INTA_ENABLED_FLAG) && (status & INTA_FLAG)) {
+		/* application writes 0x00 to 0x2F to get next interrupt */
+		status = ioread8(dev_info->priv + MAILBOX);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static void print_board_data(struct pci_dev *pdev, struct uio_info *i)
+{
+	dev_info(&pdev->dev, "PCI-TC board vendor: %x%x number: %x%x"
+		" revision: %c%c\n",
+		ioread8(i->priv + 0x01),
+		ioread8(i->priv + 0x00),
+		ioread8(i->priv + 0x03),
+		ioread8(i->priv + 0x02),
+		ioread8(i->priv + 0x06),
+		ioread8(i->priv + 0x07));
+}
+
+static int __devinit probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct uio_info *info;
+	int ret;
+
+	info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	if (pci_enable_device(pdev))
+		goto out_free;
+
+	if (pci_request_regions(pdev, "aectc"))
+		goto out_disable;
+
+	info->name = "aectc";
+	info->port[0].start = pci_resource_start(pdev, 0);
+	if (!info->port[0].start)
+		goto out_release;
+	info->priv = pci_iomap(pdev, 0, 0);
+	if (!info->priv)
+		goto out_release;
+	info->port[0].size = pci_resource_len(pdev, 0);
+	info->port[0].porttype = UIO_PORT_GPIO;
+
+	info->version = "0.0.1";
+	info->irq = pdev->irq;
+	info->irq_flags = IRQF_SHARED;
+	info->handler = aectc_irq;
+
+	print_board_data(pdev, info);
+	ret = uio_register_device(&pdev->dev, info);
+	if (ret)
+		goto out_unmap;
+
+	iowrite32(INT_ENABLE, info->priv + INT_ENABLE_ADDR);
+	iowrite8(INT_MASK_ALL, info->priv + INT_MASK_ADDR);
+	if (!(ioread8(info->priv + INTA_DRVR_ADDR)
+			& INTA_ENABLED_FLAG))
+		dev_err(&pdev->dev, "aectc: interrupts not enabled\n");
+
+	pci_set_drvdata(pdev, info);
+
+	return 0;
+
+out_unmap:
+	pci_iounmap(pdev, info->priv);
+out_release:
+	pci_release_regions(pdev);
+out_disable:
+	pci_disable_device(pdev);
+out_free:
+	kfree(info);
+	return -ENODEV;
+}
+
+static void remove(struct pci_dev *pdev)
+{
+	struct uio_info *info = pci_get_drvdata(pdev);
+
+	/* disable interrupts */
+	iowrite8(INT_DISABLE, info->priv + INT_MASK_ADDR);
+	iowrite32(INT_DISABLE, info->priv + INT_ENABLE_ADDR);
+	/* read mailbox to ensure board drops irq */
+	ioread8(info->priv + MAILBOX);
+
+	uio_unregister_device(info);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	iounmap(info->priv);
+
+	kfree(info);
+}
+
+static struct pci_driver pci_driver = {
+	.name = "aectc",
+	.id_table = ids,
+	.probe = probe,
+	.remove = remove,
+};
+
+static int __init aectc_init(void)
+{
+	return pci_register_driver(&pci_driver);
+}
+
+static void __exit aectc_exit(void)
+{
+	pci_unregister_driver(&pci_driver);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(aectc_init);
+module_exit(aectc_exit);
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 83babb0..c6c816b 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -47,6 +47,7 @@
 	default y if CPU_SUBTYPE_SH7720
 	default y if CPU_SUBTYPE_SH7721
 	default y if CPU_SUBTYPE_SH7763
+	default y if CPU_SUBTYPE_SH7786
 	# more:
 	default PCI
 
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index b2ceb4a..89299a5 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_USB_U132_HCD)	+= host/
 obj-$(CONFIG_USB_R8A66597_HCD)	+= host/
 obj-$(CONFIG_USB_HWA_HCD)	+= host/
+obj-$(CONFIG_USB_ISP1760_HCD)	+= host/
 
 obj-$(CONFIG_USB_C67X00_HCD)	+= c67x00/
 
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 5ed4ae0..6789089 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -485,7 +485,7 @@
 			usb_err(instance->usbatm, "requested transfer size too large (%d, %d)\n",
 				wbuflen, rbuflen);
 		ret = -ENOMEM;
-		goto fail;
+		goto err;
 	}
 
 	mutex_lock(&instance->cm_serialize);
@@ -565,6 +565,7 @@
 	dbg("cm %#x", cm);
 fail:
 	mutex_unlock(&instance->cm_serialize);
+err:
 	return ret;
 }
 
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 3f3ee13..d2747a4 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -880,16 +880,19 @@
 		if (rc <= 0)
 			break;
 
-		if (usblp->flags & LP_ABORT) {
-			if (schedule_timeout(msecs_to_jiffies(5000)) == 0) {
+		if (schedule_timeout(msecs_to_jiffies(1500)) == 0) {
+			if (usblp->flags & LP_ABORT) {
 				err = usblp_check_status(usblp, err);
 				if (err == 1) {	/* Paper out */
 					rc = -ENOSPC;
 					break;
 				}
+			} else {
+				/* Prod the printer, Gentoo#251237. */
+				mutex_lock(&usblp->mut);
+				usblp_read_status(usblp, usblp->statusbuf);
+				mutex_unlock(&usblp->mut);
 			}
-		} else {
-			schedule();
 		}
 	}
 	set_current_state(TASK_RUNNING);
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 0f5c05f..c40a9b2 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -50,6 +50,7 @@
 
 static struct usb_device_id usbtmc_devices[] = {
 	{ USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), },
+	{ USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), },
 	{ 0, } /* terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, usbtmc_devices);
@@ -106,12 +107,13 @@
 {
 	struct usb_interface *intf;
 	struct usbtmc_device_data *data;
-	int retval = -ENODEV;
+	int retval = 0;
 
 	intf = usb_find_interface(&usbtmc_driver, iminor(inode));
 	if (!intf) {
 		printk(KERN_ERR KBUILD_MODNAME
 		       ": can not find device for minor %d", iminor(inode));
+		retval = -ENODEV;
 		goto exit;
 	}
 
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 6ec3817..73c108d 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -187,7 +187,7 @@
 	}
 
 	/* this isn't checking for illegal values */
-	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
 		type = "Ctrl";
 		if (speed == USB_SPEED_HIGH) 	/* uframes per NAK */
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 7513bb0..df3c539 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -104,7 +104,7 @@
 
 #define	MAX_USBFS_BUFFER_SIZE	16384
 
-static inline int connected(struct dev_state *ps)
+static int connected(struct dev_state *ps)
 {
 	return (!list_empty(&ps->list) &&
 			ps->dev->state != USB_STATE_NOTATTACHED);
@@ -248,7 +248,7 @@
 	kfree(as);
 }
 
-static inline void async_newpending(struct async *as)
+static void async_newpending(struct async *as)
 {
 	struct dev_state *ps = as->ps;
 	unsigned long flags;
@@ -258,7 +258,7 @@
 	spin_unlock_irqrestore(&ps->lock, flags);
 }
 
-static inline void async_removepending(struct async *as)
+static void async_removepending(struct async *as)
 {
 	struct dev_state *ps = as->ps;
 	unsigned long flags;
@@ -268,7 +268,7 @@
 	spin_unlock_irqrestore(&ps->lock, flags);
 }
 
-static inline struct async *async_getcompleted(struct dev_state *ps)
+static struct async *async_getcompleted(struct dev_state *ps)
 {
 	unsigned long flags;
 	struct async *as = NULL;
@@ -283,7 +283,7 @@
 	return as;
 }
 
-static inline struct async *async_getpending(struct dev_state *ps,
+static struct async *async_getpending(struct dev_state *ps,
 					     void __user *userurb)
 {
 	unsigned long flags;
@@ -302,7 +302,7 @@
 
 static void snoop_urb(struct urb *urb, void __user *userurb)
 {
-	int j;
+	unsigned j;
 	unsigned char *data = urb->transfer_buffer;
 
 	if (!usbfs_snoop)
@@ -311,9 +311,9 @@
 	dev_info(&urb->dev->dev, "direction=%s\n",
 			usb_urb_dir_in(urb) ? "IN" : "OUT");
 	dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
-	dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n",
+	dev_info(&urb->dev->dev, "transfer_buffer_length=%u\n",
 		 urb->transfer_buffer_length);
-	dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length);
+	dev_info(&urb->dev->dev, "actual_length=%u\n", urb->actual_length);
 	dev_info(&urb->dev->dev, "data: ");
 	for (j = 0; j < urb->transfer_buffer_length; ++j)
 		printk("%02x ", data[j]);
@@ -359,11 +359,6 @@
 		spin_lock_irqsave(&ps->lock, flags);
 	}
 	spin_unlock_irqrestore(&ps->lock, flags);
-	as = async_getcompleted(ps);
-	while (as) {
-		free_async(as);
-		as = async_getcompleted(ps);
-	}
 }
 
 static void destroy_async_on_interface(struct dev_state *ps,
@@ -381,7 +376,7 @@
 	destroy_async(ps, &hitlist);
 }
 
-static inline void destroy_all_async(struct dev_state *ps)
+static void destroy_all_async(struct dev_state *ps)
 {
 	destroy_async(ps, &ps->async_pending);
 }
@@ -530,7 +525,8 @@
 {
 	int ret = 0;
 
-	if (ps->dev->state != USB_STATE_ADDRESS
+	if (ps->dev->state != USB_STATE_UNAUTHENTICATED
+	 && ps->dev->state != USB_STATE_ADDRESS
 	 && ps->dev->state != USB_STATE_CONFIGURED)
 		return -EHOSTUNREACH;
 	if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype))
@@ -643,6 +639,7 @@
 	struct dev_state *ps = file->private_data;
 	struct usb_device *dev = ps->dev;
 	unsigned int ifnum;
+	struct async *as;
 
 	usb_lock_device(dev);
 
@@ -661,6 +658,12 @@
 	usb_unlock_device(dev);
 	usb_put_dev(dev);
 	put_pid(ps->disc_pid);
+
+	as = async_getcompleted(ps);
+	while (as) {
+		free_async(as);
+		as = async_getcompleted(ps);
+	}
 	kfree(ps);
 	return 0;
 }
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index e1710f2..40dee2a 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -66,7 +66,7 @@
 	struct ep_device *ep = to_ep_device(dev);
 	char *type = "unknown";
 
-	switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	switch (usb_endpoint_type(ep->desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
 		type = "Control";
 		break;
@@ -94,7 +94,7 @@
 
 	in = (ep->desc->bEndpointAddress & USB_DIR_IN);
 
-	switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	switch (usb_endpoint_type(ep->desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
 		if (ep->udev->speed == USB_SPEED_HIGH) 	/* uframes per NAK */
 			interval = ep->desc->bInterval;
@@ -131,10 +131,9 @@
 	struct ep_device *ep = to_ep_device(dev);
 	char *direction;
 
-	if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-			USB_ENDPOINT_XFER_CONTROL)
+	if (usb_endpoint_xfer_control(ep->desc))
 		direction = "both";
-	else if (ep->desc->bEndpointAddress & USB_DIR_IN)
+	else if (usb_endpoint_dir_in(ep->desc))
 		direction = "in";
 	else
 		direction = "out";
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 3c711db5..81fa850 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -279,9 +279,9 @@
  * helper routine for returning string descriptors in UTF-16LE
  * input can actually be ISO-8859-1; ASCII is its 7-bit subset
  */
-static int ascii2utf (char *s, u8 *utf, int utfmax)
+static unsigned ascii2utf(char *s, u8 *utf, int utfmax)
 {
-	int retval;
+	unsigned retval;
 
 	for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
 		*utf++ = *s++;
@@ -304,19 +304,15 @@
  * Produces either a manufacturer, product or serial number string for the
  * virtual root hub device.
  */
-static int rh_string (
-	int		id,
-	struct usb_hcd	*hcd,
-	u8		*data,
-	int		len
-) {
+static unsigned rh_string(int id, struct usb_hcd *hcd, u8 *data, unsigned len)
+{
 	char buf [100];
 
 	// language ids
 	if (id == 0) {
 		buf[0] = 4;    buf[1] = 3;	/* 4 bytes string data */
 		buf[2] = 0x09; buf[3] = 0x04;	/* MSFT-speak for "en-us" */
-		len = min (len, 4);
+		len = min_t(unsigned, len, 4);
 		memcpy (data, buf, len);
 		return len;
 
@@ -332,10 +328,7 @@
 	} else if (id == 3) {
 		snprintf (buf, sizeof buf, "%s %s %s", init_utsname()->sysname,
 			init_utsname()->release, hcd->driver->description);
-
-	// unsupported IDs --> "protocol stall"
-	} else
-		return -EPIPE;
+	}
 
 	switch (len) {		/* All cases fall through */
 	default:
@@ -360,9 +353,8 @@
 	u8		tbuf [sizeof (struct usb_hub_descriptor)]
 		__attribute__((aligned(4)));
 	const u8	*bufp = tbuf;
-	int		len = 0;
+	unsigned	len = 0;
 	int		status;
-	int		n;
 	u8		patch_wakeup = 0;
 	u8		patch_protocol = 0;
 
@@ -456,10 +448,11 @@
 				patch_wakeup = 1;
 			break;
 		case USB_DT_STRING << 8:
-			n = rh_string (wValue & 0xff, hcd, ubuf, wLength);
-			if (n < 0)
+			if ((wValue & 0xff) < 4)
+				urb->actual_length = rh_string(wValue & 0xff,
+						hcd, ubuf, wLength);
+			else /* unsupported IDs --> "protocol stall" */
 				goto error;
-			urb->actual_length = n;
 			break;
 		default:
 			goto error;
@@ -629,7 +622,7 @@
 {
 	int		retval;
 	unsigned long	flags;
-	int		len = 1 + (urb->dev->maxchild / 8);
+	unsigned	len = 1 + (urb->dev->maxchild / 8);
 
 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
 	if (hcd->status_urb || urb->transfer_buffer_length < len) {
@@ -901,7 +894,7 @@
 
 	mutex_lock(&usb_bus_list_lock);
 
-	usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
+	usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
 	retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
 	if (retval != sizeof usb_dev->descriptor) {
 		mutex_unlock(&usb_bus_list_lock);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index cd50d86..be86ae3 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -392,7 +392,7 @@
 {
 	struct usb_hub *hub = urb->context;
 	int status = urb->status;
-	int i;
+	unsigned i;
 	unsigned long bits;
 
 	switch (status) {
@@ -1305,6 +1305,7 @@
 		recursively_mark_NOTATTACHED(udev);
 	spin_unlock_irqrestore(&device_state_lock, flags);
 }
+EXPORT_SYMBOL_GPL(usb_set_device_state);
 
 /*
  * WUSB devices are simple: they have no hubs behind, so the mapping
@@ -2471,20 +2472,20 @@
 	 */
 	switch (udev->speed) {
 	case USB_SPEED_VARIABLE:	/* fixed at 512 */
-		udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512);
+		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
 		break;
 	case USB_SPEED_HIGH:		/* fixed at 64 */
-		udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
+		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
 		break;
 	case USB_SPEED_FULL:		/* 8, 16, 32, or 64 */
 		/* to determine the ep0 maxpacket size, try to read
 		 * the device descriptor to get bMaxPacketSize0 and
 		 * then correct our initial guess.
 		 */
-		udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
+		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
 		break;
 	case USB_SPEED_LOW:		/* fixed at 8 */
-		udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8);
+		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
 		break;
 	default:
 		goto fail;
@@ -3392,10 +3393,10 @@
 		udev->descriptor = descriptor;	/* for disconnect() calls */
 		goto re_enumerate;
   	}
-  
+
+	/* Restore the device's previous configuration */
 	if (!udev->actconfig)
 		goto done;
-
 	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 			USB_REQ_SET_CONFIGURATION, 0,
 			udev->actconfig->desc.bConfigurationValue, 0,
@@ -3408,16 +3409,25 @@
   	}
 	usb_set_device_state(udev, USB_STATE_CONFIGURED);
 
+	/* Put interfaces back into the same altsettings as before.
+	 * Don't bother to send the Set-Interface request for interfaces
+	 * that were already in altsetting 0; besides being unnecessary,
+	 * many devices can't handle it.  Instead just reset the host-side
+	 * endpoint state.
+	 */
 	for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 		struct usb_interface *intf = udev->actconfig->interface[i];
 		struct usb_interface_descriptor *desc;
 
-		/* set_interface resets host side toggle even
-		 * for altsetting zero.  the interface may have no driver.
-		 */
 		desc = &intf->cur_altsetting->desc;
-		ret = usb_set_interface(udev, desc->bInterfaceNumber,
-			desc->bAlternateSetting);
+		if (desc->bAlternateSetting == 0) {
+			usb_disable_interface(udev, intf, true);
+			usb_enable_interface(udev, intf, true);
+			ret = 0;
+		} else {
+			ret = usb_set_interface(udev, desc->bInterfaceNumber,
+					desc->bAlternateSetting);
+		}
 		if (ret < 0) {
 			dev_err(&udev->dev, "failed to restore interface %d "
 				"altsetting %d (error=%d)\n",
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 49e7f56..30a0690 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -59,7 +59,7 @@
 		retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
 
 		dev_dbg(&urb->dev->dev,
-			"%s timed out on ep%d%s len=%d/%d\n",
+			"%s timed out on ep%d%s len=%u/%u\n",
 			current->comm,
 			usb_endpoint_num(&urb->ep->desc),
 			usb_urb_dir_in(urb) ? "in" : "out",
@@ -804,18 +804,16 @@
 			dev_err(&dev->dev,
 				"string descriptor 0 read error: %d\n",
 				err);
-			goto errout;
 		} else if (err < 4) {
 			dev_err(&dev->dev, "string descriptor 0 too short\n");
-			err = -EINVAL;
-			goto errout;
 		} else {
-			dev->have_langid = 1;
 			dev->string_langid = tbuf[2] | (tbuf[3] << 8);
 			/* always use the first langid listed */
 			dev_dbg(&dev->dev, "default language 0x%04x\n",
 				dev->string_langid);
 		}
+
+		dev->have_langid = 1;
 	}
 
 	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
@@ -1719,7 +1717,8 @@
 	}
 	kfree(new_interfaces);
 
-	if (cp->string == NULL)
+	if (cp->string == NULL &&
+			!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
 		cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
 
 	/* Now that all the interfaces are set up, register them
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index c070b34..ab93918 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -54,6 +54,10 @@
 	{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
 	  USB_QUIRK_STRING_FETCH_255 },
 
+	/* Saitek Cyborg Gold Joystick */
+	{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
+			USB_QUIRK_CONFIG_INTF_STRINGS },
+
 	/* M-Systems Flash Disk Pioneers */
 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
 
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 4cc2456..c667891 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/usb.h>
+#include <linux/usb/quirks.h>
 #include "usb.h"
 
 /* Active configuration fields */
@@ -813,7 +814,8 @@
 	if (intf->sysfs_files_created || intf->unregistering)
 		return 0;
 
-	if (alt->string == NULL)
+	if (alt->string == NULL &&
+			!(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
 	if (alt->string)
 		retval = device_create_file(&intf->dev, &dev_attr_interface);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 58bc5e3..3376055 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -295,7 +295,7 @@
 	if (!urb || urb->hcpriv || !urb->complete)
 		return -EINVAL;
 	dev = urb->dev;
-	if ((!dev) || (dev->state < USB_STATE_DEFAULT))
+	if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
 		return -ENODEV;
 
 	/* For now, get the endpoint from the pipe.  Eventually drivers
@@ -370,7 +370,7 @@
 	}
 
 	/* the I/O buffer must be mapped/unmapped, except when length=0 */
-	if (urb->transfer_buffer_length < 0)
+	if (urb->transfer_buffer_length > INT_MAX)
 		return -EMSGSIZE;
 
 #ifdef DEBUG
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index e55fef5..770b3ea 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -254,6 +254,7 @@
 config USB_GADGET_PXA27X
 	boolean "PXA 27x"
 	depends on ARCH_PXA && PXA27x
+	select USB_OTG_UTILS
 	help
 	   Intel's PXA 27x series XScale ARM v5TE processors include
 	   an integrated full speed USB 1.1 device controller.
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index abf8192..826f3ad 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -551,7 +551,7 @@
 		dma_desc->status = AMD_ADDBITS(dma_desc->status,
 						UDC_DMA_STP_STS_BS_HOST_BUSY,
 						UDC_DMA_STP_STS_BS);
-		dma_desc->bufptr = __constant_cpu_to_le32(DMA_DONT_USE);
+		dma_desc->bufptr = cpu_to_le32(DMA_DONT_USE);
 		req->td_data = dma_desc;
 		req->td_data_last = NULL;
 		req->chain_len = 1;
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 65b03e3..c22fab1 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1017,7 +1017,7 @@
 	.bDescriptorType = USB_DT_ENDPOINT,
 	.bEndpointAddress = 0,
 	.bmAttributes = USB_ENDPOINT_XFER_CONTROL,
-	.wMaxPacketSize = __constant_cpu_to_le16(64),
+	.wMaxPacketSize = cpu_to_le16(64),
 	/* FIXME: I have no idea what to put here */
 	.bInterval = 1,
 };
@@ -1207,21 +1207,21 @@
 /* Avoid overly long expressions */
 static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq)
 {
-	if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
+	if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
 		return true;
 	return false;
 }
 
 static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq)
 {
-	if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_TEST_MODE))
+	if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE))
 		return true;
 	return false;
 }
 
 static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq)
 {
-	if (crq->wValue == __constant_cpu_to_le16(USB_ENDPOINT_HALT))
+	if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT))
 		return true;
 	return false;
 }
@@ -1239,7 +1239,7 @@
 			status = cpu_to_le16(udc->devstatus);
 		} else if (crq->bRequestType
 				== (USB_DIR_IN | USB_RECIP_INTERFACE)) {
-			status = __constant_cpu_to_le16(0);
+			status = cpu_to_le16(0);
 		} else if (crq->bRequestType
 				== (USB_DIR_IN | USB_RECIP_ENDPOINT)) {
 			struct usba_ep *target;
@@ -1250,12 +1250,12 @@
 
 			status = 0;
 			if (is_stalled(udc, target))
-				status |= __constant_cpu_to_le16(1);
+				status |= cpu_to_le16(1);
 		} else
 			goto delegate;
 
 		/* Write directly to the FIFO. No queueing is done. */
-		if (crq->wLength != __constant_cpu_to_le16(sizeof(status)))
+		if (crq->wLength != cpu_to_le16(sizeof(status)))
 			goto stall;
 		ep->state = DATA_STAGE_IN;
 		__raw_writew(status, ep->fifo);
@@ -1274,7 +1274,7 @@
 		} else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
 			struct usba_ep *target;
 
-			if (crq->wLength != __constant_cpu_to_le16(0)
+			if (crq->wLength != cpu_to_le16(0)
 					|| !feature_is_ep_halt(crq))
 				goto stall;
 			target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
@@ -1308,7 +1308,7 @@
 		} else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
 			struct usba_ep *target;
 
-			if (crq->wLength != __constant_cpu_to_le16(0)
+			if (crq->wLength != cpu_to_le16(0)
 					|| !feature_is_ep_halt(crq))
 				goto stall;
 
@@ -1514,7 +1514,7 @@
 			 */
 			ep->state = DATA_STAGE_IN;
 		} else {
-			if (crq.crq.wLength != __constant_cpu_to_le16(0))
+			if (crq.crq.wLength != cpu_to_le16(0))
 				ep->state = DATA_STAGE_OUT;
 			else
 				ep->state = STATUS_STAGE_IN;
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index 5495b17..928137d 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -66,7 +66,7 @@
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bcdUSB =		cpu_to_le16(0x0200),
 
 	.bDeviceClass =		USB_CLASS_COMM,
 	.bDeviceSubClass =	0,
@@ -74,8 +74,8 @@
 	/* .bMaxPacketSize0 = f(hardware) */
 
 	/* Vendor and product id can be overridden by module parameters.  */
-	.idVendor =		__constant_cpu_to_le16(CDC_VENDOR_NUM),
-	.idProduct =		__constant_cpu_to_le16(CDC_PRODUCT_NUM),
+	.idVendor =		cpu_to_le16(CDC_VENDOR_NUM),
+	.idProduct =		cpu_to_le16(CDC_PRODUCT_NUM),
 	/* .bcdDevice = f(hardware) */
 	/* .iManufacturer = DYNAMIC */
 	/* .iProduct = DYNAMIC */
@@ -193,7 +193,7 @@
 				gadget->name,
 				cdc_config_driver.label);
 		device_desc.bcdDevice =
-			__constant_cpu_to_le16(0x0300 | 0x0099);
+			cpu_to_le16(0x0300 | 0x0099);
 	}
 
 
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index bebf911..22c6596 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -56,7 +56,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
@@ -2626,7 +2625,7 @@
 	INIT_LIST_HEAD(&udc->gadget.ep_list);
 	udc->gadget.ep0 = NULL;
 
-	strcpy(udc->gadget.dev.bus_id, "gadget");
+	dev_set_name(&udc->gadget.dev, "gadget");
 	udc->gadget.dev.dma_mask = dev->dma_mask;
 	udc->gadget.dev.parent   = dev;
 	udc->gadget.dev.release  = udc_release;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 5d11c29..59e8523 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -149,16 +149,17 @@
 int usb_function_deactivate(struct usb_function *function)
 {
 	struct usb_composite_dev	*cdev = function->config->cdev;
+	unsigned long			flags;
 	int				status = 0;
 
-	spin_lock(&cdev->lock);
+	spin_lock_irqsave(&cdev->lock, flags);
 
 	if (cdev->deactivations == 0)
 		status = usb_gadget_disconnect(cdev->gadget);
 	if (status == 0)
 		cdev->deactivations++;
 
-	spin_unlock(&cdev->lock);
+	spin_unlock_irqrestore(&cdev->lock, flags);
 	return status;
 }
 
@@ -1013,7 +1014,7 @@
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
 	struct usb_function		*f;
 
-	/* REVISIT:  should we have config and device level
+	/* REVISIT:  should we have config level
 	 * suspend/resume callbacks?
 	 */
 	DBG(cdev, "suspend\n");
@@ -1023,6 +1024,8 @@
 				f->suspend(f);
 		}
 	}
+	if (composite->suspend)
+		composite->suspend(cdev);
 }
 
 static void
@@ -1031,10 +1034,12 @@
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
 	struct usb_function		*f;
 
-	/* REVISIT:  should we have config and device level
+	/* REVISIT:  should we have config level
 	 * suspend/resume callbacks?
 	 */
 	DBG(cdev, "resume\n");
+	if (composite->resume)
+		composite->resume(cdev);
 	if (cdev->config) {
 		list_for_each_entry(f, &cdev->config->functions, list) {
 			if (f->resume)
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 9064696..a56b24d 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -1437,7 +1437,7 @@
 					}
 					if (urb->transfer_buffer_length > 1)
 						buf [1] = 0;
-					urb->actual_length = min (2,
+					urb->actual_length = min_t(u32, 2,
 						urb->transfer_buffer_length);
 					value = 0;
 					status = 0;
@@ -1626,7 +1626,7 @@
 		hub_descriptor ((struct usb_hub_descriptor *) buf);
 		break;
 	case GetHubStatus:
-		*(__le32 *) buf = __constant_cpu_to_le32 (0);
+		*(__le32 *) buf = cpu_to_le32 (0);
 		break;
 	case GetPortStatus:
 		if (wIndex != 1)
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index a36b117..cd0914e 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -148,7 +148,7 @@
 			return 0;
 
 		/* BOTH:  "high bandwidth" works only at high speed */
-		if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) {
+		if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
 			if (!gadget->is_dualspeed)
 				return 0;
 			/* configure your hardware with enough buffering!! */
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 37252d0..d006dc6 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -156,7 +156,7 @@
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
-	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
+	.bcdUSB =		cpu_to_le16 (0x0200),
 
 	.bDeviceClass =		USB_CLASS_COMM,
 	.bDeviceSubClass =	0,
@@ -167,8 +167,8 @@
 	 * we support.  (As does bNumConfigurations.)  These values can
 	 * also be overridden by module parameters.
 	 */
-	.idVendor =		__constant_cpu_to_le16 (CDC_VENDOR_NUM),
-	.idProduct =		__constant_cpu_to_le16 (CDC_PRODUCT_NUM),
+	.idVendor =		cpu_to_le16 (CDC_VENDOR_NUM),
+	.idProduct =		cpu_to_le16 (CDC_PRODUCT_NUM),
 	/* .bcdDevice = f(hardware) */
 	/* .iManufacturer = DYNAMIC */
 	/* .iProduct = DYNAMIC */
@@ -318,7 +318,7 @@
 				gadget->name,
 				eth_config_driver.label);
 		device_desc.bcdDevice =
-			__constant_cpu_to_le16(0x0300 | 0x0099);
+			cpu_to_le16(0x0300 | 0x0099);
 	}
 
 
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index c1d34df..7953948 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -125,7 +125,7 @@
 	.bLength =		sizeof(acm_header_desc),
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
-	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+	.bcdCDC =		cpu_to_le16(0x0110),
 };
 
 static struct usb_cdc_call_mgmt_descriptor
@@ -159,7 +159,7 @@
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
+	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
 	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL,
 };
 
@@ -197,7 +197,7 @@
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
+	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
 	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,
 };
 
@@ -205,14 +205,14 @@
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_descriptor_header *acm_hs_function[] __initdata = {
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 4ae5799..ecf5bdd 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -130,7 +130,7 @@
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
 
-	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+	.bcdCDC =		cpu_to_le16(0x0110),
 };
 
 static struct usb_cdc_union_desc ecm_union_desc __initdata = {
@@ -148,9 +148,9 @@
 
 	/* this descriptor actually adds value, surprise! */
 	/* .iMACAddress = DYNAMIC */
-	.bmEthernetStatistics =	__constant_cpu_to_le32(0), /* no statistics */
-	.wMaxSegmentSize =	__constant_cpu_to_le16(ETH_FRAME_LEN),
-	.wNumberMCFilters =	__constant_cpu_to_le16(0),
+	.bmEthernetStatistics =	cpu_to_le32(0), /* no statistics */
+	.wMaxSegmentSize =	cpu_to_le16(ETH_FRAME_LEN),
+	.wNumberMCFilters =	cpu_to_le16(0),
 	.bNumberPowerFilters =	0,
 };
 
@@ -192,7 +192,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
+	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
 	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
 };
 
@@ -236,7 +236,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
+	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
 	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
 };
 static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
@@ -245,7 +245,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
@@ -254,7 +254,7 @@
 
 	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_descriptor_header *ecm_hs_function[] __initdata = {
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 8affe1d..eb6ddfc 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -100,7 +100,7 @@
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor hs_loop_sink_desc = {
@@ -108,7 +108,7 @@
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_descriptor_header *hs_loopback_descs[] = {
@@ -359,7 +359,7 @@
  * loopback_add - add a loopback testing configuration to a device
  * @cdev: the device to support the loopback configuration
  */
-int __init loopback_add(struct usb_composite_dev *cdev)
+int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
 {
 	int id;
 
@@ -372,6 +372,10 @@
 	loopback_intf.iInterface = id;
 	loopback_driver.iConfiguration = id;
 
+	/* support autoresume for remote wakeup testing */
+	if (autoresume)
+		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+
 	/* support OTG systems */
 	if (gadget_is_otg(cdev->gadget)) {
 		loopback_driver.descriptors = otg_desc;
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index 38aa896..46d6266 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -123,7 +123,7 @@
 	.bLength		= sizeof(obex_cdc_header_desc),
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorSubType	= USB_CDC_HEADER_TYPE,
-	.bcdCDC			= __constant_cpu_to_le16(0x0120),
+	.bcdCDC			= cpu_to_le16(0x0120),
 };
 
 static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
@@ -138,7 +138,7 @@
 	.bLength		= sizeof(obex_desc),
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorSubType	= USB_CDC_OBEX_TYPE,
-	.bcdVersion		= __constant_cpu_to_le16(0x0100),
+	.bcdVersion		= cpu_to_le16(0x0100),
 };
 
 /* High-Speed Support */
@@ -149,7 +149,7 @@
 
 	.bEndpointAddress	= USB_DIR_OUT,
 	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize		= __constant_cpu_to_le16(512),
+	.wMaxPacketSize		= cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
@@ -158,7 +158,7 @@
 
 	.bEndpointAddress	= USB_DIR_IN,
 	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize		= __constant_cpu_to_le16(512),
+	.wMaxPacketSize		= cpu_to_le16(512),
 };
 
 static struct usb_descriptor_header *hs_function[] __initdata = {
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
index c0916c7..c1abeb8 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/f_phonet.c
@@ -79,7 +79,7 @@
 	.bLength =		sizeof pn_header_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
-	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+	.bcdCDC =		cpu_to_le16(0x0110),
 };
 
 static const struct usb_cdc_header_desc
@@ -87,7 +87,7 @@
 	.bLength =		sizeof pn_phonet_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_PHONET_TYPE,
-	.bcdCDC =		__constant_cpu_to_le16(0x1505), /* ??? */
+	.bcdCDC =		cpu_to_le16(0x1505), /* ??? */
 };
 
 static struct usb_cdc_union_desc
@@ -138,7 +138,7 @@
 
 	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor
@@ -157,7 +157,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_descriptor_header *fs_pn_function[] = {
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 3a8bb53..3279a47 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -137,7 +137,7 @@
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
 
-	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+	.bcdCDC =		cpu_to_le16(0x0110),
 };
 
 static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
@@ -187,7 +187,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
 	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
 };
 
@@ -230,7 +230,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
 	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
 };
 static struct usb_endpoint_descriptor hs_in_desc __initdata = {
@@ -239,7 +239,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor hs_out_desc __initdata = {
@@ -248,7 +248,7 @@
 
 	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_descriptor_header *eth_hs_function[] __initdata = {
@@ -437,7 +437,7 @@
 		DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			w_value, w_index, w_length);
-		req->zero = 0;
+		req->zero = (value < w_length);
 		req->length = value;
 		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
 		if (value < 0)
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index fe5674db..db0aa93 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -89,14 +89,14 @@
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_descriptor_header *gser_hs_function[] __initdata = {
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index dc84d26..bffe91d 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -59,7 +59,6 @@
 
 	struct usb_ep		*in_ep;
 	struct usb_ep		*out_ep;
-	struct timer_list	resume;
 };
 
 static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
@@ -67,10 +66,6 @@
 	return container_of(f, struct f_sourcesink, function);
 }
 
-static unsigned autoresume;
-module_param(autoresume, uint, 0);
-MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
-
 static unsigned pattern;
 module_param(pattern, uint, 0);
 MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
@@ -118,7 +113,7 @@
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor hs_sink_desc = {
@@ -126,7 +121,7 @@
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_descriptor_header *hs_source_sink_descs[] = {
@@ -155,21 +150,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void sourcesink_autoresume(unsigned long _c)
-{
-	struct usb_composite_dev *cdev = (void *)_c;
-	struct usb_gadget	*g = cdev->gadget;
-
-	/* Normally the host would be woken up for something
-	 * more significant than just a timer firing; likely
-	 * because of some direct user request.
-	 */
-	if (g->speed != USB_SPEED_UNKNOWN) {
-		int status = usb_gadget_wakeup(g);
-		DBG(cdev, "%s --> %d\n", __func__, status);
-	}
-}
-
 static int __init
 sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
 {
@@ -198,9 +178,6 @@
 		goto autoconf_fail;
 	ss->out_ep->driver_data = cdev;	/* claim */
 
-	setup_timer(&ss->resume, sourcesink_autoresume,
-			(unsigned long) c->cdev);
-
 	/* support high speed hardware */
 	if (gadget_is_dualspeed(c->cdev->gadget)) {
 		hs_source_desc.bEndpointAddress =
@@ -359,7 +336,6 @@
 
 	cdev = ss->function.config->cdev;
 	disable_endpoints(cdev, ss->in_ep, ss->out_ep);
-	del_timer(&ss->resume);
 	VDBG(cdev, "%s disabled\n", ss->function.name);
 }
 
@@ -426,30 +402,6 @@
 	disable_source_sink(ss);
 }
 
-static void sourcesink_suspend(struct usb_function *f)
-{
-	struct f_sourcesink	*ss = func_to_ss(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
-
-	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
-		return;
-
-	if (autoresume) {
-		mod_timer(&ss->resume, jiffies + (HZ * autoresume));
-		DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
-	} else
-		DBG(cdev, "%s\n", __func__);
-}
-
-static void sourcesink_resume(struct usb_function *f)
-{
-	struct f_sourcesink	*ss = func_to_ss(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
-
-	DBG(cdev, "%s\n", __func__);
-	del_timer(&ss->resume);
-}
-
 /*-------------------------------------------------------------------------*/
 
 static int __init sourcesink_bind_config(struct usb_configuration *c)
@@ -467,8 +419,6 @@
 	ss->function.unbind = sourcesink_unbind;
 	ss->function.set_alt = sourcesink_set_alt;
 	ss->function.disable = sourcesink_disable;
-	ss->function.suspend = sourcesink_suspend;
-	ss->function.resume = sourcesink_resume;
 
 	status = usb_add_function(c, &ss->function);
 	if (status)
@@ -559,7 +509,7 @@
  * sourcesink_add - add a source/sink testing configuration to a device
  * @cdev: the device to support the configuration
  */
-int __init sourcesink_add(struct usb_composite_dev *cdev)
+int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)
 {
 	int id;
 
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index fe18328..a9c98fd 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -108,7 +108,7 @@
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
 
-	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+	.bcdCDC =		cpu_to_le16(0x0110),
 };
 
 static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
@@ -116,7 +116,7 @@
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_MDLM_TYPE,
 
-	.bcdVersion =		__constant_cpu_to_le16(0x0100),
+	.bcdVersion =		cpu_to_le16(0x0100),
 	.bGUID = {
 		0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
 		0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
@@ -144,9 +144,9 @@
 
 	/* this descriptor actually adds value, surprise! */
 	/* .iMACAddress = DYNAMIC */
-	.bmEthernetStatistics =	__constant_cpu_to_le32(0), /* no statistics */
-	.wMaxSegmentSize =	__constant_cpu_to_le16(ETH_FRAME_LEN),
-	.wNumberMCFilters =	__constant_cpu_to_le16(0),
+	.bmEthernetStatistics =	cpu_to_le32(0), /* no statistics */
+	.wMaxSegmentSize =	cpu_to_le16(ETH_FRAME_LEN),
+	.wNumberMCFilters =	cpu_to_le16(0),
 	.bNumberPowerFilters =	0,
 };
 
@@ -186,7 +186,7 @@
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
@@ -194,7 +194,7 @@
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_descriptor_header *hs_eth_function[] __initdata = {
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 1ab9dac..d3c2464 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -847,13 +847,13 @@
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bcdUSB =		cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
 
 	/* The next three values can be overridden by module parameters */
-	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_ID),
-	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_ID),
-	.bcdDevice =		__constant_cpu_to_le16(0xffff),
+	.idVendor =		cpu_to_le16(DRIVER_VENDOR_ID),
+	.idProduct =		cpu_to_le16(DRIVER_PRODUCT_ID),
+	.bcdDevice =		cpu_to_le16(0xffff),
 
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
@@ -926,7 +926,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(2),
+	.wMaxPacketSize =	cpu_to_le16(2),
 	.bInterval =		32,	// frames -> 32 ms
 };
 
@@ -954,7 +954,7 @@
 	.bLength =		sizeof dev_qualifier,
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
 
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bcdUSB =		cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
 
 	.bNumConfigurations =	1,
@@ -967,7 +967,7 @@
 
 	/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor
@@ -977,7 +977,7 @@
 
 	/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+	.wMaxPacketSize =	cpu_to_le16(512),
 	.bInterval =		1,	// NAK every 1 uframe
 };
 
@@ -988,7 +988,7 @@
 
 	/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(2),
+	.wMaxPacketSize =	cpu_to_le16(2),
 	.bInterval =		9,	// 2**(9-1) = 256 uframes -> 32 ms
 };
 
@@ -2646,7 +2646,7 @@
 		struct bulk_cs_wrap	*csw = bh->buf;
 
 		/* Store and send the Bulk-only CSW */
-		csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG);
+		csw->Signature = cpu_to_le32(USB_BULK_CS_SIG);
 		csw->Tag = fsg->tag;
 		csw->Residue = cpu_to_le32(fsg->residue);
 		csw->Status = status;
@@ -3089,7 +3089,7 @@
 
 	/* Is the CBW valid? */
 	if (req->actual != USB_BULK_CB_WRAP_LEN ||
-			cbw->Signature != __constant_cpu_to_le32(
+			cbw->Signature != cpu_to_le32(
 				USB_BULK_CB_SIG)) {
 		DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
 				req->actual,
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index d8d9a52..9d7b95d 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -1802,7 +1802,8 @@
 
 out:
 	if (retval)
-		printk("gadget driver register failed %d\n", retval);
+		printk(KERN_WARNING "gadget driver register failed %d\n",
+		       retval);
 	return retval;
 }
 EXPORT_SYMBOL(usb_gadget_register_driver);
@@ -1847,7 +1848,8 @@
 	udc_controller->gadget.dev.driver = NULL;
 	udc_controller->driver = NULL;
 
-	printk("unregistered gadget driver '%s'\n", driver->driver.name);
+	printk(KERN_WARNING "unregistered gadget driver '%s'\n",
+	       driver->driver.name);
 	return 0;
 }
 EXPORT_SYMBOL(usb_gadget_unregister_driver);
@@ -2455,7 +2457,7 @@
 static void __exit udc_exit(void)
 {
 	platform_driver_unregister(&udc_driver);
-	printk("%s unregistered\n", driver_desc);
+	printk(KERN_WARNING "%s unregistered\n", driver_desc);
 }
 
 module_exit(udc_exit);
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h
index dd2f16a..e84b3c4 100644
--- a/drivers/usb/gadget/g_zero.h
+++ b/drivers/usb/gadget/g_zero.h
@@ -19,7 +19,7 @@
 		struct usb_ep *in, struct usb_ep *out);
 
 /* configuration-specific linkup */
-int sourcesink_add(struct usb_composite_dev *cdev);
-int loopback_add(struct usb_composite_dev *cdev);
+int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume);
+int loopback_add(struct usb_composite_dev *cdev, bool autoresume);
 
 #endif /* __G_ZERO_H */
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 60d3f9e..b9312dc 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -199,10 +199,10 @@
 static struct usb_device_descriptor device_desc = {
 	.bLength =		USB_DT_DEVICE_SIZE,
 	.bDescriptorType =	USB_DT_DEVICE,
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bcdUSB =		cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
-	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_NUM),
-	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+	.idVendor =		cpu_to_le16(DRIVER_VENDOR_NUM),
+	.idProduct =		cpu_to_le16(DRIVER_PRODUCT_NUM),
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
 	.bNumConfigurations =	1,
@@ -241,8 +241,8 @@
 	.bLength =		USB_DT_AC_HEADER_SIZE(1),
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubtype =	USB_MS_HEADER,
-	.bcdADC =		__constant_cpu_to_le16(0x0100),
-	.wTotalLength =		__constant_cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)),
+	.bcdADC =		cpu_to_le16(0x0100),
+	.wTotalLength =		cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)),
 	.bInCollection =	1,
 	.baInterfaceNr = {
 		[0] =		GMIDI_MS_INTERFACE,
@@ -265,8 +265,8 @@
 	.bLength =		USB_DT_MS_HEADER_SIZE,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubtype =	USB_MS_HEADER,
-	.bcdMSC =		__constant_cpu_to_le16(0x0100),
-	.wTotalLength =		__constant_cpu_to_le16(USB_DT_MS_HEADER_SIZE
+	.bcdMSC =		cpu_to_le16(0x0100),
+	.wTotalLength =		cpu_to_le16(USB_DT_MS_HEADER_SIZE
 				+ 2*USB_DT_MIDI_IN_SIZE
 				+ 2*USB_DT_MIDI_OUT_SIZE(1)),
 };
@@ -1099,10 +1099,9 @@
 		.dev_free = gmidi_snd_free,
 	};
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (!card) {
-		ERROR(dev, "snd_card_new failed\n");
-		err = -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0) {
+		ERROR(dev, "snd_card_create failed\n");
 		goto fail;
 	}
 	dev->card = card;
@@ -1227,7 +1226,7 @@
 		 */
 		pr_warning("%s: controller '%s' not recognized\n",
 			shortname, gadget->name);
-		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+		device_desc.bcdDevice = cpu_to_le16(0x9999);
 	}
 
 
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 63419c4..de010c9 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1472,7 +1472,7 @@
 				/* active endpoint */
 				if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0))
 					goto stall;
-				if (ctrl.wIndex & __constant_cpu_to_le16(
+				if (ctrl.wIndex & cpu_to_le16(
 						USB_DIR_IN)) {
 					if (!dev->ep[tmp].is_in)
 						goto stall;
@@ -1480,7 +1480,7 @@
 					if (dev->ep[tmp].is_in)
 						goto stall;
 				}
-				if (ctrl.wValue != __constant_cpu_to_le16(
+				if (ctrl.wValue != cpu_to_le16(
 						USB_ENDPOINT_HALT))
 					goto stall;
 				if (tmp)
@@ -1493,7 +1493,7 @@
 				return;
 			case USB_RECIP_DEVICE:
 				/* device remote wakeup: always clear */
-				if (ctrl.wValue != __constant_cpu_to_le16(1))
+				if (ctrl.wValue != cpu_to_le16(1))
 					goto stall;
 				VDBG(dev, "clear dev remote wakeup\n");
 				goto succeed;
@@ -1519,7 +1519,7 @@
 	dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION
 				&& ctrl.bRequestType == USB_RECIP_DEVICE);
 	if (unlikely(dev->req_config))
-		dev->configured = (ctrl.wValue != __constant_cpu_to_le16(0));
+		dev->configured = (ctrl.wValue != cpu_to_le16(0));
 
 	/* delegate everything to the gadget driver.
 	 * it may respond after this irq handler returns.
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index 77c5d0a..168658b 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1,7 +1,7 @@
 /*
  *	driver/usb/gadget/imx_udc.c
  *
- *	Copyright (C) 2005 Mike Lee(eemike@gmail.com)
+ *	Copyright (C) 2005 Mike Lee <eemike@gmail.com>
  *	Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com>
  *
  *	This program is free software; you can redistribute it and/or modify
@@ -28,6 +28,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/timer.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -51,7 +52,8 @@
 void imx_udc_enable(struct imx_udc_struct *imx_usb)
 {
 	int temp = __raw_readl(imx_usb->base + USB_CTRL);
-	__raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, imx_usb->base + USB_CTRL);
+	__raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA,
+						imx_usb->base + USB_CTRL);
 	imx_usb->gadget.speed = USB_SPEED_FULL;
 }
 
@@ -126,7 +128,8 @@
 			for (j = 0; j < 5; j++) {
 				__raw_writeb(ep_conf[j],
 					imx_usb->base + USB_DDAT);
-				do {} while (__raw_readl(imx_usb->base + USB_DADR)
+				do {} while (__raw_readl(imx_usb->base
+								+ USB_DADR)
 					& DADR_BSY);
 			}
 		}
@@ -183,7 +186,8 @@
 		temp = (EP_DIR(imx_ep) << 7) | (max << 5)
 			| (imx_ep->bmAttributes << 3);
 		__raw_writel(temp, imx_usb->base + USB_EP_STAT(i));
-		__raw_writel(temp | EPSTAT_FLUSH, imx_usb->base + USB_EP_STAT(i));
+		__raw_writel(temp | EPSTAT_FLUSH,
+						imx_usb->base + USB_EP_STAT(i));
 		D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i,
 			__raw_readl(imx_usb->base + USB_EP_STAT(i)));
 	}
@@ -278,15 +282,18 @@
 	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
 	int temp, i;
 
-	D_ERR(imx_usb->dev, "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name);
+	D_ERR(imx_usb->dev,
+		"<%s> Forced stall on %s\n", __func__, imx_ep->ep.name);
 
 	imx_flush(imx_ep);
 
 	/* Special care for ep0 */
-	if (EP_NO(imx_ep)) {
+	if (!EP_NO(imx_ep)) {
 		temp = __raw_readl(imx_usb->base + USB_CTRL);
-		__raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL);
-		do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER);
+		__raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR,
+						imx_usb->base + USB_CTRL);
+		do { } while (__raw_readl(imx_usb->base + USB_CTRL)
+						& CTRL_CMDOVER);
 		temp = __raw_readl(imx_usb->base + USB_CTRL);
 		__raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL);
 	}
@@ -296,12 +303,13 @@
 			imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
 
 		for (i = 0; i < 100; i ++) {
-			temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
+			temp = __raw_readl(imx_usb->base
+						+ USB_EP_STAT(EP_NO(imx_ep)));
 			if (!(temp & EPSTAT_STALL))
 	 			break;
 	 		udelay(20);
 	 	}
-		if (i == 50)
+		if (i == 100)
 			D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n",
 				__func__, imx_ep->ep.name);
 	}
@@ -325,7 +333,8 @@
  *******************************************************************************
  */
 
-static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req)
+static void ep_add_request(struct imx_ep_struct *imx_ep,
+							struct imx_request *req)
 {
 	if (unlikely(!req))
 		return;
@@ -334,7 +343,8 @@
 	list_add_tail(&req->queue, &imx_ep->queue);
 }
 
-static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req)
+static void ep_del_request(struct imx_ep_struct *imx_ep,
+							struct imx_request *req)
 {
 	if (unlikely(!req))
 		return;
@@ -343,7 +353,8 @@
 	req->in_use = 0;
 }
 
-static void done(struct imx_ep_struct *imx_ep, struct imx_request *req, int status)
+static void done(struct imx_ep_struct *imx_ep,
+					struct imx_request *req, int status)
 {
 	ep_del_request(imx_ep, req);
 
@@ -494,7 +505,8 @@
 				__func__, imx_ep->ep.name, req,
 				completed ? "completed" : "not completed");
 			if (!EP_NO(imx_ep))
-				ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE);
+				ep0_chg_stat(__func__,
+						imx_ep->imx_usb, EP0_IDLE);
 		}
 	}
 
@@ -539,10 +551,9 @@
 	struct imx_request *req = NULL;
 	int ret = 0;
 
-	if (!list_empty(&imx_ep->queue))
+	if (!list_empty(&imx_ep->queue)) {
 		req = list_entry(imx_ep->queue.next, struct imx_request, queue);
 
-	if (req) {
 		switch (imx_ep->imx_usb->ep0state) {
 
 		case EP0_IN_DATA_PHASE:			/* GET_DESCRIPTOR */
@@ -561,6 +572,10 @@
 		}
 	}
 
+	else
+		D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n",
+						__func__, imx_ep->ep.name);
+
 	return ret;
 }
 
@@ -583,7 +598,8 @@
 				"<%s> no setup packet received\n", __func__);
 			goto stall;
 		}
-		u.word[i] = __raw_readl(imx_usb->base +	USB_EP_FDAT(EP_NO(imx_ep)));
+		u.word[i] = __raw_readl(imx_usb->base
+						+ USB_EP_FDAT(EP_NO(imx_ep)));
 	}
 
 	temp = imx_ep_empty(imx_ep);
@@ -759,7 +775,7 @@
 	*/
 	if (imx_usb->set_config && !EP_NO(imx_ep)) {
 		imx_usb->set_config = 0;
-		D_EPX(imx_usb->dev,
+		D_ERR(imx_usb->dev,
 			"<%s> gadget reply set config\n", __func__);
 		return 0;
 	}
@@ -779,28 +795,29 @@
 		return -ESHUTDOWN;
 	}
 
-	local_irq_save(flags);
-
 	/* Debug */
 	D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n",
 		__func__, EP_NO(imx_ep),
-		((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE)
-		|| (EP_NO(imx_ep) && EP_DIR(imx_ep))) ? "IN" : "OUT", usb_req->length);
+		((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
+							== EP0_IN_DATA_PHASE)
+		|| (EP_NO(imx_ep) && EP_DIR(imx_ep)))
+					? "IN" : "OUT", usb_req->length);
 	dump_req(__func__, imx_ep, usb_req);
 
 	if (imx_ep->stopped) {
 		usb_req->status = -ESHUTDOWN;
-		ret = -ESHUTDOWN;
-		goto out;
+		return -ESHUTDOWN;
 	}
 
 	if (req->in_use) {
 		D_ERR(imx_usb->dev,
 			"<%s> refusing to queue req %p (already queued)\n",
 			__func__, req);
-		goto out;
+		return 0;
 	}
 
+	local_irq_save(flags);
+
 	usb_req->status = -EINPROGRESS;
 	usb_req->actual = 0;
 
@@ -810,7 +827,7 @@
 		ret = handle_ep0(imx_ep);
 	else
 		ret = handle_ep(imx_ep);
-out:
+
 	local_irq_restore(flags);
 	return ret;
 }
@@ -997,71 +1014,32 @@
  *******************************************************************************
  */
 
-static irqreturn_t imx_udc_irq(int irq, void *dev)
+/*
+ * Called when timer expires.
+ * Timer is started when CFG_CHG is received.
+ */
+static void handle_config(unsigned long data)
 {
-	struct imx_udc_struct *imx_usb = dev;
+	struct imx_udc_struct *imx_usb = (void *)data;
 	struct usb_ctrlrequest u;
 	int temp, cfg, intf, alt;
-	int intr = __raw_readl(imx_usb->base + USB_INTR);
 
-	if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START
-			| INTR_RESET_STOP | INTR_CFG_CHG)) {
-				dump_intr(__func__, intr, imx_usb->dev);
-				dump_usb_stat(__func__, imx_usb);
-	}
+	local_irq_disable();
 
-	if (!imx_usb->driver) {
-		/*imx_udc_disable(imx_usb);*/
-		goto end_irq;
-	}
+	temp = __raw_readl(imx_usb->base + USB_STAT);
+	cfg  = (temp & STAT_CFG) >> 5;
+	intf = (temp & STAT_INTF) >> 3;
+	alt  =  temp & STAT_ALTSET;
 
-	if (intr & INTR_WAKEUP) {
-		if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
-			&& imx_usb->driver && imx_usb->driver->resume)
-				imx_usb->driver->resume(&imx_usb->gadget);
-		imx_usb->set_config = 0;
-		imx_usb->gadget.speed = USB_SPEED_FULL;
-	}
+	D_REQ(imx_usb->dev,
+		"<%s> orig config C=%d, I=%d, A=%d / "
+		"req config C=%d, I=%d, A=%d\n",
+		__func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt,
+		cfg, intf, alt);
 
-	if (intr & INTR_SUSPEND) {
-		if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN
-			&& imx_usb->driver && imx_usb->driver->suspend)
-				imx_usb->driver->suspend(&imx_usb->gadget);
-		imx_usb->set_config = 0;
-		imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
-	}
+	if (cfg == 1 || cfg == 2) {
 
-	if (intr & INTR_RESET_START) {
-		__raw_writel(intr, imx_usb->base + USB_INTR);
-		udc_stop_activity(imx_usb, imx_usb->driver);
-		imx_usb->set_config = 0;
-		imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
-	}
-
-	if (intr & INTR_RESET_STOP)
-		imx_usb->gadget.speed = USB_SPEED_FULL;
-
-	if (intr & INTR_CFG_CHG) {
-		__raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR);
-		temp = __raw_readl(imx_usb->base + USB_STAT);
-		cfg  = (temp & STAT_CFG) >> 5;
-		intf = (temp & STAT_INTF) >> 3;
-		alt  =  temp & STAT_ALTSET;
-
-		D_REQ(imx_usb->dev,
-			"<%s> orig config C=%d, I=%d, A=%d / "
-			"req config C=%d, I=%d, A=%d\n",
-			__func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt,
-			cfg, intf, alt);
-
-		if (cfg != 1 && cfg != 2)
-			goto end_irq;
-
-		imx_usb->set_config = 0;
-
-		/* Config setup */
 		if (imx_usb->cfg != cfg) {
-			D_REQ(imx_usb->dev, "<%s> Change config start\n",__func__);
 			u.bRequest = USB_REQ_SET_CONFIGURATION;
 			u.bRequestType = USB_DIR_OUT |
 					USB_TYPE_STANDARD |
@@ -1070,14 +1048,10 @@
 			u.wIndex = 0;
 			u.wLength = 0;
 			imx_usb->cfg = cfg;
-			imx_usb->set_config = 1;
 			imx_usb->driver->setup(&imx_usb->gadget, &u);
-			imx_usb->set_config = 0;
-			D_REQ(imx_usb->dev, "<%s> Change config done\n",__func__);
 
 		}
 		if (imx_usb->intf != intf || imx_usb->alt != alt) {
-			D_REQ(imx_usb->dev, "<%s> Change interface start\n",__func__);
 			u.bRequest = USB_REQ_SET_INTERFACE;
 			u.bRequestType = USB_DIR_OUT |
 					  USB_TYPE_STANDARD |
@@ -1087,20 +1061,92 @@
 			u.wLength = 0;
 			imx_usb->intf = intf;
 			imx_usb->alt = alt;
-			imx_usb->set_config = 1;
 			imx_usb->driver->setup(&imx_usb->gadget, &u);
-			imx_usb->set_config = 0;
-			D_REQ(imx_usb->dev, "<%s> Change interface done\n",__func__);
 		}
 	}
 
+	imx_usb->set_config = 0;
+
+	local_irq_enable();
+}
+
+static irqreturn_t imx_udc_irq(int irq, void *dev)
+{
+	struct imx_udc_struct *imx_usb = dev;
+	int intr = __raw_readl(imx_usb->base + USB_INTR);
+	int temp;
+
+	if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START
+			| INTR_RESET_STOP | INTR_CFG_CHG)) {
+				dump_intr(__func__, intr, imx_usb->dev);
+				dump_usb_stat(__func__, imx_usb);
+	}
+
+	if (!imx_usb->driver)
+		goto end_irq;
+
 	if (intr & INTR_SOF) {
+		/* Copy from Freescale BSP.
+		   We must enable SOF intr and set CMDOVER.
+		   Datasheet don't specifiy this action, but it
+		   is done in Freescale BSP, so just copy it.
+		*/
 		if (imx_usb->ep0state == EP0_IDLE) {
 			temp = __raw_readl(imx_usb->base + USB_CTRL);
-			__raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL);
+			__raw_writel(temp | CTRL_CMDOVER,
+						imx_usb->base + USB_CTRL);
 		}
 	}
 
+	if (intr & INTR_CFG_CHG) {
+		/* A workaround of serious IMX UDC bug.
+		   Handling of CFG_CHG should be delayed for some time, because
+		   IMX does not NACK the host when CFG_CHG interrupt is pending.
+		   There is no time to handle current CFG_CHG
+		   if next CFG_CHG or SETUP packed is send immediately.
+		   We have to clear CFG_CHG, start the timer and
+		   NACK the host by setting CTRL_CMDOVER
+		   if it sends any SETUP packet.
+		   When timer expires, handler is called to handle configuration
+		   changes. While CFG_CHG is not handled (set_config=1),
+		   we must NACK the host to every SETUP packed.
+		   This delay prevents from going out of sync with host.
+		 */
+		__raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR);
+		imx_usb->set_config = 1;
+		mod_timer(&imx_usb->timer, jiffies + 5);
+		goto end_irq;
+	}
+
+	if (intr & INTR_WAKEUP) {
+		if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
+			&& imx_usb->driver && imx_usb->driver->resume)
+				imx_usb->driver->resume(&imx_usb->gadget);
+		imx_usb->set_config = 0;
+		del_timer(&imx_usb->timer);
+		imx_usb->gadget.speed = USB_SPEED_FULL;
+	}
+
+	if (intr & INTR_SUSPEND) {
+		if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN
+			&& imx_usb->driver && imx_usb->driver->suspend)
+				imx_usb->driver->suspend(&imx_usb->gadget);
+		imx_usb->set_config = 0;
+		del_timer(&imx_usb->timer);
+		imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
+	}
+
+	if (intr & INTR_RESET_START) {
+		__raw_writel(intr, imx_usb->base + USB_INTR);
+		udc_stop_activity(imx_usb, imx_usb->driver);
+		imx_usb->set_config = 0;
+		del_timer(&imx_usb->timer);
+		imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
+	}
+
+	if (intr & INTR_RESET_STOP)
+		imx_usb->gadget.speed = USB_SPEED_FULL;
+
 end_irq:
 	__raw_writel(intr, imx_usb->base + USB_INTR);
 	return IRQ_HANDLED;
@@ -1109,6 +1155,7 @@
 static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev)
 {
 	struct imx_udc_struct *imx_usb = dev;
+	struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0];
 	int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0));
 
 	dump_ep_intr(__func__, 0, intr, imx_usb->dev);
@@ -1118,16 +1165,15 @@
 		return IRQ_HANDLED;
 	}
 
-	/* DEVREQ IRQ has highest priority */
+	/* DEVREQ has highest priority */
 	if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ))
 		handle_ep0_devreq(imx_usb);
 	/* Seem i.MX is missing EOF interrupt sometimes.
-	 * Therefore we monitor both EOF and FIFO_EMPTY interrups
-	 * when transmiting, and both EOF and FIFO_FULL when
-	 * receiving data.
+	 * Therefore we don't monitor EOF.
+	 * We call handle_ep0() only if a request is queued for ep0.
 	 */
-	else if (intr & (EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL))
-		handle_ep0(&imx_usb->imx_ep[0]);
+	else if (!list_empty(&imx_ep->queue))
+		handle_ep0(imx_ep);
 
 	__raw_writel(intr, imx_usb->base + USB_EP_INTR(0));
 
@@ -1186,8 +1232,8 @@
 		.ep0		= &controller.imx_ep[0].ep,
 		.name		= driver_name,
 		.dev = {
-			 .bus_id	= "gadget",
-		 },
+			.init_name	= "gadget",
+		},
 	},
 
 	.imx_ep[0] = {
@@ -1318,6 +1364,7 @@
 
 	udc_stop_activity(imx_usb, driver);
 	imx_udc_disable(imx_usb);
+	del_timer(&imx_usb->timer);
 
 	driver->unbind(&imx_usb->gadget);
 	imx_usb->gadget.dev.driver = NULL;
@@ -1435,6 +1482,10 @@
 	usb_init_data(imx_usb);
 	imx_udc_init(imx_usb);
 
+	init_timer(&imx_usb->timer);
+	imx_usb->timer.function = handle_config;
+	imx_usb->timer.data = (unsigned long)imx_usb;
+
 	return 0;
 
 fail3:
@@ -1457,6 +1508,7 @@
 	int i;
 
 	imx_udc_disable(imx_usb);
+	del_timer(&imx_usb->timer);
 
 	for (i = 0; i < IMX_USB_NB_EP + 1; i++)
 		free_irq(imx_usb->usbd_int[i], imx_usb);
diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h
index 8500769..b48ad59 100644
--- a/drivers/usb/gadget/imx_udc.h
+++ b/drivers/usb/gadget/imx_udc.h
@@ -23,7 +23,8 @@
 /* Helper macros */
 #define EP_NO(ep)	((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */
 #define EP_DIR(ep)	((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0)
-#define irq_to_ep(irq)	(((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/
+#define irq_to_ep(irq)	(((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) \
+		? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/
 #define ep_to_irq(ep)	(EP_NO((ep)) + USBD_INT0)
 #define IMX_USB_NB_EP	6
 
@@ -58,6 +59,7 @@
 	struct device				*dev;
 	struct imx_ep_struct			imx_ep[IMX_USB_NB_EP];
 	struct clk				*clk;
+	struct timer_list			timer;
 	enum ep0_state				ep0state;
 	struct resource				*res;
 	void __iomem				*base;
@@ -88,8 +90,8 @@
 #define  USB_EP_FDAT3(x)	(0x3F + (x*0x30)) /* USB FIFO data */
 #define  USB_EP_FSTAT(x)	(0x40 + (x*0x30)) /* USB FIFO status */
 #define  USB_EP_FCTRL(x)	(0x44 + (x*0x30)) /* USB FIFO control */
-#define  USB_EP_LRFP(x)		(0x48 + (x*0x30)) /* USB last read frame pointer */
-#define  USB_EP_LWFP(x)		(0x4C + (x*0x30)) /* USB last write frame pointer */
+#define  USB_EP_LRFP(x)		(0x48 + (x*0x30)) /* USB last rd f. pointer */
+#define  USB_EP_LWFP(x)		(0x4C + (x*0x30)) /* USB last wr f. pointer */
 #define  USB_EP_FALRM(x)	(0x50 + (x*0x30)) /* USB FIFO alarm */
 #define  USB_EP_FRDP(x)		(0x54 + (x*0x30)) /* USB FIFO read pointer */
 #define  USB_EP_FWRP(x)		(0x58 + (x*0x30)) /* USB FIFO write pointer */
@@ -170,7 +172,7 @@
 /* #define DEBUG_IRQ */
 /* #define DEBUG_EPIRQ */
 /* #define DEBUG_DUMP */
-#define DEBUG_ERR
+/* #define DEBUG_ERR */
 
 #ifdef DEBUG_REQ
 	#define D_REQ(dev, args...)	dev_dbg(dev, ## args)
@@ -228,7 +230,8 @@
 #endif /* DEBUG_IRQ */
 
 #ifdef DEBUG_EPIRQ
-	static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev)
+	static void dump_ep_intr(const char *label, int nr, int irqreg,
+							struct device *dev)
 	{
 		dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr,
 			(irqreg & EPINTR_FIFO_FULL) ? " full" : "",
@@ -246,7 +249,8 @@
 #endif /* DEBUG_IRQ */
 
 #ifdef DEBUG_DUMP
-	static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb)
+	static void dump_usb_stat(const char *label,
+						struct imx_udc_struct *imx_usb)
 	{
 		int temp = __raw_readl(imx_usb->base + USB_STAT);
 
@@ -259,12 +263,15 @@
 			(temp & STAT_ALTSET));
 	}
 
-	static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep)
+	static void dump_ep_stat(const char *label,
+						struct imx_ep_struct *imx_ep)
 	{
-		int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
+		int temp = __raw_readl(imx_ep->imx_usb->base
+						+ USB_EP_INTR(EP_NO(imx_ep)));
 
 		dev_dbg(imx_ep->imx_usb->dev,
-			"<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep),
+			"<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n",
+			label, EP_NO(imx_ep),
 			(temp & EPINTR_FIFO_FULL) ? " full" : "",
 			(temp & EPINTR_FIFO_EMPTY) ? " fempty" : "",
 			(temp & EPINTR_FIFO_ERROR) ? " ferr" : "",
@@ -275,18 +282,22 @@
 			(temp & EPINTR_DEVREQ) ? " devreq" : "",
 			(temp & EPINTR_EOT) ? " eot" : "");
 
-		temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
+		temp = __raw_readl(imx_ep->imx_usb->base
+						+ USB_EP_STAT(EP_NO(imx_ep)));
 
 		dev_dbg(imx_ep->imx_usb->dev,
-			"<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep),
+			"<%s> EP%d_STAT=[%s%s bcount=%d]\n",
+			label, EP_NO(imx_ep),
 			(temp & EPSTAT_SIP) ? " sip" : "",
 			(temp & EPSTAT_STALL) ? " stall" : "",
 			(temp & EPSTAT_BCOUNT) >> 16);
 
-		temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep)));
+		temp = __raw_readl(imx_ep->imx_usb->base
+						+ USB_EP_FSTAT(EP_NO(imx_ep)));
 
 		dev_dbg(imx_ep->imx_usb->dev,
-			"<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep),
+			"<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n",
+			label, EP_NO(imx_ep),
 			(temp & FSTAT_ERR) ? " ferr" : "",
 			(temp & FSTAT_UF) ? " funder" : "",
 			(temp & FSTAT_OF) ? " fover" : "",
@@ -296,19 +307,23 @@
 			(temp & FSTAT_EMPTY) ? " fempty" : "");
 	}
 
-	static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req)
+	static void dump_req(const char *label, struct imx_ep_struct *imx_ep,
+							struct usb_request *req)
 	{
 		int i;
 
 		if (!req || !req->buf) {
-			dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label);
+			dev_dbg(imx_ep->imx_usb->dev,
+					"<%s> req or req buf is free\n", label);
 			return;
 		}
 
-		if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE)
+		if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
+			== EP0_IN_DATA_PHASE)
 			|| (EP_NO(imx_ep) && EP_DIR(imx_ep))) {
 
-			dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label);
+			dev_dbg(imx_ep->imx_usb->dev,
+						"<%s> request dump <", label);
 			for (i = 0; i < req->length; i++)
 				printk("%02x-", *((u8 *)req->buf + i));
 			printk(">\n");
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 317b48f..d20937f 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1334,7 +1334,7 @@
 
 	qual.bLength = sizeof qual;
 	qual.bDescriptorType = USB_DT_DEVICE_QUALIFIER;
-	qual.bcdUSB = __constant_cpu_to_le16 (0x0200);
+	qual.bcdUSB = cpu_to_le16 (0x0200);
 
 	desc = dev->dev;
 	qual.bDeviceClass = desc->bDeviceClass;
@@ -1908,7 +1908,7 @@
 			|| dev->dev->bNumConfigurations != 1)
 		goto fail;
 	dev->dev->bNumConfigurations = 1;
-	dev->dev->bcdUSB = __constant_cpu_to_le16 (0x0200);
+	dev->dev->bcdUSB = cpu_to_le16 (0x0200);
 
 	/* triggers gadgetfs_bind(); then we can enumerate. */
 	spin_unlock_irq (&dev->lock);
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index d554b08..6cd3d54 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -432,8 +432,8 @@
 	device_add(&dev->gadget.dev);
 	retval = driver->bind(&dev->gadget);
 	if (retval) {
-		printk("%s: bind to driver %s --> error %d\n", dev->gadget.name,
-		       driver->driver.name, retval);
+		printk(KERN_WARNING "%s: bind to driver %s --> error %d\n",
+		       dev->gadget.name, driver->driver.name, retval);
 		device_del(&dev->gadget.dev);
 
 		dev->driver = 0;
@@ -445,8 +445,8 @@
 	 * for set_configuration as well as eventual disconnect.
 	 * NOTE:  this shouldn't power up until later.
 	 */
-	printk("%s: registered gadget driver '%s'\n", dev->gadget.name,
-	       driver->driver.name);
+	printk(KERN_WARNING "%s: registered gadget driver '%s'\n",
+	       dev->gadget.name, driver->driver.name);
 
 	udc_enable(dev);
 
@@ -581,7 +581,8 @@
 			 * discard the extra data.
 			 */
 			if (req->req.status != -EOVERFLOW)
-				printk("%s overflow %d\n", ep->ep.name, count);
+				printk(KERN_WARNING "%s overflow %d\n",
+				       ep->ep.name, count);
 			req->req.status = -EOVERFLOW;
 		} else {
 			*buf++ = byte;
@@ -831,7 +832,8 @@
 						       queue);
 
 				if (!req) {
-					printk("%s: NULL REQ %d\n",
+					printk(KERN_WARNING
+					       "%s: NULL REQ %d\n",
 					       __func__, ep_idx);
 					flush(ep);
 					break;
@@ -844,7 +846,7 @@
 
 	} else {
 		/* Throw packet away.. */
-		printk("%s: No descriptor?!?\n", __func__);
+		printk(KERN_WARNING "%s: No descriptor?!?\n", __func__);
 		flush(ep);
 	}
 }
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 12c6d83..9498be8 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -142,8 +142,8 @@
 
 #include "net2280.h"
 
-#define valid_bit	__constant_cpu_to_le32 (1 << VALID_BIT)
-#define dma_done_ie	__constant_cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
+#define valid_bit	cpu_to_le32 (1 << VALID_BIT)
+#define dma_done_ie	cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
 
 /*-------------------------------------------------------------------------*/
 
@@ -425,7 +425,7 @@
 			return NULL;
 		}
 		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
+		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
 		td->dmadesc = td->dmaaddr;
 		req->td = td;
 	}
@@ -775,7 +775,7 @@
 	fill_dma_desc (ep, req, 1);
 
 	if (!use_dma_chaining)
-		req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN);
+		req->td->dmacount |= cpu_to_le32 (1 << END_OF_CHAIN);
 
 	start_queue (ep, tmp, req->td_dma);
 }
@@ -2407,9 +2407,9 @@
 
 			if (readl (&e->regs->ep_rsp)
 					& (1 << SET_ENDPOINT_HALT))
-				status = __constant_cpu_to_le32 (1);
+				status = cpu_to_le32 (1);
 			else
-				status = __constant_cpu_to_le32 (0);
+				status = cpu_to_le32 (0);
 
 			/* don't bother with a request object! */
 			writel (0, &dev->epregs [0].ep_irqenb);
@@ -2667,7 +2667,7 @@
 				req = list_entry (ep->queue.next,
 						struct net2280_request, queue);
 				dmacount = req->td->dmacount;
-				dmacount &= __constant_cpu_to_le32 (
+				dmacount &= cpu_to_le32 (
 						(1 << VALID_BIT)
 						| DMA_BYTE_COUNT_MASK);
 				if (dmacount && (dmacount & valid_bit) == 0)
@@ -2881,7 +2881,7 @@
 			goto done;
 		}
 		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
+		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
 		td->dmadesc = td->dmaaddr;
 		dev->ep [i].dummy = td;
 	}
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 5a3034f..2950015 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -225,12 +225,12 @@
 static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bcdUSB =		cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
-	.idVendor =		__constant_cpu_to_le16(PRINTER_VENDOR_NUM),
-	.idProduct =		__constant_cpu_to_le16(PRINTER_PRODUCT_NUM),
+	.idVendor =		cpu_to_le16(PRINTER_VENDOR_NUM),
+	.idProduct =		cpu_to_le16(PRINTER_PRODUCT_NUM),
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
 	.iSerialNumber =	STRING_SERIALNUM,
@@ -299,20 +299,20 @@
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512)
+	.wMaxPacketSize =	cpu_to_le16(512)
 };
 
 static struct usb_endpoint_descriptor hs_ep_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512)
+	.wMaxPacketSize =	cpu_to_le16(512)
 };
 
 static struct usb_qualifier_descriptor dev_qualifier = {
 	.bLength =		sizeof dev_qualifier,
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bcdUSB =		cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_PRINTER,
 	.bNumConfigurations =	1
 };
@@ -1406,16 +1406,16 @@
 			gadget->name);
 		/* unrecognized, but safe unless bulk is REALLY quirky */
 		device_desc.bcdDevice =
-			__constant_cpu_to_le16(0xFFFF);
+			cpu_to_le16(0xFFFF);
 	}
 	snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
 		init_utsname()->sysname, init_utsname()->release,
 		gadget->name);
 
 	device_desc.idVendor =
-		__constant_cpu_to_le16(PRINTER_VENDOR_NUM);
+		cpu_to_le16(PRINTER_VENDOR_NUM);
 	device_desc.idProduct =
-		__constant_cpu_to_le16(PRINTER_PRODUCT_NUM);
+		cpu_to_le16(PRINTER_PRODUCT_NUM);
 
 	/* support optional vendor/distro customization */
 	if (idVendor) {
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 990f40f..8cc676e 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -30,6 +30,7 @@
 #include <linux/proc_fs.h>
 #include <linux/clk.h>
 #include <linux/irq.h>
+#include <linux/gpio.h>
 
 #include <asm/byteorder.h>
 #include <mach/hardware.h>
@@ -278,7 +279,7 @@
 		goto err_queues;
 	eps = debugfs_create_file("epstate", 0400, root, udc,
 			&eps_dbg_fops);
-	if (!queues)
+	if (!eps)
 		goto err_eps;
 
 	udc->debugfs_root = root;
@@ -747,13 +748,13 @@
 }
 
 /**
- * ep_end_out_req - Ends control endpoint in request
+ * ep_end_out_req - Ends endpoint OUT request
  * @ep: physical endpoint
  * @req: pxa request
  *
  * Context: ep->lock held
  *
- * Ends endpoint in request (completes usb request).
+ * Ends endpoint OUT request (completes usb request).
  */
 static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
 {
@@ -762,13 +763,13 @@
 }
 
 /**
- * ep0_end_out_req - Ends control endpoint in request (ends data stage)
+ * ep0_end_out_req - Ends control endpoint OUT request (ends data stage)
  * @ep: physical endpoint
  * @req: pxa request
  *
  * Context: ep->lock held
  *
- * Ends control endpoint in request (completes usb request), and puts
+ * Ends control endpoint OUT request (completes usb request), and puts
  * control endpoint into idle state
  */
 static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
@@ -779,13 +780,13 @@
 }
 
 /**
- * ep_end_in_req - Ends endpoint out request
+ * ep_end_in_req - Ends endpoint IN request
  * @ep: physical endpoint
  * @req: pxa request
  *
  * Context: ep->lock held
  *
- * Ends endpoint out request (completes usb request).
+ * Ends endpoint IN request (completes usb request).
  */
 static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
 {
@@ -794,20 +795,18 @@
 }
 
 /**
- * ep0_end_in_req - Ends control endpoint out request (ends data stage)
+ * ep0_end_in_req - Ends control endpoint IN request (ends data stage)
  * @ep: physical endpoint
  * @req: pxa request
  *
  * Context: ep->lock held
  *
- * Ends control endpoint out request (completes usb request), and puts
+ * Ends control endpoint IN request (completes usb request), and puts
  * control endpoint into status state
  */
 static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
 {
-	struct pxa_udc *udc = ep->dev;
-
-	set_ep0state(udc, IN_STATUS_STAGE);
+	set_ep0state(ep->dev, IN_STATUS_STAGE);
 	ep_end_in_req(ep, req);
 }
 
@@ -1167,7 +1166,7 @@
 				ep_end_in_req(ep, req);
 			} else {
 				ep_err(ep, "got a request of %d bytes while"
-					"in state WATI_ACK_SET_CONF_INTERF\n",
+					"in state WAIT_ACK_SET_CONF_INTERF\n",
 					length);
 				ep_del_request(ep, req);
 				rc = -EL2HLT;
@@ -1213,30 +1212,26 @@
 	struct udc_usb_ep	*udc_usb_ep;
 	struct pxa27x_request	*req;
 	unsigned long		flags;
-	int			rc;
+	int			rc = -EINVAL;
 
 	if (!_ep)
-		return -EINVAL;
+		return rc;
 	udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
 	ep = udc_usb_ep->pxa_ep;
 	if (!ep || is_ep0(ep))
-		return -EINVAL;
+		return rc;
 
 	spin_lock_irqsave(&ep->lock, flags);
 
 	/* make sure it's actually queued on this endpoint */
 	list_for_each_entry(req, &ep->queue, queue) {
-		if (&req->req == _req)
+		if (&req->req == _req) {
+			req_done(ep, req, -ECONNRESET);
+			rc = 0;
 			break;
+		}
 	}
 
-	rc = -EINVAL;
-	if (&req->req != _req)
-		goto out;
-
-	rc = 0;
-	req_done(ep, req, -ECONNRESET);
-out:
 	spin_unlock_irqrestore(&ep->lock, flags);
 	return rc;
 }
@@ -1471,6 +1466,32 @@
 	.fifo_flush	= pxa_ep_fifo_flush,
 };
 
+/**
+ * dplus_pullup - Connect or disconnect pullup resistor to D+ pin
+ * @udc: udc device
+ * @on: 0 if disconnect pullup resistor, 1 otherwise
+ * Context: any
+ *
+ * Handle D+ pullup resistor, make the device visible to the usb bus, and
+ * declare it as a full speed usb device
+ */
+static void dplus_pullup(struct pxa_udc *udc, int on)
+{
+	if (on) {
+		if (gpio_is_valid(udc->mach->gpio_pullup))
+			gpio_set_value(udc->mach->gpio_pullup,
+				       !udc->mach->gpio_pullup_inverted);
+		if (udc->mach->udc_command)
+			udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+	} else {
+		if (gpio_is_valid(udc->mach->gpio_pullup))
+			gpio_set_value(udc->mach->gpio_pullup,
+				       udc->mach->gpio_pullup_inverted);
+		if (udc->mach->udc_command)
+			udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+	}
+	udc->pullup_on = on;
+}
 
 /**
  * pxa_udc_get_frame - Returns usb frame number
@@ -1500,21 +1521,145 @@
 	return 0;
 }
 
+static void udc_enable(struct pxa_udc *udc);
+static void udc_disable(struct pxa_udc *udc);
+
+/**
+ * should_enable_udc - Tells if UDC should be enabled
+ * @udc: udc device
+ * Context: any
+ *
+ * The UDC should be enabled if :
+
+ *  - the pullup resistor is connected
+ *  - and a gadget driver is bound
+ *  - and vbus is sensed (or no vbus sense is available)
+ *
+ * Returns 1 if UDC should be enabled, 0 otherwise
+ */
+static int should_enable_udc(struct pxa_udc *udc)
+{
+	int put_on;
+
+	put_on = ((udc->pullup_on) && (udc->driver));
+	put_on &= ((udc->vbus_sensed) || (!udc->transceiver));
+	return put_on;
+}
+
+/**
+ * should_disable_udc - Tells if UDC should be disabled
+ * @udc: udc device
+ * Context: any
+ *
+ * The UDC should be disabled if :
+ *  - the pullup resistor is not connected
+ *  - or no gadget driver is bound
+ *  - or no vbus is sensed (when vbus sesing is available)
+ *
+ * Returns 1 if UDC should be disabled
+ */
+static int should_disable_udc(struct pxa_udc *udc)
+{
+	int put_off;
+
+	put_off = ((!udc->pullup_on) || (!udc->driver));
+	put_off |= ((!udc->vbus_sensed) && (udc->transceiver));
+	return put_off;
+}
+
+/**
+ * pxa_udc_pullup - Offer manual D+ pullup control
+ * @_gadget: usb gadget using the control
+ * @is_active: 0 if disconnect, else connect D+ pullup resistor
+ * Context: !in_interrupt()
+ *
+ * Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup
+ */
+static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+	struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+	if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
+		return -EOPNOTSUPP;
+
+	dplus_pullup(udc, is_active);
+
+	if (should_enable_udc(udc))
+		udc_enable(udc);
+	if (should_disable_udc(udc))
+		udc_disable(udc);
+	return 0;
+}
+
+static void udc_enable(struct pxa_udc *udc);
+static void udc_disable(struct pxa_udc *udc);
+
+/**
+ * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc
+ * @_gadget: usb gadget
+ * @is_active: 0 if should disable the udc, 1 if should enable
+ *
+ * Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the
+ * udc, and deactivates D+ pullup resistor.
+ *
+ * Returns 0
+ */
+static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+	struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+	udc->vbus_sensed = is_active;
+	if (should_enable_udc(udc))
+		udc_enable(udc);
+	if (should_disable_udc(udc))
+		udc_disable(udc);
+
+	return 0;
+}
+
+/**
+ * pxa_udc_vbus_draw - Called by gadget driver after SET_CONFIGURATION completed
+ * @_gadget: usb gadget
+ * @mA: current drawn
+ *
+ * Context: !in_interrupt()
+ *
+ * Called after a configuration was chosen by a USB host, to inform how much
+ * current can be drawn by the device from VBus line.
+ *
+ * Returns 0 or -EOPNOTSUPP if no transceiver is handling the udc
+ */
+static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+	struct pxa_udc *udc;
+
+	udc = to_gadget_udc(_gadget);
+	if (udc->transceiver)
+		return otg_set_power(udc->transceiver, mA);
+	return -EOPNOTSUPP;
+}
+
 static const struct usb_gadget_ops pxa_udc_ops = {
 	.get_frame	= pxa_udc_get_frame,
 	.wakeup		= pxa_udc_wakeup,
-	/* current versions must always be self-powered */
+	.pullup		= pxa_udc_pullup,
+	.vbus_session	= pxa_udc_vbus_session,
+	.vbus_draw	= pxa_udc_vbus_draw,
 };
 
 /**
  * udc_disable - disable udc device controller
  * @udc: udc device
+ * Context: any
  *
  * Disables the udc device : disables clocks, udc interrupts, control endpoint
  * interrupts.
  */
 static void udc_disable(struct pxa_udc *udc)
 {
+	if (!udc->enabled)
+		return;
+
 	udc_writel(udc, UDCICR0, 0);
 	udc_writel(udc, UDCICR1, 0);
 
@@ -1523,8 +1668,8 @@
 
 	ep0_idle(udc);
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
-	if (udc->mach->udc_command)
-		udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+
+	udc->enabled = 0;
 }
 
 /**
@@ -1555,10 +1700,9 @@
 	}
 
 	/* USB endpoints init */
-	for (i = 0; i < NR_USB_ENDPOINTS; i++)
-		if (i != 0)
-			list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
-					&dev->gadget.ep_list);
+	for (i = 1; i < NR_USB_ENDPOINTS; i++)
+		list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
+				&dev->gadget.ep_list);
 }
 
 /**
@@ -1570,6 +1714,9 @@
  */
 static void udc_enable(struct pxa_udc *udc)
 {
+	if (udc->enabled)
+		return;
+
 	udc_writel(udc, UDCICR0, 0);
 	udc_writel(udc, UDCICR1, 0);
 	udc_clear_mask_UDCCR(udc, UDCCR_UDE);
@@ -1598,9 +1745,7 @@
 	/* enable ep0 irqs */
 	pio_irq_enable(&udc->pxa_ep[0]);
 
-	dev_info(udc->dev, "UDC connecting\n");
-	if (udc->mach->udc_command)
-		udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+	udc->enabled = 1;
 }
 
 /**
@@ -1612,6 +1757,9 @@
  * usb traffic follows until a disconnect is reported.  Then a host may connect
  * again, or the driver might get unbound.
  *
+ * Note that the udc is not automatically enabled. Check function
+ * should_enable_udc().
+ *
  * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
  */
 int usb_gadget_register_driver(struct usb_gadget_driver *driver)
@@ -1630,6 +1778,7 @@
 	/* first hook up the driver ... */
 	udc->driver = driver;
 	udc->gadget.dev.driver = &driver->driver;
+	dplus_pullup(udc, 1);
 
 	retval = device_add(&udc->gadget.dev);
 	if (retval) {
@@ -1645,9 +1794,21 @@
 	dev_dbg(udc->dev, "registered gadget driver '%s'\n",
 		driver->driver.name);
 
-	udc_enable(udc);
+	if (udc->transceiver) {
+		retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
+		if (retval) {
+			dev_err(udc->dev, "can't bind to transceiver\n");
+			goto transceiver_fail;
+		}
+	}
+
+	if (should_enable_udc(udc))
+		udc_enable(udc);
 	return 0;
 
+transceiver_fail:
+	if (driver->unbind)
+		driver->unbind(&udc->gadget);
 bind_fail:
 	device_del(&udc->gadget.dev);
 add_fail:
@@ -1699,14 +1860,17 @@
 
 	stop_activity(udc, driver);
 	udc_disable(udc);
+	dplus_pullup(udc, 0);
 
 	driver->unbind(&udc->gadget);
 	udc->driver = NULL;
 
 	device_del(&udc->gadget.dev);
-
 	dev_info(udc->dev, "unregistered gadget driver '%s'\n",
 		 driver->driver.name);
+
+	if (udc->transceiver)
+		return otg_set_peripheral(udc->transceiver, NULL);
 	return 0;
 }
 EXPORT_SYMBOL(usb_gadget_unregister_driver);
@@ -1823,14 +1987,14 @@
 	struct pxa27x_request	*req = NULL;
 	int			completed = 0;
 
+	if (!list_empty(&ep->queue))
+		req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+
 	udccsr0 = udc_ep_readl(ep, UDCCSR);
 	ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n",
 		EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR),
 		(fifo_irq << 1 | opc_irq));
 
-	if (!list_empty(&ep->queue))
-		req = list_entry(ep->queue.next, struct pxa27x_request, queue);
-
 	if (udccsr0 & UDCCSR0_SST) {
 		ep_dbg(ep, "clearing stall status\n");
 		nuke(ep, -EPIPE);
@@ -2212,7 +2376,7 @@
 {
 	struct resource *regs;
 	struct pxa_udc *udc = &memory;
-	int retval;
+	int retval = 0, gpio;
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs)
@@ -2223,6 +2387,20 @@
 
 	udc->dev = &pdev->dev;
 	udc->mach = pdev->dev.platform_data;
+	udc->transceiver = otg_get_transceiver();
+
+	gpio = udc->mach->gpio_pullup;
+	if (gpio_is_valid(gpio)) {
+		retval = gpio_request(gpio, "USB D+ pullup");
+		if (retval == 0)
+			gpio_direction_output(gpio,
+				       udc->mach->gpio_pullup_inverted);
+	}
+	if (retval) {
+		dev_err(&pdev->dev, "Couldn't request gpio %d : %d\n",
+			gpio, retval);
+		return retval;
+	}
 
 	udc->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(udc->clk)) {
@@ -2240,6 +2418,7 @@
 	device_initialize(&udc->gadget.dev);
 	udc->gadget.dev.parent = &pdev->dev;
 	udc->gadget.dev.dma_mask = NULL;
+	udc->vbus_sensed = 0;
 
 	the_controller = udc;
 	platform_set_drvdata(pdev, udc);
@@ -2273,14 +2452,21 @@
 static int __exit pxa_udc_remove(struct platform_device *_dev)
 {
 	struct pxa_udc *udc = platform_get_drvdata(_dev);
+	int gpio = udc->mach->gpio_pullup;
 
 	usb_gadget_unregister_driver(udc->driver);
 	free_irq(udc->irq, udc);
 	pxa_cleanup_debugfs(udc);
+	if (gpio_is_valid(gpio))
+		gpio_free(gpio);
 
+	otg_put_transceiver(udc->transceiver);
+
+	udc->transceiver = NULL;
 	platform_set_drvdata(_dev, NULL);
 	the_controller = NULL;
 	clk_put(udc->clk);
+	iounmap(udc->regs);
 
 	return 0;
 }
@@ -2319,6 +2505,8 @@
 	}
 
 	udc_disable(udc);
+	udc->pullup_resume = udc->pullup_on;
+	dplus_pullup(udc, 0);
 
 	return 0;
 }
@@ -2346,7 +2534,9 @@
 				ep->udccsr_value, ep->udccr_value);
 	}
 
-	udc_enable(udc);
+	dplus_pullup(udc, udc->pullup_resume);
+	if (should_enable_udc(udc))
+		udc_enable(udc);
 	/*
 	 * We do not handle OTG yet.
 	 *
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
index 1d1b7936..db58125 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -26,6 +26,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/usb/otg.h>
 
 /*
  * Register definitions
@@ -421,10 +422,14 @@
  * @driver: bound gadget (zero, g_ether, g_file_storage, ...)
  * @dev: device
  * @mach: machine info, used to activate specific GPIO
+ * @transceiver: external transceiver to handle vbus sense and D+ pullup
  * @ep0state: control endpoint state machine state
  * @stats: statistics on udc usage
  * @udc_usb_ep: array of usb endpoints offered by the gadget
  * @pxa_ep: array of pxa available endpoints
+ * @enabled: UDC was enabled by a previous udc_enable()
+ * @pullup_on: if pullup resistor connected to D+ pin
+ * @pullup_resume: if pullup resistor should be connected to D+ pin on resume
  * @config: UDC active configuration
  * @last_interface: UDC interface of the last SET_INTERFACE host request
  * @last_alternate: UDC altsetting of the last SET_INTERFACE host request
@@ -443,6 +448,7 @@
 	struct usb_gadget_driver		*driver;
 	struct device				*dev;
 	struct pxa2xx_udc_mach_info		*mach;
+	struct otg_transceiver			*transceiver;
 
 	enum ep0_state				ep0state;
 	struct udc_stats			stats;
@@ -450,6 +456,10 @@
 	struct udc_usb_ep			udc_usb_ep[NR_USB_ENDPOINTS];
 	struct pxa_ep				pxa_ep[NR_PXA_ENDPOINTS];
 
+	unsigned				enabled:1;
+	unsigned				pullup_on:1;
+	unsigned				pullup_resume:1;
+	unsigned				vbus_sensed:1;
 	unsigned				config:2;
 	unsigned				last_interface:3;
 	unsigned				last_alternate:3;
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 37879af..f46a609 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -87,12 +87,12 @@
 static struct usb_device_descriptor device_desc = {
 	.bLength =		USB_DT_DEVICE_SIZE,
 	.bDescriptorType =	USB_DT_DEVICE,
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bcdUSB =		cpu_to_le16(0x0200),
 	/* .bDeviceClass = f(use_acm) */
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
 	/* .bMaxPacketSize0 = f(hardware) */
-	.idVendor =		__constant_cpu_to_le16(GS_VENDOR_ID),
+	.idVendor =		cpu_to_le16(GS_VENDOR_ID),
 	/* .idProduct =	f(use_acm) */
 	/* .bcdDevice = f(hardware) */
 	/* .iManufacturer = DYNAMIC */
@@ -216,7 +216,7 @@
 		pr_warning("gs_bind: controller '%s' not recognized\n",
 			gadget->name);
 		device_desc.bcdDevice =
-			__constant_cpu_to_le16(GS_VERSION_NUM | 0x0099);
+			cpu_to_le16(GS_VERSION_NUM | 0x0099);
 	}
 
 	if (gadget_is_otg(cdev->gadget)) {
@@ -255,19 +255,19 @@
 		serial_config_driver.bConfigurationValue = 2;
 		device_desc.bDeviceClass = USB_CLASS_COMM;
 		device_desc.idProduct =
-				__constant_cpu_to_le16(GS_CDC_PRODUCT_ID);
+				cpu_to_le16(GS_CDC_PRODUCT_ID);
 	} else if (use_obex) {
 		serial_config_driver.label = "CDC OBEX config";
 		serial_config_driver.bConfigurationValue = 3;
 		device_desc.bDeviceClass = USB_CLASS_COMM;
 		device_desc.idProduct =
-			__constant_cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
+			cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
 	} else {
 		serial_config_driver.label = "Generic Serial config";
 		serial_config_driver.bConfigurationValue = 1;
 		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
 		device_desc.idProduct =
-				__constant_cpu_to_le16(GS_PRODUCT_ID);
+				cpu_to_le16(GS_PRODUCT_ID);
 	}
 	strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
 
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 53d5928..0a4d99a 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1092,7 +1092,7 @@
 	gs_tty_driver->init_termios.c_ispeed = 9600;
 	gs_tty_driver->init_termios.c_ospeed = 9600;
 
-	coding.dwDTERate = __constant_cpu_to_le32(9600);
+	coding.dwDTERate = cpu_to_le32(9600);
 	coding.bCharFormat = 8;
 	coding.bParityType = USB_CDC_NO_PARITY;
 	coding.bDataBits = USB_CDC_1_STOP_BITS;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 361d965..2d77240 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -102,22 +102,32 @@
 #ifndef	CONFIG_USB_ZERO_HNPTEST
 #define DRIVER_VENDOR_NUM	0x0525		/* NetChip */
 #define DRIVER_PRODUCT_NUM	0xa4a0		/* Linux-USB "Gadget Zero" */
+#define DEFAULT_AUTORESUME	0
 #else
 #define DRIVER_VENDOR_NUM	0x1a0a		/* OTG test device IDs */
 #define DRIVER_PRODUCT_NUM	0xbadd
+#define DEFAULT_AUTORESUME	5
 #endif
 
+/* If the optional "autoresume" mode is enabled, it provides good
+ * functional coverage for the "USBCV" test harness from USB-IF.
+ * It's always set if OTG mode is enabled.
+ */
+unsigned autoresume = DEFAULT_AUTORESUME;
+module_param(autoresume, uint, S_IRUGO);
+MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
+
 /*-------------------------------------------------------------------------*/
 
 static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bcdUSB =		cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
 
-	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_NUM),
-	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+	.idVendor =		cpu_to_le16(DRIVER_VENDOR_NUM),
+	.idProduct =		cpu_to_le16(DRIVER_PRODUCT_NUM),
 	.bNumConfigurations =	2,
 };
 
@@ -212,6 +222,47 @@
 
 /*-------------------------------------------------------------------------*/
 
+static struct timer_list	autoresume_timer;
+
+static void zero_autoresume(unsigned long _c)
+{
+	struct usb_composite_dev	*cdev = (void *)_c;
+	struct usb_gadget		*g = cdev->gadget;
+
+	/* unconfigured devices can't issue wakeups */
+	if (!cdev->config)
+		return;
+
+	/* Normally the host would be woken up for something
+	 * more significant than just a timer firing; likely
+	 * because of some direct user request.
+	 */
+	if (g->speed != USB_SPEED_UNKNOWN) {
+		int status = usb_gadget_wakeup(g);
+		INFO(cdev, "%s --> %d\n", __func__, status);
+	}
+}
+
+static void zero_suspend(struct usb_composite_dev *cdev)
+{
+	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
+		return;
+
+	if (autoresume) {
+		mod_timer(&autoresume_timer, jiffies + (HZ * autoresume));
+		DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
+	} else
+		DBG(cdev, "%s\n", __func__);
+}
+
+static void zero_resume(struct usb_composite_dev *cdev)
+{
+	DBG(cdev, "%s\n", __func__);
+	del_timer(&autoresume_timer);
+}
+
+/*-------------------------------------------------------------------------*/
+
 static int __init zero_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
@@ -239,17 +290,19 @@
 	strings_dev[STRING_SERIAL_IDX].id = id;
 	device_desc.iSerialNumber = id;
 
+	setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
+
 	/* Register primary, then secondary configuration.  Note that
 	 * SH3 only allows one config...
 	 */
 	if (loopdefault) {
-		loopback_add(cdev);
+		loopback_add(cdev, autoresume != 0);
 		if (!gadget_is_sh(gadget))
-			sourcesink_add(cdev);
+			sourcesink_add(cdev, autoresume != 0);
 	} else {
-		sourcesink_add(cdev);
+		sourcesink_add(cdev, autoresume != 0);
 		if (!gadget_is_sh(gadget))
-			loopback_add(cdev);
+			loopback_add(cdev, autoresume != 0);
 	}
 
 	gcnum = usb_gadget_controller_number(gadget);
@@ -265,7 +318,7 @@
 		 */
 		pr_warning("%s: controller '%s' not recognized\n",
 			longname, gadget->name);
-		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+		device_desc.bcdDevice = cpu_to_le16(0x9999);
 	}
 
 
@@ -278,11 +331,20 @@
 	return 0;
 }
 
+static int zero_unbind(struct usb_composite_dev *cdev)
+{
+	del_timer_sync(&autoresume_timer);
+	return 0;
+}
+
 static struct usb_composite_driver zero_driver = {
 	.name		= "zero",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
 	.bind		= zero_bind,
+	.unbind		= zero_unbind,
+	.suspend	= zero_suspend,
+	.resume		= zero_resume,
 };
 
 MODULE_AUTHOR("David Brownell");
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 2c63bfb..845479f 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -24,10 +24,7 @@
 	  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
 	  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
 	  If your USB host controller supports USB 2.0, you will likely want to
-	  configure this Host Controller Driver.  At the time of this writing, 
-	  the primary implementation of EHCI is a chip from NEC, widely available
-	  in add-on PCI cards, but implementations are in the works from other 
-	  vendors including Intel and Philips.  Motherboard support is appearing.
+	  configure this Host Controller Driver.
 
 	  EHCI controllers are packaged with "companion" host controllers (OHCI
 	  or UHCI) to handle USB 1.1 devices connected to root hub ports.  Ports
@@ -123,7 +120,7 @@
 
 config USB_ISP1760_HCD
 	tristate "ISP 1760 HCD support"
-	depends on USB && EXPERIMENTAL && (PCI || PPC_OF)
+	depends on USB && EXPERIMENTAL
 	---help---
 	  The ISP1760 chip is a USB 2.0 host controller.
 
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index e551bb3..f2618d1 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -110,6 +110,42 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void
+timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
+{
+	/* Don't override timeouts which shrink or (later) disable
+	 * the async ring; just the I/O watchdog.  Note that if a
+	 * SHRINK were pending, OFF would never be requested.
+	 */
+	if (timer_pending(&ehci->watchdog)
+			&& ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
+				& ehci->actions))
+		return;
+
+	if (!test_and_set_bit(action, &ehci->actions)) {
+		unsigned long t;
+
+		switch (action) {
+		case TIMER_IO_WATCHDOG:
+			t = EHCI_IO_JIFFIES;
+			break;
+		case TIMER_ASYNC_OFF:
+			t = EHCI_ASYNC_JIFFIES;
+			break;
+		/* case TIMER_ASYNC_SHRINK: */
+		default:
+			/* add a jiffie since we synch against the
+			 * 8 KHz uframe counter.
+			 */
+			t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
+			break;
+		}
+		mod_timer(&ehci->watchdog, t + jiffies);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
 /*
  * handshake - spin reading hc until handshake completes or fails
  * @ptr: address of hc register to be read
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 3712b92..1976b1b 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -333,12 +333,40 @@
 		token = hc32_to_cpu(ehci, qtd->hw_token);
 
 		/* always clean up qtds the hc de-activated */
+ retry_xacterr:
 		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) {
+
+				/* retry transaction errors until we
+				 * reach the software xacterr limit
+				 */
+				if ((token & QTD_STS_XACT) &&
+						QTD_CERR(token) == 0 &&
+						--qh->xacterrs > 0 &&
+						!urb->unlinked) {
+					ehci_dbg(ehci,
+	"detected XactErr len %zu/%zu retry %d\n",
+	qtd->length - QTD_LENGTH(token), qtd->length,
+	QH_XACTERR_MAX - qh->xacterrs);
+
+					/* reset the token in the qtd and the
+					 * qh overlay (which still contains
+					 * the qtd) so that we pick up from
+					 * where we left off
+					 */
+					token &= ~QTD_STS_HALT;
+					token |= QTD_STS_ACTIVE |
+							(EHCI_TUNE_CERR << 10);
+					qtd->hw_token = cpu_to_hc32(ehci,
+							token);
+					wmb();
+					qh->hw_token = cpu_to_hc32(ehci, token);
+					goto retry_xacterr;
+				}
 				stopped = 1;
 
 			/* magic dummy for some short reads; qh won't advance.
@@ -421,6 +449,9 @@
 		/* remove qtd; it's recycled after possible urb completion */
 		list_del (&qtd->qtd_list);
 		last = qtd;
+
+		/* reinit the xacterr counter for the next qtd */
+		qh->xacterrs = QH_XACTERR_MAX;
 	}
 
 	/* last urb's completion might still need calling */
@@ -862,6 +893,7 @@
 	head->qh_next.qh = qh;
 	head->hw_next = dma;
 
+	qh->xacterrs = QH_XACTERR_MAX;
 	qh->qh_state = QH_STATE_LINKED;
 	/* qtd completions reported later by interrupt */
 }
@@ -1095,7 +1127,8 @@
 	prev->qh_next = qh->qh_next;
 	wmb ();
 
-	if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) {
+	/* If the controller isn't running, we don't have to wait for it */
+	if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) {
 		/* if (unlikely (qh->reclaim != 0))
 		 *	this will recurse, probably not much
 		 */
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 07bcb93..ada5d2b 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -563,7 +563,7 @@
 	//   and this qh is active in the current uframe
 	//   (and overlay token SplitXstate is false?)
 	// THEN
-	//   qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */);
+	//   qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */);
 
 	/* high bandwidth, or otherwise part of every microframe */
 	if ((period = qh->period) == 0)
@@ -1536,7 +1536,7 @@
 					struct ehci_itd, itd_list);
 			list_move_tail (&itd->itd_list, &stream->td_list);
 			itd->stream = iso_stream_get (stream);
-			itd->urb = usb_get_urb (urb);
+			itd->urb = urb;
 			itd_init (ehci, stream, itd);
 		}
 
@@ -1645,7 +1645,7 @@
 	(void) disable_periodic(ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
-	if (unlikely (list_empty (&stream->td_list))) {
+	if (unlikely(list_is_singular(&stream->td_list))) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
 				-= stream->bandwidth;
 		ehci_vdbg (ehci,
@@ -1656,7 +1656,6 @@
 	iso_stream_put (ehci, stream);
 
 done:
-	usb_put_urb(urb);
 	itd->urb = NULL;
 	if (ehci->clock_frame != itd->frame || itd->index[7] != -1) {
 		/* OK to recycle this ITD now. */
@@ -1949,7 +1948,7 @@
 				struct ehci_sitd, sitd_list);
 		list_move_tail (&sitd->sitd_list, &stream->td_list);
 		sitd->stream = iso_stream_get (stream);
-		sitd->urb = usb_get_urb (urb);
+		sitd->urb = urb;
 
 		sitd_patch(ehci, stream, sitd, sched, packet);
 		sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
@@ -2034,7 +2033,7 @@
 	(void) disable_periodic(ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
-	if (list_empty (&stream->td_list)) {
+	if (list_is_singular(&stream->td_list)) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
 				-= stream->bandwidth;
 		ehci_vdbg (ehci,
@@ -2045,7 +2044,6 @@
 	iso_stream_put (ehci, stream);
 	/* OK to recycle this SITD now that its completion callback ran. */
 done:
-	usb_put_urb(urb);
 	sitd->urb = NULL;
 	sitd->stream = NULL;
 	list_move(&sitd->sitd_list, &stream->free_list);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 262b00c..6cff195 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -190,40 +190,6 @@
 	clear_bit (action, &ehci->actions);
 }
 
-static inline void
-timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
-{
-	/* Don't override timeouts which shrink or (later) disable
-	 * the async ring; just the I/O watchdog.  Note that if a
-	 * SHRINK were pending, OFF would never be requested.
-	 */
-	if (timer_pending(&ehci->watchdog)
-			&& ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
-				& ehci->actions))
-		return;
-
-	if (!test_and_set_bit (action, &ehci->actions)) {
-		unsigned long t;
-
-		switch (action) {
-		case TIMER_IO_WATCHDOG:
-			t = EHCI_IO_JIFFIES;
-			break;
-		case TIMER_ASYNC_OFF:
-			t = EHCI_ASYNC_JIFFIES;
-			break;
-		// case TIMER_ASYNC_SHRINK:
-		default:
-			/* add a jiffie since we synch against the
-			 * 8 KHz uframe counter.
-			 */
-			t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
-			break;
-		}
-		mod_timer(&ehci->watchdog, t + jiffies);
-	}
-}
-
 static void free_cached_itd_list(struct ehci_hcd *ehci);
 
 /*-------------------------------------------------------------------------*/
@@ -287,7 +253,7 @@
 
 /*
  * Now the following defines are not converted using the
- * __constant_cpu_to_le32() macro anymore, since we have to support
+ * cpu_to_le32() macro anymore, since we have to support
  * "dynamic" switching between be and le support, so that the driver
  * can be used on one system with SoC EHCI controller using big-endian
  * descriptors as well as a normal little-endian PCI EHCI controller.
@@ -376,6 +342,9 @@
 #define	QH_STATE_UNLINK_WAIT	4		/* LINKED and on reclaim q */
 #define	QH_STATE_COMPLETING	5		/* don't touch token.HALT */
 
+	u8			xacterrs;	/* XactErr retry counter */
+#define	QH_XACTERR_MAX		32		/* XactErr retry limit */
+
 	/* periodic schedule info */
 	u8			usecs;		/* intr bandwidth */
 	u8			gap_uf;		/* uframes split/csplit gap */
diff --git a/drivers/usb/host/fhci-dbg.c b/drivers/usb/host/fhci-dbg.c
index 34e14ed..ea8a425 100644
--- a/drivers/usb/host/fhci-dbg.c
+++ b/drivers/usb/host/fhci-dbg.c
@@ -108,7 +108,7 @@
 {
 	struct device *dev = fhci_to_hcd(fhci)->self.controller;
 
-	fhci->dfs_root = debugfs_create_dir(dev->bus_id, NULL);
+	fhci->dfs_root = debugfs_create_dir(dev_name(dev), NULL);
 	if (!fhci->dfs_root) {
 		WARN_ON(1);
 		return;
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index ba622cc..0951818 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -583,7 +583,7 @@
 	if (sprop && strcmp(sprop, "host"))
 		return -ENODEV;
 
-	hcd = usb_create_hcd(&fhci_driver, dev, dev->bus_id);
+	hcd = usb_create_hcd(&fhci_driver, dev, dev_name(dev));
 	if (!hcd) {
 		dev_err(dev, "could not create hcd\n");
 		return -ENOMEM;
@@ -650,7 +650,7 @@
 			}
 		}
 
-		ret = gpio_request(gpio, dev->bus_id);
+		ret = gpio_request(gpio, dev_name(dev));
 		if (ret) {
 			dev_err(dev, "failed to request gpio %d", i);
 			goto err_gpios;
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index 8582236..cbf30e5 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -464,8 +464,7 @@
 			port_idx << 8 | iface_no,
 			keyd, keyd_len, 1000 /* FIXME: arbitrary */);
 
-	memset(keyd, 0, sizeof(*keyd));	/* clear keys etc. */
-	kfree(keyd);
+	kzfree(keyd); /* clear keys etc. */
 	return result;
 }
 
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 4dda31b..a2b3054 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -772,7 +772,7 @@
 		break;
 	case PIPE_INTERRUPT:
 		urb->interval = ep->period;
-		ep->length = min((int)ep->maxpacket,
+		ep->length = min_t(u32, ep->maxpacket,
 				 urb->transfer_buffer_length);
 
 		/* urb submitted for already existing endpoint */
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index aa211ba..12db961 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -563,7 +563,7 @@
 */
 static inline void dump_ptd(struct ptd *ptd)
 {
-	printk("td: %x %d%c%d %d,%d,%d  %x %x%x%x\n",
+	printk(KERN_WARNING "td: %x %d%c%d %d,%d,%d  %x %x%x%x\n",
 	       PTD_GET_CC(ptd), PTD_GET_FA(ptd),
 	       PTD_DIR_STR(ptd), PTD_GET_EP(ptd),
 	       PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd),
@@ -576,7 +576,7 @@
 	int k;
 
 	if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) {
-		printk("-> ");
+		printk(KERN_WARNING "-> ");
 		for (k = 0; k < PTD_GET_LEN(ptd); ++k)
 			printk("%02x ", ((u8 *) buf)[k]);
 		printk("\n");
@@ -588,13 +588,13 @@
 	int k;
 
 	if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) {
-		printk("<- ");
+		printk(KERN_WARNING "<- ");
 		for (k = 0; k < PTD_GET_COUNT(ptd); ++k)
 			printk("%02x ", ((u8 *) buf)[k]);
 		printk("\n");
 	}
 	if (PTD_GET_LAST(ptd))
-		printk("-\n");
+		printk(KERN_WARNING "-\n");
 }
 
 #else
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index b899f1a..cd07ea3 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -644,7 +644,7 @@
 
 	if (urb->dev->speed != USB_SPEED_HIGH) {
 		/* split */
-		ptd->dw5 = __constant_cpu_to_le32(0x1c);
+		ptd->dw5 = cpu_to_le32(0x1c);
 
 		if (qh->period >= 32)
 			period = qh->period / 2;
@@ -819,6 +819,13 @@
 	u32 atl_regs, payload;
 	u32 buffstatus;
 
+	/*
+	 * When this function is called from the interrupt handler to enqueue
+	 * a follow-up packet, the SKIP register gets written and read back
+	 * almost immediately. With ISP1761, this register requires a delay of
+	 * 195ns between a write and subsequent read (see section 15.1.1.3).
+	 */
+	ndelay(195);
 	skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
 
 	BUG_ON(!skip_map);
@@ -853,6 +860,13 @@
 	u32 int_regs, payload;
 	u32 buffstatus;
 
+	/*
+	 * When this function is called from the interrupt handler to enqueue
+	 * a follow-up packet, the SKIP register gets written and read back
+	 * almost immediately. With ISP1761, this register requires a delay of
+	 * 195ns between a write and subsequent read (see section 15.1.1.3).
+	 */
+	ndelay(195);
 	skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG);
 
 	BUG_ON(!skip_map);
@@ -1054,7 +1068,7 @@
 			priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
 					atl_regs, sizeof(ptd));
 
-			ptd.dw0 |= __constant_cpu_to_le32(PTD_VALID);
+			ptd.dw0 |= cpu_to_le32(PTD_VALID);
 			priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
 					atl_regs, sizeof(ptd));
 
@@ -2235,9 +2249,10 @@
 	kmem_cache_destroy(qh_cachep);
 }
 
-struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
-		u64 irqflags, struct device *dev, const char *busname,
-		unsigned int devflags)
+struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len,
+				 int irq, unsigned long irqflags,
+				 struct device *dev, const char *busname,
+				 unsigned int devflags)
 {
 	struct usb_hcd *hcd;
 	struct isp1760_hcd *priv;
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h
index a9daea5..462f494 100644
--- a/drivers/usb/host/isp1760-hcd.h
+++ b/drivers/usb/host/isp1760-hcd.h
@@ -2,9 +2,10 @@
 #define _ISP1760_HCD_H_
 
 /* exports for if */
-struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
-		u64 irqflags, struct device *dev, const char *busname,
-		unsigned int devflags);
+struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len,
+				 int irq, unsigned long irqflags,
+				 struct device *dev, const char *busname,
+				 unsigned int devflags);
 int init_kmem_once(void);
 void deinit_kmem_cache(void);
 
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index 4cf7ca4..3fa3a17 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -10,6 +10,7 @@
 
 #include <linux/usb.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 #include "../core/hcd.h"
 #include "isp1760-hcd.h"
@@ -300,39 +301,101 @@
 };
 #endif
 
+static int __devinit isp1760_plat_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct usb_hcd *hcd;
+	struct resource *mem_res;
+	struct resource *irq_res;
+	resource_size_t mem_size;
+	unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED;
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_res) {
+		pr_warning("isp1760: Memory resource not available\n");
+		ret = -ENODEV;
+		goto out;
+	}
+	mem_size = resource_size(mem_res);
+	if (!request_mem_region(mem_res->start, mem_size, "isp1760")) {
+		pr_warning("isp1760: Cannot reserve the memory resource\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq_res) {
+		pr_warning("isp1760: IRQ resource not available\n");
+		return -ENODEV;
+	}
+	irqflags |= irq_res->flags & IRQF_TRIGGER_MASK;
+
+	hcd = isp1760_register(mem_res->start, mem_size, irq_res->start,
+			       irqflags, &pdev->dev, dev_name(&pdev->dev), 0);
+	if (IS_ERR(hcd)) {
+		pr_warning("isp1760: Failed to register the HCD device\n");
+		ret = -ENODEV;
+		goto cleanup;
+	}
+
+	pr_info("ISP1760 USB device initialised\n");
+	return ret;
+
+cleanup:
+	release_mem_region(mem_res->start, mem_size);
+out:
+	return ret;
+}
+
+static int __devexit isp1760_plat_remove(struct platform_device *pdev)
+{
+	struct resource *mem_res;
+	resource_size_t mem_size;
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mem_size = resource_size(mem_res);
+	release_mem_region(mem_res->start, mem_size);
+
+	return 0;
+}
+
+static struct platform_driver isp1760_plat_driver = {
+	.probe	= isp1760_plat_probe,
+	.remove	= isp1760_plat_remove,
+	.driver	= {
+		.name	= "isp1760",
+	},
+};
+
 static int __init isp1760_init(void)
 {
-	int ret;
+	int ret, any_ret = -ENODEV;
 
 	init_kmem_once();
 
+	ret = platform_driver_register(&isp1760_plat_driver);
+	if (!ret)
+		any_ret = 0;
 #ifdef CONFIG_PPC_OF
 	ret = of_register_platform_driver(&isp1760_of_driver);
-	if (ret) {
-		deinit_kmem_cache();
-		return ret;
-	}
+	if (!ret)
+		any_ret = 0;
 #endif
 #ifdef CONFIG_PCI
 	ret = pci_register_driver(&isp1761_pci_driver);
-	if (ret)
-		goto unreg_of;
+	if (!ret)
+		any_ret = 0;
 #endif
-	return ret;
 
-#ifdef CONFIG_PCI
-unreg_of:
-#endif
-#ifdef CONFIG_PPC_OF
-	of_unregister_platform_driver(&isp1760_of_driver);
-#endif
-	deinit_kmem_cache();
-	return ret;
+	if (any_ret)
+		deinit_kmem_cache();
+	return any_ret;
 }
 module_init(isp1760_init);
 
 static void __exit isp1760_exit(void)
 {
+	platform_driver_unregister(&isp1760_plat_driver);
 #ifdef CONFIG_PPC_OF
 	of_unregister_platform_driver(&isp1760_of_driver);
 #endif
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 5cf5f1e..25db704 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -997,7 +997,7 @@
 #define SA1111_DRIVER		ohci_hcd_sa1111_driver
 #endif
 
-#ifdef CONFIG_ARCH_S3C2410
+#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX)
 #include "ohci-s3c2410.c"
 #define PLATFORM_DRIVER		ohci_hcd_s3c2410_driver
 #endif
@@ -1049,7 +1049,8 @@
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7763)
+    defined(CONFIG_CPU_SUBTYPE_SH7763) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7786)
 #include "ohci-sh.c"
 #define PLATFORM_DRIVER		ohci_hcd_sh_driver
 #endif
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index f46af7a..a68af2d 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -21,9 +21,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-
-#include <mach/hardware.h>
-#include <mach/usb-control.h>
+#include <plat/usb-control.h>
 
 #define valid_port(idx) ((idx) == 1 || (idx) == 2)
 
@@ -372,7 +370,7 @@
 
 	usb_clk = clk_get(&dev->dev, "usb-bus-host");
 	if (IS_ERR(usb_clk)) {
-		dev_err(&dev->dev, "cannot get usb-host clock\n");
+		dev_err(&dev->dev, "cannot get usb-bus-host clock\n");
 		retval = -ENOENT;
 		goto err_clk;
 	}
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index 75548f7..5ac489e 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -845,14 +845,14 @@
 		is_out = !(qtd->hw_token & cpu_to_le32(1 << 8));
 		epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f;
 		if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) {
-			qh->hw_token &= ~__constant_cpu_to_le32(QTD_TOGGLE);
+			qh->hw_token &= ~cpu_to_le32(QTD_TOGGLE);
 			usb_settoggle(qh->dev, epnum, is_out, 1);
 		}
 	}
 
 	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
 	wmb();
-	qh->hw_token &= __constant_cpu_to_le32(QTD_TOGGLE | QTD_STS_PING);
+	qh->hw_token &= cpu_to_le32(QTD_TOGGLE | QTD_STS_PING);
 }
 
 /* If it weren't for a common silicon quirk (writing the dummy into the qh
@@ -937,7 +937,7 @@
 		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv;
 
 		/* S-mask in a QH means it's an interrupt urb */
-		if ((qh->hw_info2 & __constant_cpu_to_le32(QH_SMASK)) != 0) {
+		if ((qh->hw_info2 & cpu_to_le32(QH_SMASK)) != 0) {
 
 			/* ... update hc-wide periodic stats (for usbfs) */
 			oxu_to_hcd(oxu)->self.bandwidth_int_reqs--;
@@ -981,7 +981,7 @@
 static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh);
 static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh);
 
-#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
+#define HALT_BIT cpu_to_le32(QTD_STS_HALT)
 
 /* Process and free completed qtds for a qh, returning URBs to drivers.
  * Chases up to qh->hw_current.  Returns number of completions called,
@@ -1160,7 +1160,7 @@
 			/* should be rare for periodic transfers,
 			 * except maybe high bandwidth ...
 			 */
-			if ((__constant_cpu_to_le32(QH_SMASK)
+			if ((cpu_to_le32(QH_SMASK)
 					& qh->hw_info2) != 0) {
 				intr_deschedule(oxu, qh);
 				(void) qh_schedule(oxu, qh);
@@ -1350,7 +1350,7 @@
 	}
 
 	/* by default, enable interrupt on urb completion */
-		qtd->hw_token |= __constant_cpu_to_le32(QTD_IOC);
+		qtd->hw_token |= cpu_to_le32(QTD_IOC);
 	return head;
 
 cleanup:
@@ -1539,7 +1539,7 @@
 	/* qtd completions reported later by interrupt */
 }
 
-#define	QH_ADDR_MASK	__constant_cpu_to_le32(0x7f)
+#define	QH_ADDR_MASK	cpu_to_le32(0x7f)
 
 /*
  * For control/bulk/interrupt, return QH with these TDs appended.
@@ -2012,7 +2012,7 @@
 	 *   and this qh is active in the current uframe
 	 *   (and overlay token SplitXstate is false?)
 	 * THEN
-	 *   qh->hw_info1 |= __constant_cpu_to_le32(1 << 7 "ignore");
+	 *   qh->hw_info1 |= cpu_to_le32(1 << 7 "ignore");
 	 */
 
 	/* high bandwidth, or otherwise part of every microframe */
@@ -2057,7 +2057,7 @@
 	 * active high speed queues may need bigger delays...
 	 */
 	if (list_empty(&qh->qtd_list)
-		|| (__constant_cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0)
+		|| (cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0)
 		wait = 2;
 	else
 		wait = 55;	/* worst case: 3 * 1024 */
@@ -2183,10 +2183,10 @@
 		qh->start = frame;
 
 		/* reset S-frame and (maybe) C-frame masks */
-		qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK));
+		qh->hw_info2 &= cpu_to_le32(~(QH_CMASK | QH_SMASK));
 		qh->hw_info2 |= qh->period
 			? cpu_to_le32(1 << uframe)
-			: __constant_cpu_to_le32(QH_SMASK);
+			: cpu_to_le32(QH_SMASK);
 		qh->hw_info2 |= c_mask;
 	} else
 		oxu_dbg(oxu, "reused qh %p schedule\n", qh);
@@ -2684,7 +2684,7 @@
 	oxu->urb_len = 0;
 
 	/* FIMXE */
-	hcd->self.controller->dma_mask = 0UL;
+	hcd->self.controller->dma_mask = NULL;
 
 	if (oxu->is_otg) {
 		oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET;
diff --git a/drivers/usb/host/oxu210hp.h b/drivers/usb/host/oxu210hp.h
index 8910e27..1c216ad 100644
--- a/drivers/usb/host/oxu210hp.h
+++ b/drivers/usb/host/oxu210hp.h
@@ -235,21 +235,21 @@
 } __attribute__ ((aligned(32)));
 
 /* mask NakCnt+T in qh->hw_alt_next */
-#define QTD_MASK __constant_cpu_to_le32 (~0x1f)
+#define QTD_MASK cpu_to_le32 (~0x1f)
 
 #define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1)
 
 /* Type tag from {qh, itd, sitd, fstn}->hw_next */
-#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
+#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1))
 
 /* values for that type tag */
-#define Q_TYPE_QH	__constant_cpu_to_le32 (1 << 1)
+#define Q_TYPE_QH	cpu_to_le32 (1 << 1)
 
 /* next async queue entry, or pointer to interrupt/periodic QH */
 #define	QH_NEXT(dma)	(cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
 
 /* for periodic/async schedules and qtd lists, mark end of list */
-#define	EHCI_LIST_END	__constant_cpu_to_le32(1) /* "null pointer" to hw */
+#define	EHCI_LIST_END	cpu_to_le32(1) /* "null pointer" to hw */
 
 /*
  * Entries in periodic shadow table are pointers to one of four kinds
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 75b6984..033c284 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -234,7 +234,7 @@
 	 */
 	hcc_params = readl(base + EHCI_HCC_PARAMS);
 	offset = (hcc_params >> 8) & 0xff;
-	while (offset && count--) {
+	while (offset && --count) {
 		u32		cap;
 		int		msec;
 
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 3190412..f1626e5 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -660,9 +660,9 @@
 	u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min;
 
 	memset(array, 0, sizeof(array));
-	switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	switch (usb_endpoint_type(ep)) {
 	case USB_ENDPOINT_XFER_BULK:
-		if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+		if (usb_endpoint_dir_in(ep))
 			array[i++] = 4;
 		else {
 			array[i++] = 3;
@@ -670,7 +670,7 @@
 		}
 		break;
 	case USB_ENDPOINT_XFER_INT:
-		if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+		if (usb_endpoint_dir_in(ep)) {
 			array[i++] = 6;
 			array[i++] = 7;
 			array[i++] = 8;
@@ -678,7 +678,7 @@
 			array[i++] = 9;
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
-		if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+		if (usb_endpoint_dir_in(ep))
 			array[i++] = 2;
 		else
 			array[i++] = 1;
@@ -928,10 +928,9 @@
 
 	info.pipenum = get_empty_pipenum(r8a66597, ep);
 	info.address = get_urb_to_r8a66597_addr(r8a66597, urb);
-	info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	info.epnum = usb_endpoint_num(ep);
 	info.maxpacket = le16_to_cpu(ep->wMaxPacketSize);
-	info.type = get_r8a66597_type(ep->bmAttributes
-				      & USB_ENDPOINT_XFERTYPE_MASK);
+	info.type = get_r8a66597_type(usb_endpoint_type(ep));
 	info.bufnum = get_bufnum(info.pipenum);
 	info.buf_bsize = get_buf_bsize(info.pipenum);
 	if (info.type == R8A66597_BULK) {
@@ -941,7 +940,7 @@
 		info.interval = get_interval(urb, ep->bInterval);
 		info.timer_interval = get_timer_interval(urb, ep->bInterval);
 	}
-	if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+	if (usb_endpoint_dir_in(ep))
 		info.dir_in = 1;
 	else
 		info.dir_in = 0;
@@ -1014,6 +1013,9 @@
 
 	r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
 	r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
+
+	if (r8a66597->bus_suspended)
+		usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
 }
 
 /* this function must be called with interrupt disabled */
@@ -1395,7 +1397,7 @@
 			   (int)urb->iso_frame_desc[td->iso_cnt].length);
 	} else {
 		buf = (u16 *)(urb->transfer_buffer + urb->actual_length);
-		size = min((int)bufsize,
+		size = min_t(u32, bufsize,
 			   urb->transfer_buffer_length - urb->actual_length);
 	}
 
@@ -1615,6 +1617,11 @@
 			r8a66597_bclr(r8a66597, DTCHE, INTENB2);
 			r8a66597_usb_disconnect(r8a66597, 1);
 		}
+		if (mask2 & BCHG) {
+			r8a66597_write(r8a66597, ~BCHG, INTSTS2);
+			r8a66597_bclr(r8a66597, BCHGE, INTENB2);
+			usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
+		}
 	}
 
 	if (mask1) {
@@ -1630,6 +1637,12 @@
 			r8a66597_bclr(r8a66597, DTCHE, INTENB1);
 			r8a66597_usb_disconnect(r8a66597, 0);
 		}
+		if (mask1 & BCHG) {
+			r8a66597_write(r8a66597, ~BCHG, INTSTS1);
+			r8a66597_bclr(r8a66597, BCHGE, INTENB1);
+			usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
+		}
+
 		if (mask1 & SIGN) {
 			r8a66597_write(r8a66597, ~SIGN, INTSTS1);
 			status = get_urb_error(r8a66597, 0);
@@ -2141,7 +2154,7 @@
 
 		switch (wValue) {
 		case USB_PORT_FEAT_ENABLE:
-			rh->port &= (1 << USB_PORT_FEAT_POWER);
+			rh->port &= ~(1 << USB_PORT_FEAT_POWER);
 			break;
 		case USB_PORT_FEAT_SUSPEND:
 			break;
@@ -2213,6 +2226,68 @@
 	return ret;
 }
 
+#if defined(CONFIG_PM)
+static int r8a66597_bus_suspend(struct usb_hcd *hcd)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	int port;
+
+	dbg("%s", __func__);
+
+	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+		unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+		if (!(rh->port & (1 << USB_PORT_FEAT_ENABLE)))
+			continue;
+
+		dbg("suspend port = %d", port);
+		r8a66597_bclr(r8a66597, UACT, dvstctr_reg);	/* suspend */
+		rh->port |= 1 << USB_PORT_FEAT_SUSPEND;
+
+		if (rh->dev->udev->do_remote_wakeup) {
+			msleep(3);	/* waiting last SOF */
+			r8a66597_bset(r8a66597, RWUPE, dvstctr_reg);
+			r8a66597_write(r8a66597, ~BCHG, get_intsts_reg(port));
+			r8a66597_bset(r8a66597, BCHGE, get_intenb_reg(port));
+		}
+	}
+
+	r8a66597->bus_suspended = 1;
+
+	return 0;
+}
+
+static int r8a66597_bus_resume(struct usb_hcd *hcd)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	int port;
+
+	dbg("%s", __func__);
+
+	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+		unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+		if (!(rh->port & (1 << USB_PORT_FEAT_SUSPEND)))
+			continue;
+
+		dbg("resume port = %d", port);
+		rh->port &= ~(1 << USB_PORT_FEAT_SUSPEND);
+		rh->port |= 1 << USB_PORT_FEAT_C_SUSPEND;
+		r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
+		msleep(50);
+		r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
+	}
+
+	return 0;
+
+}
+#else
+#define	r8a66597_bus_suspend	NULL
+#define	r8a66597_bus_resume	NULL
+#endif
+
 static struct hc_driver r8a66597_hc_driver = {
 	.description =		hcd_name,
 	.hcd_priv_size =	sizeof(struct r8a66597),
@@ -2243,16 +2318,39 @@
 	 */
 	.hub_status_data =	r8a66597_hub_status_data,
 	.hub_control =		r8a66597_hub_control,
+	.bus_suspend =		r8a66597_bus_suspend,
+	.bus_resume =		r8a66597_bus_resume,
 };
 
 #if defined(CONFIG_PM)
 static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
 {
+	struct r8a66597		*r8a66597 = dev_get_drvdata(&pdev->dev);
+	int port;
+
+	dbg("%s", __func__);
+
+	disable_controller(r8a66597);
+
+	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+		rh->port = 0x00000000;
+	}
+
 	return 0;
 }
 
 static int r8a66597_resume(struct platform_device *pdev)
 {
+	struct r8a66597		*r8a66597 = dev_get_drvdata(&pdev->dev);
+	struct usb_hcd		*hcd = r8a66597_to_hcd(r8a66597);
+
+	dbg("%s", __func__);
+
+	enable_controller(r8a66597);
+	usb_root_hub_lost_power(hcd->self.root_hub);
+
 	return 0;
 }
 #else	/* if defined(CONFIG_PM) */
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index ecacde4..f49208f 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -504,6 +504,8 @@
 
 	struct list_head child_device;
 	unsigned long child_connect_map[4];
+
+	unsigned bus_suspended:1;
 };
 
 static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd)
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index e106e9d..a949259 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -230,7 +230,7 @@
 	writeb(usb_pipedevice(urb->pipe), data_reg);
 
 	sl811_write(sl811, bank + SL11H_HOSTCTLREG, control);
-	ep->length = min((int)len,
+	ep->length = min_t(u32, len,
 			urb->transfer_buffer_length - urb->actual_length);
 	PACKET("IN%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "",
 			!!usb_gettoggle(urb->dev, ep->epnum, 0), ep, len);
@@ -255,7 +255,7 @@
 	buf = urb->transfer_buffer + urb->actual_length;
 	prefetch(buf);
 
-	len = min((int)ep->maxpacket,
+	len = min_t(u32, ep->maxpacket,
 			urb->transfer_buffer_length - urb->actual_length);
 
 	if (!(control & SL11H_HCTLMASK_ISOCH)
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 20cc58b..e52b954 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -118,7 +118,9 @@
 	}
 
 	out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
-	out += sprintf(out, " Actlen=%d", urbp->urb->actual_length);
+	out += sprintf(out, " Actlen=%d%s", urbp->urb->actual_length,
+			(urbp->qh->type == USB_ENDPOINT_XFER_CONTROL ?
+				"-8" : ""));
 
 	if (urbp->urb->unlinked)
 		out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked);
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 7d01c56..26bd1b2 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -73,11 +73,11 @@
 #define   USBLEGSUP_RWC		0x8f00	/* the R/WC bits */
 #define   USBLEGSUP_RO		0x5040	/* R/O and reserved bits */
 
-#define UHCI_PTR_BITS		__constant_cpu_to_le32(0x000F)
-#define UHCI_PTR_TERM		__constant_cpu_to_le32(0x0001)
-#define UHCI_PTR_QH		__constant_cpu_to_le32(0x0002)
-#define UHCI_PTR_DEPTH		__constant_cpu_to_le32(0x0004)
-#define UHCI_PTR_BREADTH	__constant_cpu_to_le32(0x0000)
+#define UHCI_PTR_BITS		cpu_to_le32(0x000F)
+#define UHCI_PTR_TERM		cpu_to_le32(0x0001)
+#define UHCI_PTR_QH		cpu_to_le32(0x0002)
+#define UHCI_PTR_DEPTH		cpu_to_le32(0x0004)
+#define UHCI_PTR_BREADTH	cpu_to_le32(0x0000)
 
 #define UHCI_NUMFRAMES		1024	/* in the frame list [array] */
 #define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 5631d89..3e5807d 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -402,7 +402,7 @@
 		/* Otherwise all the toggles in the URB have to be switched */
 		} else {
 			list_for_each_entry(td, &urbp->td_list, list) {
-				td->token ^= __constant_cpu_to_le32(
+				td->token ^= cpu_to_le32(
 							TD_TOKEN_TOGGLE);
 				toggle ^= 1;
 			}
@@ -883,7 +883,7 @@
 
 	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
 	wmb();
-	qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
+	qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE);
 	qh->dummy_td = td;
 
 	/* Low-speed transfers get a different queue, and won't hog the bus.
@@ -899,8 +899,6 @@
 	}
 	if (qh->state != QH_STATE_ACTIVE)
 		qh->skel = skel;
-
-	urb->actual_length = -8;	/* Account for the SETUP packet */
 	return 0;
 
 nomem:
@@ -1003,7 +1001,7 @@
 	 * fast side but not enough to justify delaying an interrupt
 	 * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
 	 * flag setting. */
-	td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
+	td->status |= cpu_to_le32(TD_CTRL_IOC);
 
 	/*
 	 * Build the new dummy TD and activate the old one
@@ -1015,7 +1013,7 @@
 
 	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
 	wmb();
-	qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
+	qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE);
 	qh->dummy_td = td;
 
 	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
@@ -1317,7 +1315,7 @@
 	}
 
 	/* Set the interrupt-on-completion flag on the last packet. */
-	td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
+	td->status |= cpu_to_le32(TD_CTRL_IOC);
 
 	/* Add the TDs to the frame list */
 	frame = urb->start_frame;
@@ -1494,11 +1492,10 @@
 
 	if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
 
-		/* urb->actual_length < 0 means the setup transaction didn't
-		 * complete successfully.  Either it failed or the URB was
-		 * unlinked first.  Regardless, don't confuse people with a
-		 * negative length. */
-		urb->actual_length = max(urb->actual_length, 0);
+		/* Subtract off the length of the SETUP packet from
+		 * urb->actual_length.
+		 */
+		urb->actual_length -= min_t(u32, 8, urb->actual_length);
 	}
 
 	/* When giving back the first URB in an Isochronous queue,
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 878c77c..eca355d 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -188,7 +188,7 @@
 		.bDescriptorType =	0,
 		.bEndpointAddress =	0x01,
 		.bmAttributes = 	0x02,
-		.wMaxPacketSize =	__constant_cpu_to_le16(8),
+		.wMaxPacketSize =	cpu_to_le16(8),
 		.bInterval = 		0,
 		.bRefresh = 		0,
 		.bSynchAddress = 	0,
@@ -198,7 +198,7 @@
 		.bDescriptorType = 	0,
 		.bEndpointAddress = 	0x82,
 		.bmAttributes = 	0x03,
-		.wMaxPacketSize = 	__constant_cpu_to_le16(8),
+		.wMaxPacketSize = 	cpu_to_le16(8),
 		.bInterval = 		0,
 		.bRefresh = 		0,
 		.bSynchAddress = 	0,
@@ -208,7 +208,7 @@
 		.bDescriptorType = 	0,
 		.bEndpointAddress = 	0x03,
 		.bmAttributes = 	0x02,
-		.wMaxPacketSize = 	__constant_cpu_to_le16(64),
+		.wMaxPacketSize = 	cpu_to_le16(64),
 		.bInterval = 		0,
 		.bRefresh = 		0,
 		.bSynchAddress = 	0,
@@ -218,7 +218,7 @@
 		.bDescriptorType = 	0,
 		.bEndpointAddress = 	0x84,
 		.bmAttributes = 	0x02,
-		.wMaxPacketSize = 	__constant_cpu_to_le16(64),
+		.wMaxPacketSize = 	cpu_to_le16(64),
 		.bInterval = 		0,
 		.bRefresh = 		0,
 		.bSynchAddress = 	0,
@@ -499,6 +499,7 @@
 	retval = usb_register_dev(intf, &mdc800_class);
 	if (retval) {
 		dev_err(&intf->dev, "Not able to get a minor for this device.\n");
+		mutex_unlock(&mdc800->io_lock);
 		return -ENODEV;
 	}
 
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index e463db5..a68d91a 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -135,45 +135,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called cytherm.
 
-config USB_PHIDGET
-	tristate "USB Phidgets drivers"
-	depends on USB
-	help
-	  Say Y here to enable the various drivers for devices from
-	  Phidgets inc.
-
-config USB_PHIDGETKIT
-	tristate "USB PhidgetInterfaceKit support"
-	depends on USB_PHIDGET
-	help
-	  Say Y here if you want to connect a PhidgetInterfaceKit USB device
-	  from Phidgets Inc.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called phidgetkit.
-
-config USB_PHIDGETMOTORCONTROL
-	tristate "USB PhidgetMotorControl support"
-	depends on USB_PHIDGET
-	help
-	  Say Y here if you want to connect a PhidgetMotorControl USB device
-	  from Phidgets Inc.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called phidgetmotorcontrol.
-
-config USB_PHIDGETSERVO
-	tristate "USB PhidgetServo support"
-	depends on USB_PHIDGET
-	help
-	  Say Y here if you want to connect an 1 or 4 Motor PhidgetServo 
-	  servo controller version 2.0 or 3.0.
-
-	  Phidgets Inc. has a web page at <http://www.phidgets.com/>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called phidgetservo.
-
 config USB_IDMOUSE
 	tristate "Siemens ID USB Mouse Fingerprint sensor support"
 	depends on USB
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 1334f7b..0826aab 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -18,10 +18,6 @@
 obj-$(CONFIG_USB_LD)		+= ldusb.o
 obj-$(CONFIG_USB_LED)		+= usbled.o
 obj-$(CONFIG_USB_LEGOTOWER)	+= legousbtower.o
-obj-$(CONFIG_USB_PHIDGET)	+= phidget.o
-obj-$(CONFIG_USB_PHIDGETKIT)	+= phidgetkit.o
-obj-$(CONFIG_USB_PHIDGETMOTORCONTROL)	+= phidgetmotorcontrol.o
-obj-$(CONFIG_USB_PHIDGETSERVO)	+= phidgetservo.o
 obj-$(CONFIG_USB_RIO500)	+= rio500.o
 obj-$(CONFIG_USB_TEST)		+= usbtest.o
 obj-$(CONFIG_USB_TRANCEVIBRATOR)	+= trancevibrator.o
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 7b6922e..2035265 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -376,7 +376,7 @@
 	if (dev->open_count <= 0) {
 		dbg(1," %s : device not opened", __func__);
 		retval = -ENODEV;
-		goto exit;
+		goto unlock;
 	}
 
 	adu_release_internal(dev);
@@ -385,9 +385,9 @@
 		if (!dev->open_count)	/* ... and we're the last user */
 			adu_delete(dev);
 	}
-
-exit:
+unlock:
 	mutex_unlock(&adutux_mutex);
+exit:
 	dbg(2," %s : leave, return value %d", __func__, retval);
 	return retval;
 }
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 79a7668..9d0675e 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -1568,7 +1568,7 @@
                         struct u132_target *target = &ftdi->target[ed];
                         struct u132_command *command = &ftdi->command[
                                 COMMAND_MASK & ftdi->command_next];
-                        int remaining_length = urb->transfer_buffer_length -
+                        u32 remaining_length = urb->transfer_buffer_length -
                                 urb->actual_length;
                         command->header = 0x82 | (ed << 5);
                         if (remaining_length == 0) {
@@ -1702,7 +1702,7 @@
                                 | (address << 0);
                         command->width = usb_maxpacket(urb->dev, urb->pipe,
                                 usb_pipeout(urb->pipe));
-                        command->follows = min(1024,
+                        command->follows = min_t(u32, 1024,
                                 urb->transfer_buffer_length -
                                 urb->actual_length);
                         command->value = 0;
@@ -1766,7 +1766,7 @@
                 mutex_lock(&ftdi->u132_lock);
                 command_size = ftdi->command_next - ftdi->command_head;
                 if (command_size < COMMAND_SIZE) {
-                        int remaining_length = urb->transfer_buffer_length -
+                        u32 remaining_length = urb->transfer_buffer_length -
                                 urb->actual_length;
                         struct u132_target *target = &ftdi->target[ed];
                         struct u132_command *command = &ftdi->command[
diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c
deleted file mode 100644
index 735ed33..0000000
--- a/drivers/usb/misc/phidget.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * USB Phidgets class
- *
- * Copyright (C) 2006  Sean Young <sean@mess.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/device.h>
-
-struct class *phidget_class;
-
-static int __init init_phidget(void)
-{
-	phidget_class = class_create(THIS_MODULE, "phidget");
-
-	if (IS_ERR(phidget_class))
-		return PTR_ERR(phidget_class);
-
-	return 0;
-}
-
-static void __exit cleanup_phidget(void)
-{
-	class_destroy(phidget_class);
-}
-
-EXPORT_SYMBOL_GPL(phidget_class);
-
-module_init(init_phidget);
-module_exit(cleanup_phidget);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Sean Young <sean@mess.org>");
-MODULE_DESCRIPTION("Container module for phidget class");
-
diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h
deleted file mode 100644
index c401190..0000000
--- a/drivers/usb/misc/phidget.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * USB Phidgets class
- *
- * Copyright (C) 2006  Sean Young <sean@mess.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.
- */
-
-extern struct class *phidget_class;
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
deleted file mode 100644
index cc8e0a9..0000000
--- a/drivers/usb/misc/phidgetkit.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * USB PhidgetInterfaceKit driver 1.0
- *
- * Copyright (C) 2004, 2006 Sean Young <sean@mess.org>
- * Copyright (C) 2005 Daniel Saakes <daniel@saakes.net>
- * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.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 is a driver for the USB PhidgetInterfaceKit.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-
-#include "phidget.h"
-
-#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
-#define DRIVER_DESC "USB PhidgetInterfaceKit Driver"
-
-#define USB_VENDOR_ID_GLAB		0x06c2
-#define USB_DEVICE_ID_INTERFACEKIT004	0x0040
-#define USB_DEVICE_ID_INTERFACEKIT01616	0x0044
-#define USB_DEVICE_ID_INTERFACEKIT888	0x0045
-#define USB_DEVICE_ID_INTERFACEKIT047	0x0051
-#define USB_DEVICE_ID_INTERFACEKIT088	0x0053
-
-#define USB_VENDOR_ID_WISEGROUP		0x0925
-#define USB_DEVICE_ID_INTERFACEKIT884	0x8201
-
-#define MAX_INTERFACES			16
-
-#define URB_INT_SIZE			8
-
-struct driver_interfacekit {
-	int sensors;
-	int inputs;
-	int outputs;
-	int has_lcd;
-	int amnesiac;
-};
-
-#define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac)		\
-{									\
-	.sensors	= _sensors,					\
-	.inputs		= _inputs,					\
-	.outputs	= _outputs,					\
-	.has_lcd	= _lcd,						\
-	.amnesiac	= _amnesiac					\
-};
-
-static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0);
-static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1);
-static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0);
-static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0);
-static const struct driver_interfacekit ph_884 = ifkit(8, 8, 4, 0, 0);
-static const struct driver_interfacekit ph_088 = ifkit(0, 8, 8, 1, 0);
-static const struct driver_interfacekit ph_01616 = ifkit(0, 16, 16, 0, 0);
-
-static unsigned long device_no;
-
-struct interfacekit {
-	struct usb_device *udev;
-	struct usb_interface *intf;
-	struct driver_interfacekit *ifkit;
-	struct device *dev;
-	unsigned long outputs;
-	int dev_no;
-	u8 inputs[MAX_INTERFACES];
-	u16 sensors[MAX_INTERFACES];
-	u8 lcd_files_on;
-
-	struct urb *irq;
-	unsigned char *data;
-	dma_addr_t data_dma;
-
-	struct delayed_work do_notify;
-	struct delayed_work do_resubmit;
-	unsigned long input_events;
-	unsigned long sensor_events;
-};
-
-static struct usb_device_id id_table[] = {
-	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004),
-		.driver_info = (kernel_ulong_t)&ph_004},
-	{USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814),
-		.driver_info = (kernel_ulong_t)&ph_888o},
-	{USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0x0815, 0xffff),
-		.driver_info = (kernel_ulong_t)&ph_888n},
-	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047),
-		.driver_info = (kernel_ulong_t)&ph_047},
-	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088),
-		.driver_info = (kernel_ulong_t)&ph_088},
-	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616),
-		.driver_info = (kernel_ulong_t)&ph_01616},
-	{USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884),
-		.driver_info = (kernel_ulong_t)&ph_884},
-	{}
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static int set_outputs(struct interfacekit *kit)
-{
-	u8 *buffer;
-	int retval;
-
-	buffer = kzalloc(4, GFP_KERNEL);
-	if (!buffer) {
-		dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
-		return -ENOMEM;
-	}
-	buffer[0] = (u8)kit->outputs;
-	buffer[1] = (u8)(kit->outputs >> 8);
-
-	dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs);
-
-	retval = usb_control_msg(kit->udev,
-			 usb_sndctrlpipe(kit->udev, 0),
-			 0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2000);
-
-	if (retval != 4)
-		dev_err(&kit->udev->dev, "usb_control_msg returned %d\n", 
-				retval);
-	kfree(buffer);
-
-	if (kit->ifkit->amnesiac)
-		schedule_delayed_work(&kit->do_resubmit, HZ / 2);
-
-	return retval < 0 ? retval : 0;
-}
-
-static int change_string(struct interfacekit *kit, const char *display, unsigned char row)
-{
-	unsigned char *buffer;
-	unsigned char *form_buffer;
-	int retval = -ENOMEM;
-	int i,j, len, buf_ptr;
-	
-	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", __func__);
-		goto exit;
-	}
-
-	len = strlen(display);
-	if (len > 20)
-		len = 20;
-
-	dev_dbg(&kit->udev->dev, "Setting LCD line %d to %s\n", row, display);
-
-	form_buffer[0] = row * 0x40 + 0x80;
-	form_buffer[1] = 0x02;
-	buf_ptr = 2;
-	for (i = 0; i<len; i++)
-		form_buffer[buf_ptr++] = display[i];
-
-	for (i = 0; i < (20 - len); i++)
-		form_buffer[buf_ptr++] = 0x20;
-	form_buffer[buf_ptr++] = 0x01;
-	form_buffer[buf_ptr++] = row * 0x40 + 0x80 + strlen(display);
-
-	for (i = 0; i < buf_ptr; i += 7) {
-		if ((buf_ptr - i) > 7)
-			len = 7;
-		else
-			len = (buf_ptr - i);
-		for (j = 0; j < len; j++)
-			buffer[j] = form_buffer[i + j];
-		buffer[7] = len;
-
-		retval = usb_control_msg(kit->udev,
-				 usb_sndctrlpipe(kit->udev, 0),
-				 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
-		if (retval < 0)
-			goto exit;
-	}
-
-	retval = 0;
-exit:
-	kfree(buffer);
-	kfree(form_buffer);
-
-	return retval;
-}
-
-#define set_lcd_line(number)	\
-static ssize_t lcd_line_##number(struct device *dev,			\
-					struct device_attribute *attr,	\
-					const char *buf, size_t count)	\
-{									\
-	struct interfacekit *kit = dev_get_drvdata(dev);		\
-	change_string(kit, buf, number - 1);				\
-	return count;							\
-}
-
-#define lcd_line_attr(number)						\
-	__ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number)
-
-set_lcd_line(1);
-set_lcd_line(2);
-
-static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct interfacekit *kit = dev_get_drvdata(dev);
-	int enabled;
-	unsigned char *buffer;
-	int retval = -ENOMEM;
-	
-	buffer = kzalloc(8, GFP_KERNEL);
-	if (!buffer) {
-		dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
-		goto exit;
-	}
-
-	if (sscanf(buf, "%d", &enabled) < 1) {
-		retval = -EINVAL;
-		goto exit;
-	}
-	if (enabled)
-		buffer[0] = 0x01;
-	buffer[7] = 0x11;
-
-	dev_dbg(&kit->udev->dev, "Setting backlight to %s\n", enabled ? "on" : "off");
-	
-	retval = usb_control_msg(kit->udev,
-			 usb_sndctrlpipe(kit->udev, 0),
-			 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
-	if (retval < 0)
-		goto exit;
-
-	retval = count;
-exit:
-	kfree(buffer);
-	return retval;
-}
-
-static struct device_attribute dev_lcd_line_attrs[] = {
-	lcd_line_attr(1),
-	lcd_line_attr(2),
-	__ATTR(backlight, S_IWUGO, NULL, set_backlight)
-};
-
-static void remove_lcd_files(struct interfacekit *kit)
-{
-	int i;
-
-	if (kit->lcd_files_on) {
-		dev_dbg(&kit->udev->dev, "Removing lcd files\n");
-
-		for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++)
-			device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
-	}
-}
-
-static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct interfacekit *kit = dev_get_drvdata(dev);
-	int enable;
-	int i, rc;
-	
-	if (kit->ifkit->has_lcd == 0)
-		return -ENODEV;
-
-	if (sscanf(buf, "%d", &enable) < 1)
-		return -EINVAL;
-
-	if (enable) {
-		if (!kit->lcd_files_on) {
-			dev_dbg(&kit->udev->dev, "Adding lcd files\n");
-			for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) {
-				rc = device_create_file(kit->dev,
-					&dev_lcd_line_attrs[i]);
-				if (rc)
-					goto out;
-			}
-			kit->lcd_files_on = 1;
-		}
-	} else {
-		if (kit->lcd_files_on) {
-			remove_lcd_files(kit);
-			kit->lcd_files_on = 0;
-		}
-	}
-	
-	return count;
-out:
-	while (i-- > 0)
-		device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
-
-	return rc;
-}
-
-static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
-
-static void interfacekit_irq(struct urb *urb)
-{
-	struct interfacekit *kit = urb->context;
-	unsigned char *buffer = kit->data;
-	int i, level, sensor;
-	int retval;
-	int status = urb->status;
-
-	switch (status) {
-	case 0:			/* success */
-		break;
-	case -ECONNRESET:	/* unlink */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		return;
-	/* -EPIPE:  should clear the halt */
-	default:		/* error */
-		goto resubmit;
-	}
-
-	/* digital inputs */
-	if (kit->ifkit->inputs == 16) {
-		for (i=0; i < 8; i++) {
-			level = (buffer[0] >> i) & 1;
-			if (kit->inputs[i] != level) {
-				kit->inputs[i] = level;
-				set_bit(i, &kit->input_events);
-			}
-			level = (buffer[1] >> i) & 1;
-			if (kit->inputs[8 + i] != level) {
-				kit->inputs[8 + i] = level;
-				set_bit(8 + i, &kit->input_events);
-			}
-		}
-	}
-	else if (kit->ifkit->inputs == 8) {
-		for (i=0; i < 8; i++) {
-			level = (buffer[1] >> i) & 1;
-			if (kit->inputs[i] != level) {
-				kit->inputs[i] = level;
-				set_bit(i, &kit->input_events);
-			}
-		}
-	}
-
-	/* analog inputs */
-	if (kit->ifkit->sensors) {
-		sensor = (buffer[0] & 1) ? 4 : 0;
-
-		level = buffer[2] + (buffer[3] & 0x0f) * 256;
-		if (level != kit->sensors[sensor]) {
-			kit->sensors[sensor] = level;
-			set_bit(sensor, &kit->sensor_events);
-		}
-		sensor++;
-		level = buffer[4] + (buffer[3] & 0xf0) * 16;
-		if (level != kit->sensors[sensor]) {
-			kit->sensors[sensor] = level;
-			set_bit(sensor, &kit->sensor_events);
-		}
-		sensor++;
-		level = buffer[5] + (buffer[6] & 0x0f) * 256;
-		if (level != kit->sensors[sensor]) {
-			kit->sensors[sensor] = level;
-			set_bit(sensor, &kit->sensor_events);
-		}
-		sensor++;
-		level = buffer[7] + (buffer[6] & 0xf0) * 16;
-		if (level != kit->sensors[sensor]) {
-			kit->sensors[sensor] = level;
-			set_bit(sensor, &kit->sensor_events);
-		}
-	}
-
-	if (kit->input_events || kit->sensor_events)
-		schedule_delayed_work(&kit->do_notify, 0);
-
-resubmit:
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		err("can't resubmit intr, %s-%s/interfacekit0, retval %d",
-			kit->udev->bus->bus_name,
-			kit->udev->devpath, retval);
-}
-
-static void do_notify(struct work_struct *work)
-{
-	struct interfacekit *kit =
-		container_of(work, struct interfacekit, do_notify.work);
-	int i;
-	char sysfs_file[8];
-
-	for (i=0; i<kit->ifkit->inputs; i++) {
-		if (test_and_clear_bit(i, &kit->input_events)) {
-			sprintf(sysfs_file, "input%d", i + 1);
-			sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
-		}
-	}
-
-	for (i=0; i<kit->ifkit->sensors; i++) {
-		if (test_and_clear_bit(i, &kit->sensor_events)) {
-			sprintf(sysfs_file, "sensor%d", i + 1);
-			sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
-		}
-	}
-}
-
-static void do_resubmit(struct work_struct *work)
-{
-	struct interfacekit *kit =
-		container_of(work, struct interfacekit, do_resubmit.work);
-	set_outputs(kit);
-}
-
-#define show_set_output(value)		\
-static ssize_t set_output##value(struct device *dev,			\
-					struct device_attribute *attr,	\
-					const char *buf, size_t count)	\
-{									\
-	struct interfacekit *kit = dev_get_drvdata(dev);		\
-	int enable;							\
-	int retval;							\
-									\
-	if (sscanf(buf, "%d", &enable) < 1)				\
-		return -EINVAL;						\
-									\
-	if (enable)							\
-		set_bit(value - 1, &kit->outputs);			\
-	else								\
-		clear_bit(value - 1, &kit->outputs); 			\
-									\
-	retval = set_outputs(kit);					\
-									\
-	return retval ? retval : count;					\
-}									\
-									\
-static ssize_t show_output##value(struct device *dev, 			\
-					struct device_attribute *attr,	\
-					char *buf)			\
-{									\
-	struct interfacekit *kit = dev_get_drvdata(dev);		\
-									\
-	return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\
-}
-
-#define output_attr(value)						\
-	__ATTR(output##value, S_IWUGO | S_IRUGO,			\
-		show_output##value, set_output##value)
-
-show_set_output(1);
-show_set_output(2);
-show_set_output(3);
-show_set_output(4);
-show_set_output(5);
-show_set_output(6);
-show_set_output(7);
-show_set_output(8);
-show_set_output(9);
-show_set_output(10);
-show_set_output(11);
-show_set_output(12);
-show_set_output(13);
-show_set_output(14);
-show_set_output(15);
-show_set_output(16);
-
-static struct device_attribute dev_output_attrs[] = {
-	output_attr(1), output_attr(2), output_attr(3), output_attr(4),
-	output_attr(5), output_attr(6), output_attr(7), output_attr(8),
-	output_attr(9), output_attr(10), output_attr(11), output_attr(12),
-	output_attr(13), output_attr(14), output_attr(15), output_attr(16)
-};
-
-#define show_input(value)	\
-static ssize_t show_input##value(struct device *dev, 			\
-			struct device_attribute *attr, char *buf)	\
-{									\
-	struct interfacekit *kit = dev_get_drvdata(dev);		\
-									\
-	return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]);	\
-}
-
-#define input_attr(value)						\
-	__ATTR(input##value, S_IRUGO, show_input##value, NULL)
-
-show_input(1);
-show_input(2);
-show_input(3);
-show_input(4);
-show_input(5);
-show_input(6);
-show_input(7);
-show_input(8);
-show_input(9);
-show_input(10);
-show_input(11);
-show_input(12);
-show_input(13);
-show_input(14);
-show_input(15);
-show_input(16);
-
-static struct device_attribute dev_input_attrs[] = {
-	input_attr(1), input_attr(2), input_attr(3), input_attr(4),
-	input_attr(5), input_attr(6), input_attr(7), input_attr(8),
-	input_attr(9), input_attr(10), input_attr(11), input_attr(12),
-	input_attr(13), input_attr(14), input_attr(15), input_attr(16)
-};
-
-#define show_sensor(value)	\
-static ssize_t show_sensor##value(struct device *dev,			\
-					struct device_attribute *attr,	\
-					char *buf)			\
-{									\
-	struct interfacekit *kit = dev_get_drvdata(dev);		\
-									\
-	return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]);	\
-}
-
-#define sensor_attr(value)						\
-	__ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL)
-
-show_sensor(1);
-show_sensor(2);
-show_sensor(3);
-show_sensor(4);
-show_sensor(5);
-show_sensor(6);
-show_sensor(7);
-show_sensor(8);
-
-static struct device_attribute dev_sensor_attrs[] = {
-	sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4),
-	sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8)
-};
-
-static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct interfacekit *kit;
-	struct driver_interfacekit *ifkit;
-	int pipe, maxp, rc = -ENOMEM;
-	int bit, value, i;
-
-	ifkit = (struct driver_interfacekit *)id->driver_info;
-	if (!ifkit)
-		return -ENODEV;
-
-	interface = intf->cur_altsetting;
-	if (interface->desc.bNumEndpoints != 1)
-		return -ENODEV;
-
-	endpoint = &interface->endpoint[0].desc;
-	if (!usb_endpoint_dir_in(endpoint))
-		return -ENODEV;
-	/*
-	 * bmAttributes
-	 */
-	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-	
-	kit = kzalloc(sizeof(*kit), GFP_KERNEL);
-	if (!kit)
-		goto out;
-
-	kit->dev_no = -1;
-	kit->ifkit = ifkit;
-	kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &kit->data_dma);
-	if (!kit->data)
-		goto out;
-
-	kit->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!kit->irq)
-		goto out;
-
-	kit->udev = usb_get_dev(dev);
-	kit->intf = intf;
-	INIT_DELAYED_WORK(&kit->do_notify, do_notify);
-	INIT_DELAYED_WORK(&kit->do_resubmit, do_resubmit);
-	usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
-			maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
-			interfacekit_irq, kit, endpoint->bInterval);
-	kit->irq->transfer_dma = kit->data_dma;
-	kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	usb_set_intfdata(intf, kit);
-
-        do {
-                bit = find_first_zero_bit(&device_no, sizeof(device_no));
-                value = test_and_set_bit(bit, &device_no);
-        } while(value);
-        kit->dev_no = bit;
-
-	kit->dev = device_create(phidget_class, &kit->udev->dev, MKDEV(0, 0),
-				 kit, "interfacekit%d", kit->dev_no);
-        if (IS_ERR(kit->dev)) {
-                rc = PTR_ERR(kit->dev);
-                kit->dev = NULL;
-                goto out;
-        }
-
-	if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
-		rc = -EIO;
-		goto out;
-	}
-
-	for (i=0; i<ifkit->outputs; i++ ) {
-		rc = device_create_file(kit->dev, &dev_output_attrs[i]);
-		if (rc)
-			goto out2;
-	}
-
-	for (i=0; i<ifkit->inputs; i++ ) {
-		rc = device_create_file(kit->dev, &dev_input_attrs[i]);
-		if (rc)
-			goto out3;
-	}
-
-	for (i=0; i<ifkit->sensors; i++ ) {
-		rc = device_create_file(kit->dev, &dev_sensor_attrs[i]);
-		if (rc)
-			goto out4;
-	}
-
-	if (ifkit->has_lcd) {
-		rc = device_create_file(kit->dev, &dev_attr_lcd);
-		if (rc)
-			goto out4;
-
-	}
-
-	dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
-			ifkit->sensors, ifkit->inputs, ifkit->outputs);
-
-	return 0;
-
-out4:
-	while (i-- > 0)
-		device_remove_file(kit->dev, &dev_sensor_attrs[i]);
-
-	i = ifkit->inputs;
-out3:
-	while (i-- > 0)
-		device_remove_file(kit->dev, &dev_input_attrs[i]);
-
-	i = ifkit->outputs;
-out2:
-	while (i-- > 0)
-		device_remove_file(kit->dev, &dev_output_attrs[i]);
-out:
-	if (kit) {
-		usb_free_urb(kit->irq);
-		if (kit->data)
-			usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
-		if (kit->dev)
-			device_unregister(kit->dev);
-		if (kit->dev_no >= 0)
-			clear_bit(kit->dev_no, &device_no);
-
-		kfree(kit);
-	}
-
-	return rc;
-}
-
-static void interfacekit_disconnect(struct usb_interface *interface)
-{
-	struct interfacekit *kit;
-	int i;
-
-	kit = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
-	if (!kit)
-		return;
-
-	usb_kill_urb(kit->irq);
-	usb_free_urb(kit->irq);
-	usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma);
-
-	cancel_delayed_work(&kit->do_notify);
-	cancel_delayed_work(&kit->do_resubmit);
-
-	for (i=0; i<kit->ifkit->outputs; i++)
-		device_remove_file(kit->dev, &dev_output_attrs[i]);
-
-	for (i=0; i<kit->ifkit->inputs; i++)
-		device_remove_file(kit->dev, &dev_input_attrs[i]);
-
-	for (i=0; i<kit->ifkit->sensors; i++)
-		device_remove_file(kit->dev, &dev_sensor_attrs[i]);
-
-	if (kit->ifkit->has_lcd) {
-		device_remove_file(kit->dev, &dev_attr_lcd);
-		remove_lcd_files(kit);
-	}
-
-	device_unregister(kit->dev);
-
-	dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
-		kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
-
-	usb_put_dev(kit->udev);
-	clear_bit(kit->dev_no, &device_no);
-
-	kfree(kit);
-}
-
-static struct usb_driver interfacekit_driver = {
-	.name = "phidgetkit",
-	.probe = interfacekit_probe,
-	.disconnect = interfacekit_disconnect,
-	.id_table = id_table
-};
-
-static int __init interfacekit_init(void)
-{
-	int retval = 0;
-
-	retval = usb_register(&interfacekit_driver);
-	if (retval)
-		err("usb_register failed. Error number %d", retval);
-
-	return retval;
-}
-
-static void __exit interfacekit_exit(void)
-{
-	usb_deregister(&interfacekit_driver);
-}
-
-module_init(interfacekit_init);
-module_exit(interfacekit_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
deleted file mode 100644
index 38088b4..0000000
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * USB Phidget MotorControl driver
- *
- * Copyright (C) 2006  Sean Young <sean@mess.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-
-#include "phidget.h"
-
-#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
-#define DRIVER_DESC "USB PhidgetMotorControl Driver"
-
-#define USB_VENDOR_ID_GLAB		0x06c2
-#define USB_DEVICE_ID_MOTORCONTROL	0x0058
-
-#define URB_INT_SIZE			8
-
-static unsigned long device_no;
-
-struct motorcontrol {
-	struct usb_device *udev;
-	struct usb_interface *intf;
-	struct device *dev;
-	int dev_no;
-	u8 inputs[4];
-	s8 desired_speed[2];
-	s8 speed[2];
-	s16 _current[2];
-	s8 acceleration[2];
-	struct urb *irq;
-	unsigned char *data;
-	dma_addr_t data_dma;
-
-	struct delayed_work do_notify;
-	unsigned long input_events;
-	unsigned long speed_events;
-	unsigned long exceed_events;
-};
-
-static struct usb_device_id id_table[] = {
-	{ USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) },
-	{}
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static int set_motor(struct motorcontrol *mc, int motor)
-{
-	u8 *buffer;
-	int speed, speed2, acceleration;
-	int retval;
-
-	buffer = kzalloc(8, GFP_KERNEL);
-	if (!buffer) {
-		dev_err(&mc->intf->dev, "%s - out of memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	acceleration = mc->acceleration[motor] * 10;
-	/* -127 <= speed <= 127 */
-	speed = (mc->desired_speed[motor] * 127) / 100;
-	/* -0x7300 <= speed2 <= 0x7300 */
-	speed2 = (mc->desired_speed[motor] * 230 * 128) / 100;
-
-	buffer[0] = motor;
-	buffer[1] = speed;
-	buffer[2] = acceleration >> 8;
-	buffer[3] = acceleration;
-	buffer[4] = speed2 >> 8;
-	buffer[5] = speed2;
-
-	retval = usb_control_msg(mc->udev,
-			 usb_sndctrlpipe(mc->udev, 0),
-			 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
-
-	if (retval != 8)
-		dev_err(&mc->intf->dev, "usb_control_msg returned %d\n",
-				retval);
-	kfree(buffer);
-
-	return retval < 0 ? retval : 0;
-}
-
-static void motorcontrol_irq(struct urb *urb)
-{
-	struct motorcontrol *mc = urb->context;
-	unsigned char *buffer = mc->data;
-	int i, level;
-	int retval;
-	int status = urb->status;;
-
-	switch (status) {
-	case 0:			/* success */
-		break;
-	case -ECONNRESET:	/* unlink */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		return;
-	/* -EPIPE:  should clear the halt */
-	default:		/* error */
-		goto resubmit;
-	}
-
-	/* digital inputs */
-	for (i=0; i<4; i++) {
-		level = (buffer[0] >> i) & 1;
-		if (mc->inputs[i] != level) {
-			mc->inputs[i] = level;
-			set_bit(i, &mc->input_events);
-		}
-	}
-
-	/* motor speed */
-	if (buffer[2] == 0) {
-		for (i=0; i<2; i++) {
-		level = ((s8)buffer[4+i]) * 100 / 127;
-			if (mc->speed[i] != level) {
-				mc->speed[i] = level;
-				set_bit(i, &mc->speed_events);
-			}
-		}
-	} else {
-		int index = buffer[3] & 1;
-
-		level = ((s8)buffer[4] << 8) | buffer[5];
-		level = level * 100 / 29440;
-		if (mc->speed[index] != level) {
-			mc->speed[index] = level;
-			set_bit(index, &mc->speed_events);
-		}
-
-		level = ((s8)buffer[6] << 8) | buffer[7];
-		mc->_current[index] = level * 100 / 1572;
-	}
-
-	if (buffer[1] & 1)
-		set_bit(0, &mc->exceed_events);
-
-	if (buffer[1] & 2)
-		set_bit(1, &mc->exceed_events);
-
-	if (mc->input_events || mc->exceed_events || mc->speed_events)
-		schedule_delayed_work(&mc->do_notify, 0);
-
-resubmit:
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		dev_err(&mc->intf->dev,
-			"can't resubmit intr, %s-%s/motorcontrol0, retval %d\n",
-			mc->udev->bus->bus_name,
-			mc->udev->devpath, retval);
-}
-
-static void do_notify(struct work_struct *work)
-{
-	struct motorcontrol *mc =
-		container_of(work, struct motorcontrol, do_notify.work);
-	int i;
-	char sysfs_file[8];
-
-	for (i=0; i<4; i++) {
-		if (test_and_clear_bit(i, &mc->input_events)) {
-			sprintf(sysfs_file, "input%d", i);
-			sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
-		}
-	}
-
-	for (i=0; i<2; i++) {
-		if (test_and_clear_bit(i, &mc->speed_events)) {
-			sprintf(sysfs_file, "speed%d", i);
-			sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
-		}
-	}
-
-	for (i=0; i<2; i++) {
-		if (test_and_clear_bit(i, &mc->exceed_events))
-			dev_warn(&mc->intf->dev,
-				"motor #%d exceeds 1.5 Amp current limit\n", i);
-	}
-}
-
-#define show_set_speed(value)		\
-static ssize_t set_speed##value(struct device *dev,			\
-					struct device_attribute *attr,	\
-					const char *buf, size_t count)	\
-{									\
-	struct motorcontrol *mc = dev_get_drvdata(dev);			\
-	int speed;							\
-	int retval;							\
-									\
-	if (sscanf(buf, "%d", &speed) < 1)				\
-		return -EINVAL;						\
-									\
-	if (speed < -100 || speed > 100)				\
-		return -EINVAL;						\
-									\
-	mc->desired_speed[value] = speed;				\
-									\
-	retval = set_motor(mc, value);					\
-									\
-	return retval ? retval : count;					\
-}									\
-									\
-static ssize_t show_speed##value(struct device *dev,			\
-					struct device_attribute *attr,	\
-					char *buf)			\
-{									\
-	struct motorcontrol *mc = dev_get_drvdata(dev);			\
-									\
-	return sprintf(buf, "%d\n", mc->speed[value]);			\
-}
-
-#define speed_attr(value) 						\
-	__ATTR(speed##value, S_IWUGO | S_IRUGO, 			\
-		show_speed##value, set_speed##value)
-
-show_set_speed(0);
-show_set_speed(1);
-
-#define show_set_acceleration(value)		\
-static ssize_t set_acceleration##value(struct device *dev, 		\
-					struct device_attribute *attr,	\
-					const char *buf, size_t count)	\
-{									\
-	struct motorcontrol *mc = dev_get_drvdata(dev);			\
-	int acceleration;						\
-	int retval;							\
-									\
-	if (sscanf(buf, "%d", &acceleration) < 1)			\
-		return -EINVAL;						\
-									\
-	if (acceleration < 0 || acceleration > 100)			\
-		return -EINVAL;						\
-									\
-	mc->acceleration[value] = acceleration;				\
-									\
-	retval = set_motor(mc, value);					\
-									\
-	return retval ? retval : count;					\
-}									\
-									\
-static ssize_t show_acceleration##value(struct device *dev,	 	\
-					struct device_attribute *attr,	\
-							char *buf)	\
-{									\
-	struct motorcontrol *mc = dev_get_drvdata(dev);			\
-									\
-	return sprintf(buf, "%d\n", mc->acceleration[value]);		\
-}
-
-#define acceleration_attr(value)	\
-	__ATTR(acceleration##value, S_IWUGO | S_IRUGO,			\
-		show_acceleration##value, set_acceleration##value)
-
-show_set_acceleration(0);
-show_set_acceleration(1);
-
-#define show_current(value)	\
-static ssize_t show_current##value(struct device *dev,			\
-					struct device_attribute *attr,	\
-					char *buf)			\
-{									\
-	struct motorcontrol *mc = dev_get_drvdata(dev);			\
-									\
-	return sprintf(buf, "%dmA\n", (int)mc->_current[value]);	\
-}
-
-#define current_attr(value)	\
-	__ATTR(current##value, S_IRUGO, show_current##value, NULL)
-
-show_current(0);
-show_current(1);
-
-#define show_input(value)	\
-static ssize_t show_input##value(struct device *dev,			\
-					struct device_attribute *attr,	\
-					char *buf)			\
-{									\
-	struct motorcontrol *mc = dev_get_drvdata(dev);			\
-									\
-	return sprintf(buf, "%d\n", (int)mc->inputs[value]);		\
-}
-
-#define input_attr(value)	\
-	__ATTR(input##value, S_IRUGO, show_input##value, NULL)
-
-show_input(0);
-show_input(1);
-show_input(2);
-show_input(3);
-
-static struct device_attribute dev_attrs[] = {
-	input_attr(0),
-	input_attr(1),
-	input_attr(2),
-	input_attr(3),
-	speed_attr(0),
-	speed_attr(1),
-	acceleration_attr(0),
-	acceleration_attr(1),
-	current_attr(0),
-	current_attr(1)
-};
-
-static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct motorcontrol *mc;
-	int pipe, maxp, rc = -ENOMEM;
-	int bit, value, i;
-
-	interface = intf->cur_altsetting;
-	if (interface->desc.bNumEndpoints != 1)
-		return -ENODEV;
-
-	endpoint = &interface->endpoint[0].desc;
-	if (!usb_endpoint_dir_in(endpoint))
-		return -ENODEV;
-
-	/*
-	 * bmAttributes
-	 */
-	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
-	mc = kzalloc(sizeof(*mc), GFP_KERNEL);
-	if (!mc)
-		goto out;
-
-	mc->dev_no = -1;
-	mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &mc->data_dma);
-	if (!mc->data)
-		goto out;
-
-	mc->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!mc->irq)
-		goto out;
-
-	mc->udev = usb_get_dev(dev);
-	mc->intf = intf;
-	mc->acceleration[0] = mc->acceleration[1] = 10;
-	INIT_DELAYED_WORK(&mc->do_notify, do_notify);
-	usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data,
-			maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
-			motorcontrol_irq, mc, endpoint->bInterval);
-	mc->irq->transfer_dma = mc->data_dma;
-	mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	usb_set_intfdata(intf, mc);
-
-	do {
-		bit = find_first_zero_bit(&device_no, sizeof(device_no));
-		value = test_and_set_bit(bit, &device_no);
-	} while(value);
-	mc->dev_no = bit;
-
-	mc->dev = device_create(phidget_class, &mc->udev->dev, MKDEV(0, 0), mc,
-				"motorcontrol%d", mc->dev_no);
-	if (IS_ERR(mc->dev)) {
-		rc = PTR_ERR(mc->dev);
-		mc->dev = NULL;
-		goto out;
-	}
-
-	if (usb_submit_urb(mc->irq, GFP_KERNEL)) {
-		rc = -EIO;
-		goto out;
-	}
-
-	for (i=0; i<ARRAY_SIZE(dev_attrs); i++) {
-		rc = device_create_file(mc->dev, &dev_attrs[i]);
-		if (rc)
-			goto out2;
-	}
-
-	dev_info(&intf->dev, "USB PhidgetMotorControl attached\n");
-
-	return 0;
-out2:
-	while (i-- > 0)
-		device_remove_file(mc->dev, &dev_attrs[i]);
-out:
-	if (mc) {
-		usb_free_urb(mc->irq);
-		if (mc->data)
-			usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
-		if (mc->dev)
-			device_unregister(mc->dev);
-		if (mc->dev_no >= 0)
-			clear_bit(mc->dev_no, &device_no);
-
-		kfree(mc);
-	}
-
-	return rc;
-}
-
-static void motorcontrol_disconnect(struct usb_interface *interface)
-{
-	struct motorcontrol *mc;
-	int i;
-
-	mc = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
-	if (!mc)
-		return;
-
-	usb_kill_urb(mc->irq);
-	usb_free_urb(mc->irq);
-	usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma);
-
-	cancel_delayed_work(&mc->do_notify);
-
-	for (i=0; i<ARRAY_SIZE(dev_attrs); i++)
-		device_remove_file(mc->dev, &dev_attrs[i]);
-
-	device_unregister(mc->dev);
-
-	usb_put_dev(mc->udev);
-	clear_bit(mc->dev_no, &device_no);
-	kfree(mc);
-
-	dev_info(&interface->dev, "USB PhidgetMotorControl detached\n");
-}
-
-static struct usb_driver motorcontrol_driver = {
-	.name = "phidgetmotorcontrol",
-	.probe = motorcontrol_probe,
-	.disconnect = motorcontrol_disconnect,
-	.id_table = id_table
-};
-
-static int __init motorcontrol_init(void)
-{
-	int retval = 0;
-
-	retval = usb_register(&motorcontrol_driver);
-	if (retval)
-		err("usb_register failed. Error number %d", retval);
-
-	return retval;
-}
-
-static void __exit motorcontrol_exit(void)
-{
-	usb_deregister(&motorcontrol_driver);
-}
-
-module_init(motorcontrol_init);
-module_exit(motorcontrol_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
deleted file mode 100644
index bef6fe1..0000000
--- a/drivers/usb/misc/phidgetservo.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * USB PhidgetServo driver 1.0
- *
- * Copyright (C) 2004, 2006 Sean Young <sean@mess.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 is a driver for the USB PhidgetServo version 2.0 and 3.0 servo 
- * controllers available at: http://www.phidgets.com/ 
- *
- * Note that the driver takes input as: degrees.minutes
- *
- * CAUTION: Generally you should use 0 < degrees < 180 as anything else
- * is probably beyond the range of your servo and may damage it.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-
-#include "phidget.h"
-
-#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
-#define DRIVER_DESC "USB PhidgetServo Driver"
-
-#define VENDOR_ID_GLAB				0x06c2
-#define DEVICE_ID_GLAB_PHIDGETSERVO_QUAD	0x0038
-#define DEVICE_ID_GLAB_PHIDGETSERVO_UNI		0x0039
-
-#define VENDOR_ID_WISEGROUP			0x0925
-#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD	0x8101
-#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI	0x8104
-
-#define SERVO_VERSION_30			0x01
-#define SERVO_COUNT_QUAD			0x02
-
-static struct usb_device_id id_table[] = {
-	{
-		USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_QUAD), 
-		.driver_info = SERVO_VERSION_30 | SERVO_COUNT_QUAD 
-	},
-	{
-		USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_UNI),
-		.driver_info = SERVO_VERSION_30 
-	},
-	{
-		USB_DEVICE(VENDOR_ID_WISEGROUP, 
-				VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD),
-		.driver_info = SERVO_COUNT_QUAD 
-	},
-	{
-		USB_DEVICE(VENDOR_ID_WISEGROUP, 
-				VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI),
-		.driver_info = 0
-	},
-	{}
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static int unsigned long device_no;
-
-struct phidget_servo {
-	struct usb_device *udev;
-	struct device *dev;
-	int dev_no;
-	ulong type;
-	int pulse[4];
-	int degrees[4];
-	int minutes[4];
-};
-
-static int
-change_position_v30(struct phidget_servo *servo, int servo_no, int degrees, 
-								int minutes)
-{
-	int retval;
-	unsigned char *buffer;
-
-	if (degrees < -23 || degrees > 362)
-		return -EINVAL;
-
-	buffer = kmalloc(6, GFP_KERNEL);
-	if (!buffer) {
-		dev_err(&servo->udev->dev, "%s - out of memory\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	/*
-	 * pulse = 0 - 4095
-	 * angle = 0 - 180 degrees
-	 *
-	 * pulse = angle * 10.6 + 243.8	
-	 */
-	servo->pulse[servo_no] = ((degrees*60 + minutes)*106 + 2438*60)/600;	
-	servo->degrees[servo_no]= degrees;
-	servo->minutes[servo_no]= minutes;	
-
-	/* 
-	 * The PhidgetServo v3.0 is controlled by sending 6 bytes,
-	 * 4 * 12 bits for each servo.
-	 *
-	 * low = lower 8 bits pulse
-	 * high = higher 4 bits pulse
-	 *
-	 * offset     bits
-	 * +---+-----------------+
-	 * | 0 |      low 0      |
-	 * +---+--------+--------+
-	 * | 1 | high 1 | high 0 |
-	 * +---+--------+--------+
-	 * | 2 |      low 1      |
-	 * +---+-----------------+
-	 * | 3 |      low 2      |
-	 * +---+--------+--------+
-	 * | 4 | high 3 | high 2 |
-	 * +---+--------+--------+
-	 * | 5 |      low 3      |
-	 * +---+-----------------+
-	 */
-
-	buffer[0] = servo->pulse[0] & 0xff;
-	buffer[1] = (servo->pulse[0] >> 8 & 0x0f)
-	    | (servo->pulse[1] >> 4 & 0xf0);
-	buffer[2] = servo->pulse[1] & 0xff;
-	buffer[3] = servo->pulse[2] & 0xff;
-	buffer[4] = (servo->pulse[2] >> 8 & 0x0f)
-	    | (servo->pulse[3] >> 4 & 0xf0);
-	buffer[5] = servo->pulse[3] & 0xff;
-
-	dev_dbg(&servo->udev->dev,
-		"data: %02x %02x %02x %02x %02x %02x\n",
-		buffer[0], buffer[1], buffer[2],
-		buffer[3], buffer[4], buffer[5]);
-
-	retval = usb_control_msg(servo->udev,
-				 usb_sndctrlpipe(servo->udev, 0),
-				 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2000);
-
-	kfree(buffer);
-
-	return retval;
-}
-
-static int
-change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
-								int minutes)
-{
-	int retval;
-	unsigned char *buffer;
-
-	if (degrees < -23 || degrees > 278)
-		return -EINVAL;
-
-	buffer = kmalloc(2, GFP_KERNEL);
-	if (!buffer) {
-		dev_err(&servo->udev->dev, "%s - out of memory\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	/*
-	 * angle = 0 - 180 degrees
-	 * pulse = angle + 23
-	 */
-	servo->pulse[servo_no]= degrees + 23;
-	servo->degrees[servo_no]= degrees;
-	servo->minutes[servo_no]= 0;
-
-	/*
-	 * The PhidgetServo v2.0 is controlled by sending two bytes. The
-	 * first byte is the servo number xor'ed with 2:
-	 *
-	 * servo 0 = 2
-	 * servo 1 = 3
-	 * servo 2 = 0
-	 * servo 3 = 1
-	 *
-	 * The second byte is the position.
-	 */
-
-	buffer[0] = servo_no ^ 2;
-	buffer[1] = servo->pulse[servo_no];
-
-	dev_dbg(&servo->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]);
-
-	retval = usb_control_msg(servo->udev,
-				 usb_sndctrlpipe(servo->udev, 0),
-				 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2000);
-
-	kfree(buffer);
-
-	return retval;
-}
-
-#define show_set(value)	\
-static ssize_t set_servo##value (struct device *dev, 			\
-					struct device_attribute *attr,	\
-					const char *buf, size_t count)	\
-{									\
-	int degrees, minutes, retval;					\
-	struct phidget_servo *servo = dev_get_drvdata(dev);		\
-									\
-	minutes = 0;							\
-	/* must at least convert degrees */				\
-	if (sscanf(buf, "%d.%d", &degrees, &minutes) < 1) {		\
-		return -EINVAL;						\
-	}								\
-									\
-	if (minutes < 0 || minutes > 59) 				\
-		return -EINVAL;						\
-									\
-	if (servo->type & SERVO_VERSION_30)				\
-		retval = change_position_v30(servo, value, degrees, 	\
-							minutes);	\
-	else 								\
-		retval = change_position_v20(servo, value, degrees, 	\
-							minutes);	\
-									\
-	return retval < 0 ? retval : count;				\
-}									\
-									\
-static ssize_t show_servo##value (struct device *dev,			\
-					struct device_attribute *attr,	\
-					char *buf) 			\
-{									\
-	struct phidget_servo *servo = dev_get_drvdata(dev);		\
-									\
-	return sprintf(buf, "%d.%02d\n", servo->degrees[value],		\
-				servo->minutes[value]);			\
-}
-
-#define servo_attr(value)						\
-	__ATTR(servo##value, S_IWUGO | S_IRUGO,				\
-		show_servo##value, set_servo##value)
-show_set(0);
-show_set(1);
-show_set(2);
-show_set(3);
-
-static struct device_attribute dev_attrs[] = {
-	servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3)
-};
-
-static int
-servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(interface);
-	struct phidget_servo *dev;
-	int bit, value, rc;
-	int servo_count, i;
-
-	dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL);
-	if (dev == NULL) {
-		dev_err(&interface->dev, "%s - out of memory\n", __func__);
-		rc = -ENOMEM;
-		goto out;
-	}
-
-	dev->udev = usb_get_dev(udev);
-	dev->type = id->driver_info;
-	dev->dev_no = -1;
-	usb_set_intfdata(interface, dev);
-
-        do {
-                bit = find_first_zero_bit(&device_no, sizeof(device_no));
-                value = test_and_set_bit(bit, &device_no);
-        } while (value);
-	dev->dev_no = bit;
-
-	dev->dev = device_create(phidget_class, &dev->udev->dev, MKDEV(0, 0),
-				 dev, "servo%d", dev->dev_no);
-	if (IS_ERR(dev->dev)) {
-		rc = PTR_ERR(dev->dev);
-		dev->dev = NULL;
-		goto out;
-	}
-
-	servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
-
-	for (i=0; i<servo_count; i++) {
-		rc = device_create_file(dev->dev, &dev_attrs[i]);
-		if (rc)
-			goto out2;
-	}
-
-	dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n",
-		servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
-
-	if (!(dev->type & SERVO_VERSION_30))
-		dev_info(&interface->dev,
-			 "WARNING: v2.0 not tested! Please report if it works.\n");
-
-	return 0;
-out2:
-	while (i-- > 0)
-		device_remove_file(dev->dev, &dev_attrs[i]);
-out:
-	if (dev) {
-		if (dev->dev)
-			device_unregister(dev->dev);
-		if (dev->dev_no >= 0)
-			clear_bit(dev->dev_no, &device_no);
-
-		kfree(dev);
-	}
-
-	return rc;
-}
-
-static void
-servo_disconnect(struct usb_interface *interface)
-{
-	struct phidget_servo *dev;
-	int servo_count, i;
-
-	dev = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
-
-	if (!dev)
-		return;
-
-	servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
-
-	for (i=0; i<servo_count; i++)
-		device_remove_file(dev->dev, &dev_attrs[i]);
-
-	device_unregister(dev->dev);
-	usb_put_dev(dev->udev);
-
-	dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n",
-		servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
-
-	clear_bit(dev->dev_no, &device_no);
-	kfree(dev);
-}
-
-static struct usb_driver servo_driver = {
-	.name = "phidgetservo",
-	.probe = servo_probe,
-	.disconnect = servo_disconnect,
-	.id_table = id_table
-};
-
-static int __init
-phidget_servo_init(void)
-{
-	int retval;
-
-	retval = usb_register(&servo_driver);
-	if (retval)
-		err("usb_register failed. Error number %d", retval);
-
-	return retval;
-}
-
-static void __exit
-phidget_servo_exit(void)
-{
-	usb_deregister(&servo_driver);
-}
-
-module_init(phidget_servo_init);
-module_exit(phidget_servo_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c
index 63dff9b..f26ea8d 100644
--- a/drivers/usb/misc/vstusb.c
+++ b/drivers/usb/misc/vstusb.c
@@ -401,6 +401,7 @@
 	}
 
 	if (copy_from_user(buf, buffer, count)) {
+		mutex_unlock(&vstdev->lock);
 		dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__);
 		retval = -EFAULT;
 		goto exit;
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 4cf27c7..f8d9045 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -37,10 +37,13 @@
 #define MON_IOCX_GET   _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
 #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
 #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
+/* #9 was MON_IOCT_SETAPI */
+#define MON_IOCX_GETX   _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get)
 
 #ifdef CONFIG_COMPAT
 #define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32)
 #define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32)
+#define MON_IOCX_GETX32   _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get32)
 #endif
 
 /*
@@ -92,7 +95,29 @@
 	int status;
 	unsigned int len_urb;	/* Length of data (submitted or actual) */
 	unsigned int len_cap;	/* Delivered length */
-	unsigned char setup[SETUP_LEN];	/* Only for Control S-type */
+	union {
+		unsigned char setup[SETUP_LEN];	/* Only for Control S-type */
+		struct iso_rec {
+			int error_count;
+			int numdesc;
+		} iso;
+	} s;
+	int interval;
+	int start_frame;
+	unsigned int xfer_flags;
+	unsigned int ndesc;	/* Actual number of ISO descriptors */
+};
+
+/*
+ * ISO vector, packed into the head of data stream.
+ * This has to take 16 bytes to make sure that the end of buffer
+ * wrap is not happening in the middle of a descriptor.
+ */
+struct mon_bin_isodesc {
+	int          iso_status;
+	unsigned int iso_off;
+	unsigned int iso_len;
+	u32 _pad;
 };
 
 /* per file statistic */
@@ -102,7 +127,7 @@
 };
 
 struct mon_bin_get {
-	struct mon_bin_hdr __user *hdr;	/* Only 48 bytes, not 64. */
+	struct mon_bin_hdr __user *hdr;	/* Can be 48 bytes or 64. */
 	void __user *data;
 	size_t alloc;		/* Length of data (can be zero) */
 };
@@ -131,6 +156,11 @@
 #define PKT_ALIGN   64
 #define PKT_SIZE    64
 
+#define PKT_SZ_API0 48	/* API 0 (2.6.20) size */
+#define PKT_SZ_API1 64	/* API 1 size: extra fields */
+
+#define ISODESC_MAX   128	/* Same number as usbfs allows, 2048 bytes. */
+
 /* max number of USB bus supported */
 #define MON_BIN_MAX_MINOR 128
 
@@ -360,12 +390,8 @@
     const struct urb *urb, char ev_type)
 {
 
-	if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S')
-		return '-';
-
 	if (urb->setup_packet == NULL)
 		return 'Z';
-
 	memcpy(setupb, urb->setup_packet, SETUP_LEN);
 	return 0;
 }
@@ -387,6 +413,26 @@
 	return 0;
 }
 
+static void mon_bin_get_isodesc(const struct mon_reader_bin *rp,
+    unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc)
+{
+	struct mon_bin_isodesc *dp;
+	struct usb_iso_packet_descriptor *fp;
+
+	fp = urb->iso_frame_desc;
+	while (ndesc-- != 0) {
+		dp = (struct mon_bin_isodesc *)
+		    (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE);
+		dp->iso_status = fp->status;
+		dp->iso_off = fp->offset;
+		dp->iso_len = (ev_type == 'S') ? fp->length : fp->actual_length;
+		dp->_pad = 0;
+		if ((offset += sizeof(struct mon_bin_isodesc)) >= rp->b_size)
+			offset = 0;
+		fp++;
+	}
+}
+
 static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
     char ev_type, int status)
 {
@@ -396,6 +442,7 @@
 	unsigned int urb_length;
 	unsigned int offset;
 	unsigned int length;
+	unsigned int ndesc, lendesc;
 	unsigned char dir;
 	struct mon_bin_hdr *ep;
 	char data_tag = 0;
@@ -407,6 +454,19 @@
 	/*
 	 * Find the maximum allowable length, then allocate space.
 	 */
+	if (usb_endpoint_xfer_isoc(epd)) {
+		if (urb->number_of_packets < 0) {
+			ndesc = 0;
+		} else if (urb->number_of_packets >= ISODESC_MAX) {
+			ndesc = ISODESC_MAX;
+		} else {
+			ndesc = urb->number_of_packets;
+		}
+	} else {
+		ndesc = 0;
+	}
+	lendesc = ndesc*sizeof(struct mon_bin_isodesc);
+
 	urb_length = (ev_type == 'S') ?
 	    urb->transfer_buffer_length : urb->actual_length;
 	length = urb_length;
@@ -429,10 +489,12 @@
 		dir = 0;
 	}
 
-	if (rp->mmap_active)
-		offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE);
-	else
-		offset = mon_buff_area_alloc(rp, length + PKT_SIZE);
+	if (rp->mmap_active) {
+		offset = mon_buff_area_alloc_contiguous(rp,
+						 length + PKT_SIZE + lendesc);
+	} else {
+		offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc);
+	}
 	if (offset == ~0) {
 		rp->cnt_lost++;
 		spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -456,9 +518,31 @@
 	ep->ts_usec = ts.tv_usec;
 	ep->status = status;
 	ep->len_urb = urb_length;
-	ep->len_cap = length;
+	ep->len_cap = length + lendesc;
+	ep->xfer_flags = urb->transfer_flags;
 
-	ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type);
+	if (usb_endpoint_xfer_int(epd)) {
+		ep->interval = urb->interval;
+	} else if (usb_endpoint_xfer_isoc(epd)) {
+		ep->interval = urb->interval;
+		ep->start_frame = urb->start_frame;
+		ep->s.iso.error_count = urb->error_count;
+		ep->s.iso.numdesc = urb->number_of_packets;
+	}
+
+	if (usb_endpoint_xfer_control(epd) && ev_type == 'S') {
+		ep->flag_setup = mon_bin_get_setup(ep->s.setup, urb, ev_type);
+	} else {
+		ep->flag_setup = '-';
+	}
+
+	if (ndesc != 0) {
+		ep->ndesc = ndesc;
+		mon_bin_get_isodesc(rp, offset, urb, ev_type, ndesc);
+		if ((offset += lendesc) >= rp->b_size)
+			offset -= rp->b_size;
+	}
+
 	if (length != 0) {
 		ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
 		if (ep->flag_data != 0) {	/* Yes, it's 0x00, not '0' */
@@ -592,7 +676,8 @@
  * Returns zero or error.
  */
 static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp,
-    struct mon_bin_hdr __user *hdr, void __user *data, unsigned int nbytes)
+    struct mon_bin_hdr __user *hdr, unsigned int hdrbytes,
+    void __user *data, unsigned int nbytes)
 {
 	unsigned long flags;
 	struct mon_bin_hdr *ep;
@@ -609,7 +694,7 @@
 
 	ep = MON_OFF2HDR(rp, rp->b_out);
 
-	if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) {
+	if (copy_to_user(hdr, ep, hdrbytes)) {
 		mutex_unlock(&rp->fetch_lock);
 		return -EFAULT;
 	}
@@ -657,6 +742,7 @@
     size_t nbytes, loff_t *ppos)
 {
 	struct mon_reader_bin *rp = file->private_data;
+	unsigned int hdrbytes = PKT_SZ_API0;
 	unsigned long flags;
 	struct mon_bin_hdr *ep;
 	unsigned int offset;
@@ -674,8 +760,8 @@
 
 	ep = MON_OFF2HDR(rp, rp->b_out);
 
-	if (rp->b_read < sizeof(struct mon_bin_hdr)) {
-		step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read);
+	if (rp->b_read < hdrbytes) {
+		step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read));
 		ptr = ((char *)ep) + rp->b_read;
 		if (step_len && copy_to_user(buf, ptr, step_len)) {
 			mutex_unlock(&rp->fetch_lock);
@@ -687,13 +773,13 @@
 		done += step_len;
 	}
 
-	if (rp->b_read >= sizeof(struct mon_bin_hdr)) {
+	if (rp->b_read >= hdrbytes) {
 		step_len = ep->len_cap;
-		step_len -= rp->b_read - sizeof(struct mon_bin_hdr);
+		step_len -= rp->b_read - hdrbytes;
 		if (step_len > nbytes)
 			step_len = nbytes;
 		offset = rp->b_out + PKT_SIZE;
-		offset += rp->b_read - sizeof(struct mon_bin_hdr);
+		offset += rp->b_read - hdrbytes;
 		if (offset >= rp->b_size)
 			offset -= rp->b_size;
 		if (copy_from_buf(rp, offset, buf, step_len)) {
@@ -709,7 +795,7 @@
 	/*
 	 * Check if whole packet was read, and if so, jump to the next one.
 	 */
-	if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) {
+	if (rp->b_read >= hdrbytes + ep->len_cap) {
 		spin_lock_irqsave(&rp->b_lock, flags);
 		mon_buff_area_free(rp, PKT_SIZE + ep->len_cap);
 		spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -908,6 +994,7 @@
 		break;
 
 	case MON_IOCX_GET:
+	case MON_IOCX_GETX:
 		{
 		struct mon_bin_get getb;
 
@@ -917,8 +1004,9 @@
 
 		if (getb.alloc > 0x10000000)	/* Want to cast to u32 */
 			return -EINVAL;
-		ret = mon_bin_get_event(file, rp,
-			  getb.hdr, getb.data, (unsigned int)getb.alloc);
+		ret = mon_bin_get_event(file, rp, getb.hdr,
+		    (cmd == MON_IOCX_GET)? PKT_SZ_API0: PKT_SZ_API1,
+		    getb.data, (unsigned int)getb.alloc);
 		}
 		break;
 
@@ -984,16 +1072,18 @@
 
 	switch (cmd) {
 
-	case MON_IOCX_GET32: {
+	case MON_IOCX_GET32:
+	case MON_IOCX_GETX32:
+		{
 		struct mon_bin_get32 getb;
 
 		if (copy_from_user(&getb, (void __user *)arg,
 					    sizeof(struct mon_bin_get32)))
 			return -EFAULT;
 
-		ret = mon_bin_get_event(file, rp,
-		    compat_ptr(getb.hdr32), compat_ptr(getb.data32),
-		    getb.alloc32);
+		ret = mon_bin_get_event(file, rp, compat_ptr(getb.hdr32),
+		    (cmd == MON_IOCX_GET32)? PKT_SZ_API0: PKT_SZ_API1,
+		    compat_ptr(getb.data32), getb.alloc32);
 		if (ret < 0)
 			return ret;
 		}
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 9985db0..b66e8544 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -20,8 +20,8 @@
 	  it's being used with, including the USB peripheral role,
 	  or the USB host role, or both.
 
-	  Texas Instruments parts using this IP include DaVinci 644x,
-	  OMAP 243x, OMAP 343x, and TUSB 6010.
+	  Texas Instruments familiies using this IP include DaVinci
+	  (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010.
 
 	  Analog Devices parts using this IP include Blackfin BF54x,
 	  BF525 and BF527.
@@ -40,7 +40,7 @@
 	default y if (BF54x && !BF544)
 	default y if (BF52x && !BF522 && !BF523)
 
-comment "DaVinci 644x USB support"
+comment "DaVinci 35x and 644x USB support"
 	depends on USB_MUSB_HDRC && ARCH_DAVINCI
 
 comment "OMAP 243x high speed USB support"
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 2dc7606..10d11ab 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -48,6 +48,9 @@
 #include "cppi_dma.h"
 
 
+#define USB_PHY_CTRL	IO_ADDRESS(USBPHY_CTL_PADDR)
+#define DM355_DEEPSLEEP	IO_ADDRESS(DM355_DEEPSLEEP_PADDR)
+
 /* REVISIT (PM) we should be able to keep the PHY in low power mode most
  * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0
  * and, when in host mode, autosuspending idle root ports... PHYPLLON
@@ -56,20 +59,26 @@
 
 static inline void phy_on(void)
 {
-	/* start the on-chip PHY and its PLL */
-	__raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON,
-			(void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR));
-	while ((__raw_readl((void __force __iomem *)
-				IO_ADDRESS(USBPHY_CTL_PADDR))
-			& USBPHY_PHYCLKGD) == 0)
+	u32	phy_ctrl = __raw_readl(USB_PHY_CTRL);
+
+	/* power everything up; start the on-chip PHY and its PLL */
+	phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN);
+	phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON;
+	__raw_writel(phy_ctrl, USB_PHY_CTRL);
+
+	/* wait for PLL to lock before proceeding */
+	while ((__raw_readl(USB_PHY_CTRL) & USBPHY_PHYCLKGD) == 0)
 		cpu_relax();
 }
 
 static inline void phy_off(void)
 {
-	/* powerdown the on-chip PHY and its oscillator */
-	__raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *)
-			IO_ADDRESS(USBPHY_CTL_PADDR));
+	u32	phy_ctrl = __raw_readl(USB_PHY_CTRL);
+
+	/* powerdown the on-chip PHY, its PLL, and the OTG block */
+	phy_ctrl &= ~(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON);
+	phy_ctrl |= USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN;
+	__raw_writel(phy_ctrl, USB_PHY_CTRL);
 }
 
 static int dma_off = 1;
@@ -126,10 +135,6 @@
 }
 
 
-/* REVISIT it's not clear whether DaVinci can support full OTG.  */
-
-static int vbus_state = -1;
-
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
 #define	portstate(stmt)		stmt
 #else
@@ -137,10 +142,19 @@
 #endif
 
 
-/* VBUS SWITCHING IS BOARD-SPECIFIC */
+/*
+ * VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM,
+ * which doesn't wire DRVVBUS to the FET that switches it.  Unclear
+ * if that's a problem with the DM6446 chip or just with that board.
+ *
+ * In either case, the DM355 EVM automates DRVVBUS the normal way,
+ * when J10 is out, and TI documents it as handling OTG.
+ */
 
 #ifdef CONFIG_MACH_DAVINCI_EVM
 
+static int vbus_state = -1;
+
 /* I2C operations are always synchronous, and require a task context.
  * With unloaded systems, using the shared workqueue seems to suffice
  * to satisfy the 100msec A_WAIT_VRISE timeout...
@@ -150,12 +164,12 @@
 	gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state);
 	vbus_state = !vbus_state;
 }
-static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus);
 
 #endif	/* EVM */
 
 static void davinci_source_power(struct musb *musb, int is_on, int immediate)
 {
+#ifdef CONFIG_MACH_DAVINCI_EVM
 	if (is_on)
 		is_on = 1;
 
@@ -163,16 +177,17 @@
 		return;
 	vbus_state = !is_on;		/* 0/1 vs "-1 == unknown/init" */
 
-#ifdef CONFIG_MACH_DAVINCI_EVM
 	if (machine_is_davinci_evm()) {
+		static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus);
+
 		if (immediate)
 			gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state);
 		else
 			schedule_work(&evm_vbus_work);
 	}
-#endif
 	if (immediate)
 		vbus_state = is_on;
+#endif
 }
 
 static void davinci_set_vbus(struct musb *musb, int is_on)
@@ -391,6 +406,17 @@
 	musb->board_set_vbus = davinci_set_vbus;
 	davinci_source_power(musb, 0, 1);
 
+	/* dm355 EVM swaps D+/D- for signal integrity, and
+	 * is clocked from the main 24 MHz crystal.
+	 */
+	if (machine_is_davinci_dm355_evm()) {
+		u32	phy_ctrl = __raw_readl(USB_PHY_CTRL);
+
+		phy_ctrl &= ~(3 << 9);
+		phy_ctrl |= USBPHY_DATAPOL;
+		__raw_writel(phy_ctrl, USB_PHY_CTRL);
+	}
+
 	/* reset the controller */
 	musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
 
@@ -401,8 +427,7 @@
 
 	/* NOTE:  irqs are in mixed mode, not bypass to pure-musb */
 	pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n",
-		revision, __raw_readl((void __force __iomem *)
-				IO_ADDRESS(USBPHY_CTL_PADDR)),
+		revision, __raw_readl(USB_PHY_CTRL),
 		musb_readb(tibase, DAVINCI_USB_CTRL_REG));
 
 	musb->isr = davinci_interrupt;
diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h
index 7fb6238..046c844 100644
--- a/drivers/usb/musb/davinci.h
+++ b/drivers/usb/musb/davinci.h
@@ -15,14 +15,21 @@
  */
 
 /* Integrated highspeed/otg PHY */
-#define	USBPHY_CTL_PADDR	(DAVINCI_SYSTEM_MODULE_BASE + 0x34)
-#define	USBPHY_PHYCLKGD		(1 << 8)
-#define	USBPHY_SESNDEN		(1 << 7)	/* v(sess_end) comparator */
-#define	USBPHY_VBDTCTEN		(1 << 6)	/* v(bus) comparator */
-#define	USBPHY_PHYPLLON		(1 << 4)	/* override pll suspend */
-#define	USBPHY_CLKO1SEL		(1 << 3)
-#define	USBPHY_OSCPDWN		(1 << 2)
-#define	USBPHY_PHYPDWN		(1 << 0)
+#define USBPHY_CTL_PADDR	(DAVINCI_SYSTEM_MODULE_BASE + 0x34)
+#define USBPHY_DATAPOL		BIT(11)	/* (dm355) switch D+/D- */
+#define USBPHY_PHYCLKGD		BIT(8)
+#define USBPHY_SESNDEN		BIT(7)	/* v(sess_end) comparator */
+#define USBPHY_VBDTCTEN		BIT(6)	/* v(bus) comparator */
+#define USBPHY_VBUSSENS		BIT(5)	/* (dm355,ro) is vbus > 0.5V */
+#define USBPHY_PHYPLLON		BIT(4)	/* override pll suspend */
+#define USBPHY_CLKO1SEL		BIT(3)
+#define USBPHY_OSCPDWN		BIT(2)
+#define USBPHY_OTGPDWN		BIT(1)
+#define USBPHY_PHYPDWN		BIT(0)
+
+#define DM355_DEEPSLEEP_PADDR	(DAVINCI_SYSTEM_MODULE_BASE + 0x48)
+#define DRVVBUS_FORCE		BIT(2)
+#define DRVVBUS_OVERRIDE	BIT(1)
 
 /* For now include usb OTG module registers here */
 #define DAVINCI_USB_VERSION_REG		0x00
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index af77e46..338cd16 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -769,7 +769,7 @@
 		case OTG_STATE_A_SUSPEND:
 			usb_hcd_resume_root_hub(musb_to_hcd(musb));
 			musb_root_disconnect(musb);
-			if (musb->a_wait_bcon != 0)
+			if (musb->a_wait_bcon != 0 && is_otg_enabled(musb))
 				musb_platform_try_idle(musb, jiffies
 					+ msecs_to_jiffies(musb->a_wait_bcon));
 			break;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 630946a..efb39b5 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -331,7 +331,6 @@
 	struct list_head	control;	/* of musb_qh */
 	struct list_head	in_bulk;	/* of musb_qh */
 	struct list_head	out_bulk;	/* of musb_qh */
-	struct musb_qh		*periodic[32];	/* tree of interrupt+iso */
 #endif
 
 	/* called with IRQs blocked; ON/nonzero implies starting a session,
@@ -479,10 +478,11 @@
 static inline int musb_read_fifosize(struct musb *musb,
 		struct musb_hw_ep *hw_ep, u8 epnum)
 {
+	void *mbase = musb->mregs;
 	u8 reg = 0;
 
 	/* read from core using indexed model */
-	reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE);
+	reg = musb_readb(mbase, MUSB_EP_OFFSET(epnum, MUSB_FIFOSIZE));
 	/* 0's returned when no more endpoints */
 	if (!reg)
 		return -ENODEV;
@@ -509,6 +509,7 @@
 {
 	musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
 	musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
+	musb->endpoints[0].is_shared_fifo = true;
 }
 #endif /* CONFIG_BLACKFIN */
 
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 6dbbd07..499c431 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -64,11 +64,8 @@
  *
  * - DMA (Mentor/OMAP) ...has at least toggle update problems
  *
- * - Still no traffic scheduling code to make NAKing for bulk or control
- *   transfers unable to starve other requests; or to make efficient use
- *   of hardware with periodic transfers.  (Note that network drivers
- *   commonly post bulk reads that stay pending for a long time; these
- *   would make very visible trouble.)
+ * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet
+ *   starvation ... nothing yet for TX, interrupt, or bulk.
  *
  * - Not tested with HNP, but some SRP paths seem to behave.
  *
@@ -88,11 +85,8 @@
  *
  * CONTROL transfers all go through ep0.  BULK ones go through dedicated IN
  * and OUT endpoints ... hardware is dedicated for those "async" queue(s).
- *
  * (Yes, bulk _could_ use more of the endpoints than that, and would even
- * benefit from it ... one remote device may easily be NAKing while others
- * need to perform transfers in that same direction.  The same thing could
- * be done in software though, assuming dma cooperates.)
+ * benefit from it.)
  *
  * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints.
  * So far that scheduling is both dumb and optimistic:  the endpoint will be
@@ -201,8 +195,9 @@
 		len = urb->iso_frame_desc[0].length;
 		break;
 	default:		/* bulk, interrupt */
-		buf = urb->transfer_buffer;
-		len = urb->transfer_buffer_length;
+		/* actual_length may be nonzero on retry paths */
+		buf = urb->transfer_buffer + urb->actual_length;
+		len = urb->transfer_buffer_length - urb->actual_length;
 	}
 
 	DBG(4, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n",
@@ -395,7 +390,6 @@
 			 * de-allocated if it's tracked and allocated;
 			 * and where we'd update the schedule tree...
 			 */
-			musb->periodic[ep->epnum] = NULL;
 			kfree(qh);
 			qh = NULL;
 			break;
@@ -1045,7 +1039,8 @@
 
 		/* NOTE:  this code path would be a good place to PAUSE a
 		 * control transfer, if another one is queued, so that
-		 * ep0 is more likely to stay busy.
+		 * ep0 is more likely to stay busy.  That's already done
+		 * for bulk RX transfers.
 		 *
 		 * if (qh->ring.next != &musb->control), then
 		 * we have a candidate... NAKing is *NOT* an error
@@ -1197,6 +1192,7 @@
 		/* NOTE:  this code path would be a good place to PAUSE a
 		 * transfer, if there's some other (nonperiodic) tx urb
 		 * that could use this fifo.  (dma complicates it...)
+		 * That's already done for bulk RX transfers.
 		 *
 		 * if (bulk && qh->ring.next != &musb->out_bulk), then
 		 * we have a candidate... NAKing is *NOT* an error
@@ -1358,6 +1354,50 @@
 
 #endif
 
+/* Schedule next QH from musb->in_bulk and move the current qh to
+ * the end; avoids starvation for other endpoints.
+ */
+static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep)
+{
+	struct dma_channel	*dma;
+	struct urb		*urb;
+	void __iomem		*mbase = musb->mregs;
+	void __iomem		*epio = ep->regs;
+	struct musb_qh		*cur_qh, *next_qh;
+	u16			rx_csr;
+
+	musb_ep_select(mbase, ep->epnum);
+	dma = is_dma_capable() ? ep->rx_channel : NULL;
+
+	/* clear nak timeout bit */
+	rx_csr = musb_readw(epio, MUSB_RXCSR);
+	rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+	rx_csr &= ~MUSB_RXCSR_DATAERROR;
+	musb_writew(epio, MUSB_RXCSR, rx_csr);
+
+	cur_qh = first_qh(&musb->in_bulk);
+	if (cur_qh) {
+		urb = next_urb(cur_qh);
+		if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+			dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+			musb->dma_controller->channel_abort(dma);
+			urb->actual_length += dma->actual_len;
+			dma->actual_len = 0L;
+		}
+		musb_save_toggle(ep, 1, urb);
+
+		/* move cur_qh to end of queue */
+		list_move_tail(&cur_qh->ring, &musb->in_bulk);
+
+		/* get the next qh from musb->in_bulk */
+		next_qh = first_qh(&musb->in_bulk);
+
+		/* set rx_reinit and schedule the next qh */
+		ep->rx_reinit = 1;
+		musb_start_urb(musb, 1, next_qh);
+	}
+}
+
 /*
  * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso,
  * and high-bandwidth IN transfer cases.
@@ -1421,18 +1461,26 @@
 	} else if (rx_csr & MUSB_RXCSR_DATAERROR) {
 
 		if (USB_ENDPOINT_XFER_ISOC != qh->type) {
-			/* NOTE this code path would be a good place to PAUSE a
-			 * transfer, if there's some other (nonperiodic) rx urb
-			 * that could use this fifo.  (dma complicates it...)
-			 *
-			 * if (bulk && qh->ring.next != &musb->in_bulk), then
-			 * we have a candidate... NAKing is *NOT* an error
-			 */
 			DBG(6, "RX end %d NAK timeout\n", epnum);
+
+			/* NOTE: NAKing is *NOT* an error, so we want to
+			 * continue.  Except ... if there's a request for
+			 * another QH, use that instead of starving it.
+			 *
+			 * Devices like Ethernet and serial adapters keep
+			 * reads posted at all times, which will starve
+			 * other devices without this logic.
+			 */
+			if (usb_pipebulk(urb->pipe)
+					&& qh->mux == 1
+					&& !list_is_singular(&musb->in_bulk)) {
+				musb_bulk_rx_nak_timeout(musb, hw_ep);
+				return;
+			}
 			musb_ep_select(mbase, epnum);
-			musb_writew(epio, MUSB_RXCSR,
-					MUSB_RXCSR_H_WZC_BITS
-					| MUSB_RXCSR_H_REQPKT);
+			rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+			rx_csr &= ~MUSB_RXCSR_DATAERROR;
+			musb_writew(epio, MUSB_RXCSR, rx_csr);
 
 			goto finish;
 		} else {
@@ -1711,31 +1759,27 @@
 
 	/* else, periodic transfers get muxed to other endpoints */
 
-	/* FIXME this doesn't consider direction, so it can only
-	 * work for one half of the endpoint hardware, and assumes
-	 * the previous cases handled all non-shared endpoints...
-	 */
-
-	/* we know this qh hasn't been scheduled, so all we need to do
+	/*
+	 * We know this qh hasn't been scheduled, so all we need to do
 	 * is choose which hardware endpoint to put it on ...
 	 *
 	 * REVISIT what we really want here is a regular schedule tree
-	 * like e.g. OHCI uses, but for now musb->periodic is just an
-	 * array of the _single_ logical endpoint associated with a
-	 * given physical one (identity mapping logical->physical).
-	 *
-	 * that simplistic approach makes TT scheduling a lot simpler;
-	 * there is none, and thus none of its complexity...
+	 * like e.g. OHCI uses.
 	 */
 	best_diff = 4096;
 	best_end = -1;
 
-	for (epnum = 1; epnum < musb->nr_endpoints; epnum++) {
+	for (epnum = 1, hw_ep = musb->endpoints + 1;
+			epnum < musb->nr_endpoints;
+			epnum++, hw_ep++) {
 		int	diff;
 
-		if (musb->periodic[epnum])
+		if (is_in || hw_ep->is_shared_fifo) {
+			if (hw_ep->in_qh  != NULL)
+				continue;
+		} else	if (hw_ep->out_qh != NULL)
 			continue;
-		hw_ep = &musb->endpoints[epnum];
+
 		if (hw_ep == musb->bulk_ep)
 			continue;
 
@@ -1756,6 +1800,17 @@
 			head = &musb->in_bulk;
 		else
 			head = &musb->out_bulk;
+
+		/* Enable bulk RX NAK timeout scheme when bulk requests are
+		 * multiplexed.  This scheme doen't work in high speed to full
+		 * speed scenario as NAK interrupts are not coming from a
+		 * full speed device connected to a high speed device.
+		 * NAK timeout interval is 8 (128 uframe or 16ms) for HS and
+		 * 4 (8 frame or 8ms) for FS device.
+		 */
+		if (is_in && qh->dev)
+			qh->intv_reg =
+				(USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4;
 		goto success;
 	} else if (best_end < 0) {
 		return -ENOSPC;
@@ -1764,7 +1819,6 @@
 	idle = 1;
 	qh->mux = 0;
 	hw_ep = musb->endpoints + best_end;
-	musb->periodic[best_end] = qh;
 	DBG(4, "qh %p periodic slot %d\n", qh, best_end);
 success:
 	if (head) {
@@ -1888,13 +1942,11 @@
 		 *
 		 * The downside of disabling this is that transfer scheduling
 		 * gets VERY unfair for nonperiodic transfers; a misbehaving
-		 * peripheral could make that hurt.  Or for reads, one that's
-		 * perfectly normal:  network and other drivers keep reads
-		 * posted at all times, having one pending for a week should
-		 * be perfectly safe.
+		 * peripheral could make that hurt.  That's perfectly normal
+		 * for reads from network or serial adapters ... so we have
+		 * partial NAKlimit support for bulk RX.
 		 *
-		 * The upside of disabling it is avoidng transfer scheduling
-		 * code to put this aside for while.
+		 * The upside of disabling it is simpler transfer scheduling.
 		 */
 		interval = 0;
 	}
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index e0e9ce5..bf677ac 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -285,7 +285,7 @@
 		desc->bDescLength = 9;
 		desc->bDescriptorType = 0x29;
 		desc->bNbrPorts = 1;
-		desc->wHubCharacteristics = __constant_cpu_to_le16(
+		desc->wHubCharacteristics = cpu_to_le16(
 				  0x0001	/* per-port power switching */
 				| 0x0010	/* no overcurrent reporting */
 				);
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index ee55b44..aa884d0 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -43,7 +43,7 @@
 
 config TWL4030_USB
 	tristate "TWL4030 USB Transceiver Driver"
-	depends on TWL4030_CORE
+	depends on TWL4030_CORE && REGULATOR_TWL4030
 	select USB_OTG_UTILS
 	help
 	  Enable this to support the USB OTG transceiver on TWL4030
@@ -51,4 +51,12 @@
 	  This transceiver supports high and full speed devices plus,
 	  in host mode, low speed.
 
+config NOP_USB_XCEIV
+	tristate "NOP USB Transceiver Driver"
+	select USB_OTG_UTILS
+	help
+	 this driver is to be used by all the usb transceiver which are either
+	 built-in with usb ip or which are autonomous and doesn't require any
+	 phy programming such as ISP1x04 etc.
+
 endif # USB || OTG
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index d73c7cf..2081678 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
+obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 
 ccflags-$(CONFIG_USB_DEBUG)	+= -DDEBUG
 ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
index 63a6036..1c26c94 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -13,6 +13,7 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/usb.h>
+#include <linux/workqueue.h>
 
 #include <linux/regulator/consumer.h>
 
@@ -34,6 +35,7 @@
 	struct regulator       *vbus_draw;
 	int			vbus_draw_enabled;
 	unsigned		mA;
+	struct work_struct	work;
 };
 
 
@@ -76,24 +78,26 @@
 	gpio_vbus->mA = mA;
 }
 
-/* VBUS change IRQ handler */
-static irqreturn_t gpio_vbus_irq(int irq, void *data)
+static int is_vbus_powered(struct gpio_vbus_mach_info *pdata)
 {
-	struct platform_device *pdev = data;
-	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
-	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
-	int gpio, vbus;
+	int vbus;
 
 	vbus = gpio_get_value(pdata->gpio_vbus);
 	if (pdata->gpio_vbus_inverted)
 		vbus = !vbus;
 
-	dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
-		vbus ? "supplied" : "inactive",
-		gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none");
+	return vbus;
+}
+
+static void gpio_vbus_work(struct work_struct *work)
+{
+	struct gpio_vbus_data *gpio_vbus =
+		container_of(work, struct gpio_vbus_data, work);
+	struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
+	int gpio;
 
 	if (!gpio_vbus->otg.gadget)
-		return IRQ_HANDLED;
+		return;
 
 	/* Peripheral controllers which manage the pullup themselves won't have
 	 * gpio_pullup configured here.  If it's configured here, we'll do what
@@ -101,7 +105,7 @@
 	 * that may complicate usb_gadget_{,dis}connect() support.
 	 */
 	gpio = pdata->gpio_pullup;
-	if (vbus) {
+	if (is_vbus_powered(pdata)) {
 		gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL;
 		usb_gadget_vbus_connect(gpio_vbus->otg.gadget);
 
@@ -121,6 +125,21 @@
 		usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget);
 		gpio_vbus->otg.state = OTG_STATE_B_IDLE;
 	}
+}
+
+/* VBUS change IRQ handler */
+static irqreturn_t gpio_vbus_irq(int irq, void *data)
+{
+	struct platform_device *pdev = data;
+	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
+	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
+
+	dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
+		is_vbus_powered(pdata) ? "supplied" : "inactive",
+		gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none");
+
+	if (gpio_vbus->otg.gadget)
+		schedule_work(&gpio_vbus->work);
 
 	return IRQ_HANDLED;
 }
@@ -257,6 +276,7 @@
 			irq, err);
 		goto err_irq;
 	}
+	INIT_WORK(&gpio_vbus->work, gpio_vbus_work);
 
 	/* only active when a gadget is registered */
 	err = otg_set_transceiver(&gpio_vbus->otg);
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
new file mode 100644
index 0000000..4b933f6
--- /dev/null
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -0,0 +1,180 @@
+/*
+ * drivers/usb/otg/nop-usb-xceiv.c
+ *
+ * NOP USB transceiver for all USB transceiver which are either built-in
+ * into USB IP or which are mostly autonomous.
+ *
+ * Copyright (C) 2009 Texas Instruments Inc
+ * Author: Ajay Kumar Gupta <ajay.gupta@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Current status:
+ * 	this is to add "nop" transceiver for all those phy which is
+ * 	autonomous such as isp1504 etc.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb/otg.h>
+
+struct nop_usb_xceiv {
+	struct otg_transceiver	otg;
+	struct device		*dev;
+};
+
+static u64 nop_xceiv_dmamask = DMA_32BIT_MASK;
+
+static struct platform_device nop_xceiv_device = {
+	.name           = "nop_usb_xceiv",
+	.id             = -1,
+	.dev = {
+		.dma_mask               = &nop_xceiv_dmamask,
+		.coherent_dma_mask      = DMA_32BIT_MASK,
+		.platform_data          = NULL,
+	},
+};
+
+void usb_nop_xceiv_register(void)
+{
+	if (platform_device_register(&nop_xceiv_device) < 0) {
+		printk(KERN_ERR "Unable to register usb nop transceiver\n");
+		return;
+	}
+}
+
+void usb_nop_xceiv_unregister(void)
+{
+	platform_device_unregister(&nop_xceiv_device);
+}
+
+static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x)
+{
+	return container_of(x, struct nop_usb_xceiv, otg);
+}
+
+static int nop_set_suspend(struct otg_transceiver *x, int suspend)
+{
+	return 0;
+}
+
+static int nop_set_peripheral(struct otg_transceiver *x,
+		struct usb_gadget *gadget)
+{
+	struct nop_usb_xceiv *nop;
+
+	if (!x)
+		return -ENODEV;
+
+	nop = xceiv_to_nop(x);
+
+	if (!gadget) {
+		nop->otg.gadget = NULL;
+		return -ENODEV;
+	}
+
+	nop->otg.gadget = gadget;
+	nop->otg.state = OTG_STATE_B_IDLE;
+	return 0;
+}
+
+static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host)
+{
+	struct nop_usb_xceiv *nop;
+
+	if (!x)
+		return -ENODEV;
+
+	nop = xceiv_to_nop(x);
+
+	if (!host) {
+		nop->otg.host = NULL;
+		return -ENODEV;
+	}
+
+	nop->otg.host = host;
+	return 0;
+}
+
+static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
+{
+	struct nop_usb_xceiv	*nop;
+	int err;
+
+	nop = kzalloc(sizeof *nop, GFP_KERNEL);
+	if (!nop)
+		return -ENOMEM;
+
+	nop->dev		= &pdev->dev;
+	nop->otg.dev		= nop->dev;
+	nop->otg.label		= "nop-xceiv";
+	nop->otg.state		= OTG_STATE_UNDEFINED;
+	nop->otg.set_host	= nop_set_host;
+	nop->otg.set_peripheral	= nop_set_peripheral;
+	nop->otg.set_suspend	= nop_set_suspend;
+
+	err = otg_set_transceiver(&nop->otg);
+	if (err) {
+		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
+			err);
+		goto exit;
+	}
+
+	platform_set_drvdata(pdev, nop);
+
+	return 0;
+exit:
+	kfree(nop);
+	return err;
+}
+
+static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
+{
+	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
+
+	otg_set_transceiver(NULL);
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(nop);
+
+	return 0;
+}
+
+static struct platform_driver nop_usb_xceiv_driver = {
+	.probe		= nop_usb_xceiv_probe,
+	.remove		= __devexit_p(nop_usb_xceiv_remove),
+	.driver		= {
+		.name	= "nop_usb_xceiv",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init nop_usb_xceiv_init(void)
+{
+	return platform_driver_register(&nop_usb_xceiv_driver);
+}
+subsys_initcall(nop_usb_xceiv_init);
+
+static void __exit nop_usb_xceiv_exit(void)
+{
+	platform_driver_unregister(&nop_usb_xceiv_driver);
+}
+module_exit(nop_usb_xceiv_exit);
+
+MODULE_ALIAS("platform:nop_usb_xceiv");
+MODULE_AUTHOR("Texas Instruments Inc");
+MODULE_DESCRIPTION("NOP USB Transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 416e441..d9478d0 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -34,6 +34,8 @@
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
 #include <linux/i2c/twl4030.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
 
 
 /* Register defines */
@@ -246,6 +248,11 @@
 	struct otg_transceiver	otg;
 	struct device		*dev;
 
+	/* TWL4030 internal USB regulator supplies */
+	struct regulator	*usb1v5;
+	struct regulator	*usb1v8;
+	struct regulator	*usb3v1;
+
 	/* for vbus reporting with irqs disabled */
 	spinlock_t		lock;
 
@@ -434,6 +441,18 @@
 
 	pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
 	if (on) {
+		regulator_enable(twl->usb3v1);
+		regulator_enable(twl->usb1v8);
+		/*
+		 * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
+		 * in twl4030) resets the VUSB_DEDICATED2 register. This reset
+		 * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
+		 * SLEEP. We work around this by clearing the bit after usv3v1
+		 * is re-activated. This ensures that VUSB3V1 is really active.
+		 */
+		twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
+							VUSB_DEDICATED2);
+		regulator_enable(twl->usb1v5);
 		pwr &= ~PHY_PWR_PHYPWD;
 		WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
 		twl4030_usb_write(twl, PHY_CLK_CTRL,
@@ -443,6 +462,9 @@
 	} else  {
 		pwr |= PHY_PWR_PHYPWD;
 		WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
+		regulator_disable(twl->usb1v5);
+		regulator_disable(twl->usb1v8);
+		regulator_disable(twl->usb3v1);
 	}
 }
 
@@ -468,7 +490,7 @@
 	twl->asleep = 0;
 }
 
-static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
+static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
 {
 	/* Enable writing to power configuration registers */
 	twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY);
@@ -480,20 +502,45 @@
 	/* input to VUSB3V1 LDO is from VBAT, not VBUS */
 	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
 
-	/* turn on 3.1V regulator */
-	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP);
+	/* Initialize 3.1V regulator */
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
+
+	twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
+	if (IS_ERR(twl->usb3v1))
+		return -ENODEV;
+
 	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
 
-	/* turn on 1.5V regulator */
-	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP);
+	/* Initialize 1.5V regulator */
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
+
+	twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
+	if (IS_ERR(twl->usb1v5))
+		goto fail1;
+
 	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
 
-	/* turn on 1.8V regulator */
-	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP);
+	/* Initialize 1.8V regulator */
+	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
+
+	twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
+	if (IS_ERR(twl->usb1v8))
+		goto fail2;
+
 	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
 
 	/* disable access to power configuration registers */
 	twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY);
+
+	return 0;
+
+fail2:
+	regulator_put(twl->usb1v5);
+	twl->usb1v5 = NULL;
+fail1:
+	regulator_put(twl->usb3v1);
+	twl->usb3v1 = NULL;
+	return -ENODEV;
 }
 
 static ssize_t twl4030_usb_vbus_show(struct device *dev,
@@ -598,7 +645,7 @@
 {
 	struct twl4030_usb_data *pdata = pdev->dev.platform_data;
 	struct twl4030_usb	*twl;
-	int			status;
+	int			status, err;
 
 	if (!pdata) {
 		dev_dbg(&pdev->dev, "platform_data not available\n");
@@ -622,7 +669,12 @@
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
 
-	twl4030_usb_ldo_init(twl);
+	err = twl4030_usb_ldo_init(twl);
+	if (err) {
+		dev_err(&pdev->dev, "ldo init failed\n");
+		kfree(twl);
+		return err;
+	}
 	otg_set_transceiver(&twl->otg);
 
 	platform_set_drvdata(pdev, twl);
@@ -688,6 +740,9 @@
 	twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
 
 	twl4030_phy_power(twl, 0);
+	regulator_put(twl->usb1v5);
+	regulator_put(twl->usb1v8);
+	regulator_put(twl->usb3v1);
 
 	kfree(twl);
 
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index b361f05..a65f919 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -116,14 +116,14 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called digi_acceleport.
 
-config USB_SERIAL_CP2101
-	tristate "USB CP2101 UART Bridge Controller"
+config USB_SERIAL_CP210X
+	tristate "USB CP210x family of UART Bridge Controllers"
 	help
-	  Say Y here if you want to use a CP2101/CP2102 based USB to RS232
-	  converter.
+	  Say Y here if you want to use a CP2101/CP2102/CP2103 based USB
+	  to RS232 converters.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called cp2101.
+	  module will be called cp210x.
 
 config USB_SERIAL_CYPRESS_M8
 	tristate "USB Cypress M8 USB Serial Driver"
@@ -472,6 +472,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called oti6858.
 
+config USB_SERIAL_QUALCOMM
+	tristate "USB Qualcomm Serial modem"
+	help
+	  Say Y here if you have a Qualcomm USB modem device.  These are
+	  usually wireless cellular modems.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called qcserial.
+
 config USB_SERIAL_SPCP8X5
 	tristate "USB SPCP8x5 USB To Serial Driver"
 	help
@@ -515,6 +524,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called sierra.
 
+config USB_SERIAL_SYMBOL
+	tristate "USB Symbol Barcode driver (serial mode)"
+	help
+	  Say Y here if you want to use a Symbol USB Barcode device
+	  in serial emulation mode.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called symbolserial.
+
 config USB_SERIAL_TI
 	tristate "USB TI 3410/5052 Serial Driver"
 	help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index b75be91..66619be 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -15,7 +15,7 @@
 obj-$(CONFIG_USB_SERIAL_ARK3116)		+= ark3116.o
 obj-$(CONFIG_USB_SERIAL_BELKIN)			+= belkin_sa.o
 obj-$(CONFIG_USB_SERIAL_CH341)			+= ch341.o
-obj-$(CONFIG_USB_SERIAL_CP2101)			+= cp2101.o
+obj-$(CONFIG_USB_SERIAL_CP210X)			+= cp210x.o
 obj-$(CONFIG_USB_SERIAL_CYBERJACK)		+= cyberjack.o
 obj-$(CONFIG_USB_SERIAL_CYPRESS_M8)		+= cypress_m8.o
 obj-$(CONFIG_USB_SERIAL_DEBUG)			+= usb_debug.o
@@ -45,10 +45,12 @@
 obj-$(CONFIG_USB_SERIAL_OPTION)			+= option.o
 obj-$(CONFIG_USB_SERIAL_OTI6858)		+= oti6858.o
 obj-$(CONFIG_USB_SERIAL_PL2303)			+= pl2303.o
+obj-$(CONFIG_USB_SERIAL_QUALCOMM)		+= qcserial.o
 obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
 obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI)		+= siemens_mpi.o
 obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS)		+= sierra.o
 obj-$(CONFIG_USB_SERIAL_SPCP8X5)		+= spcp8x5.o
+obj-$(CONFIG_USB_SERIAL_SYMBOL)			+= symbolserial.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/ch341.c b/drivers/usb/serial/ch341.c
index f61e3ca..ab4cc27 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -1,5 +1,7 @@
 /*
  * Copyright 2007, Frank A Kingswood <frank@kingswood-consulting.co.uk>
+ * Copyright 2007, Werner Cornelius <werner@cornelius-consult.de>
+ * Copyright 2009, Boris Hajduk <boris@hajduk.org>
  *
  * ch341.c implements a serial port driver for the Winchiphead CH341.
  *
@@ -21,9 +23,39 @@
 #include <linux/usb/serial.h>
 #include <linux/serial.h>
 
-#define DEFAULT_BAUD_RATE 2400
+#define DEFAULT_BAUD_RATE 9600
 #define DEFAULT_TIMEOUT   1000
 
+/* flags for IO-Bits */
+#define CH341_BIT_RTS (1 << 6)
+#define CH341_BIT_DTR (1 << 5)
+
+/******************************/
+/* interrupt pipe definitions */
+/******************************/
+/* always 4 interrupt bytes */
+/* first irq byte normally 0x08 */
+/* second irq byte base 0x7d + below */
+/* third irq byte base 0x94 + below */
+/* fourth irq byte normally 0xee */
+
+/* second interrupt byte */
+#define CH341_MULT_STAT 0x04 /* multiple status since last interrupt event */
+
+/* status returned in third interrupt answer byte, inverted in data
+   from irq */
+#define CH341_BIT_CTS 0x01
+#define CH341_BIT_DSR 0x02
+#define CH341_BIT_RI  0x04
+#define CH341_BIT_DCD 0x08
+#define CH341_BITS_MODEM_STAT 0x0f /* all bits */
+
+/*******************************/
+/* baudrate calculation factor */
+/*******************************/
+#define CH341_BAUDBASE_FACTOR 1532620800
+#define CH341_BAUDBASE_DIVMAX 3
+
 static int debug;
 
 static struct usb_device_id id_table [] = {
@@ -34,9 +66,12 @@
 MODULE_DEVICE_TABLE(usb, id_table);
 
 struct ch341_private {
-	unsigned baud_rate;
-	u8 dtr;
-	u8 rts;
+	spinlock_t lock; /* access lock */
+	wait_queue_head_t delta_msr_wait; /* wait queue for modem status */
+	unsigned baud_rate; /* set baud rate */
+	u8 line_control; /* set line control value RTS/DTR */
+	u8 line_status; /* active status of modem control inputs */
+	u8 multi_status_change; /* status changed multiple since last call */
 };
 
 static int ch341_control_out(struct usb_device *dev, u8 request,
@@ -72,37 +107,28 @@
 {
 	short a, b;
 	int r;
+	unsigned long factor;
+	short divisor;
 
 	dbg("ch341_set_baudrate(%d)", priv->baud_rate);
-	switch (priv->baud_rate) {
-	case 2400:
-		a = 0xd901;
-		b = 0x0038;
-		break;
-	case 4800:
-		a = 0x6402;
-		b = 0x001f;
-		break;
-	case 9600:
-		a = 0xb202;
-		b = 0x0013;
-		break;
-	case 19200:
-		a = 0xd902;
-		b = 0x000d;
-		break;
-	case 38400:
-		a = 0x6403;
-		b = 0x000a;
-		break;
-	case 115200:
-		a = 0xcc03;
-		b = 0x0008;
-		break;
-	default:
+
+	if (!priv->baud_rate)
 		return -EINVAL;
+	factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate);
+	divisor = CH341_BAUDBASE_DIVMAX;
+
+	while ((factor > 0xfff0) && divisor) {
+		factor >>= 3;
+		divisor--;
 	}
 
+	if (factor > 0xfff0)
+		return -EINVAL;
+
+	factor = 0x10000 - factor;
+	a = (factor & 0xff00) | divisor;
+	b = factor & 0xff;
+
 	r = ch341_control_out(dev, 0x9a, 0x1312, a);
 	if (!r)
 		r = ch341_control_out(dev, 0x9a, 0x0f2c, b);
@@ -110,19 +136,18 @@
 	return r;
 }
 
-static int ch341_set_handshake(struct usb_device *dev,
-			       struct ch341_private *priv)
+static int ch341_set_handshake(struct usb_device *dev, u8 control)
 {
-	dbg("ch341_set_handshake(%d,%d)", priv->dtr, priv->rts);
-	return ch341_control_out(dev, 0xa4,
-		~((priv->dtr?1<<5:0)|(priv->rts?1<<6:0)), 0);
+	dbg("ch341_set_handshake(0x%02x)", control);
+	return ch341_control_out(dev, 0xa4, ~control, 0);
 }
 
-static int ch341_get_status(struct usb_device *dev)
+static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
 {
 	char *buffer;
 	int r;
 	const unsigned size = 8;
+	unsigned long flags;
 
 	dbg("ch341_get_status()");
 
@@ -134,10 +159,15 @@
 	if (r < 0)
 		goto out;
 
-	/* Not having the datasheet for the CH341, we ignore the bytes returned
-	 * from the device. Return error if the device did not respond in time.
-	 */
-	r = 0;
+	/* setup the private status if available */
+	if (r == 2) {
+		r = 0;
+		spin_lock_irqsave(&priv->lock, flags);
+		priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
+		priv->multi_status_change = 0;
+		spin_unlock_irqrestore(&priv->lock, flags);
+	} else
+		r = -EPROTO;
 
 out:	kfree(buffer);
 	return r;
@@ -180,7 +210,7 @@
 		goto out;
 
 	/* expect 0xff 0xee */
-	r = ch341_get_status(dev);
+	r = ch341_get_status(dev, priv);
 	if (r < 0)
 		goto out;
 
@@ -192,12 +222,12 @@
 	if (r < 0)
 		goto out;
 
-	r = ch341_set_handshake(dev, priv);
+	r = ch341_set_handshake(dev, priv->line_control);
 	if (r < 0)
 		goto out;
 
 	/* expect 0x9f 0xee */
-	r = ch341_get_status(dev);
+	r = ch341_get_status(dev, priv);
 
 out:	kfree(buffer);
 	return r;
@@ -216,9 +246,10 @@
 	if (!priv)
 		return -ENOMEM;
 
+	spin_lock_init(&priv->lock);
+	init_waitqueue_head(&priv->delta_msr_wait);
 	priv->baud_rate = DEFAULT_BAUD_RATE;
-	priv->dtr = 1;
-	priv->rts = 1;
+	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
 	r = ch341_configure(serial->dev, priv);
 	if (r < 0)
@@ -231,6 +262,35 @@
 	return r;
 }
 
+static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
+				struct file *filp)
+{
+	struct ch341_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int c_cflag;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	/* shutdown our urbs */
+	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);
+
+	if (tty) {
+		c_cflag = tty->termios->c_cflag;
+		if (c_cflag & HUPCL) {
+			/* drop DTR and RTS */
+			spin_lock_irqsave(&priv->lock, flags);
+			priv->line_control = 0;
+			spin_unlock_irqrestore(&priv->lock, flags);
+			ch341_set_handshake(port->serial->dev, 0);
+		}
+	}
+	wake_up_interruptible(&priv->delta_msr_wait);
+}
+
+
 /* open this device, set default parameters */
 static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
 				struct file *filp)
@@ -242,14 +302,13 @@
 	dbg("ch341_open()");
 
 	priv->baud_rate = DEFAULT_BAUD_RATE;
-	priv->dtr = 1;
-	priv->rts = 1;
+	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
 	r = ch341_configure(serial->dev, priv);
 	if (r)
 		goto out;
 
-	r = ch341_set_handshake(serial->dev, priv);
+	r = ch341_set_handshake(serial->dev, priv->line_control);
 	if (r)
 		goto out;
 
@@ -257,6 +316,16 @@
 	if (r)
 		goto out;
 
+	dbg("%s - submitting interrupt urb", __func__);
+	port->interrupt_in_urb->dev = serial->dev;
+	r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+	if (r) {
+		dev_err(&port->dev, "%s - failed submitting interrupt urb,"
+			" error %d\n", __func__, r);
+		ch341_close(tty, port, NULL);
+		return -EPROTO;
+	}
+
 	r = usb_serial_generic_open(tty, port, filp);
 
 out:	return r;
@@ -270,46 +339,224 @@
 {
 	struct ch341_private *priv = usb_get_serial_port_data(port);
 	unsigned baud_rate;
+	unsigned long flags;
 
 	dbg("ch341_set_termios()");
 
+	if (!tty || !tty->termios)
+		return;
+
 	baud_rate = tty_get_baud_rate(tty);
 
-	switch (baud_rate) {
-	case 2400:
-	case 4800:
-	case 9600:
-	case 19200:
-	case 38400:
-	case 115200:
-		priv->baud_rate = baud_rate;
-		break;
-	default:
-		dbg("Rate %d not supported, using %d",
-			baud_rate, DEFAULT_BAUD_RATE);
-		priv->baud_rate = DEFAULT_BAUD_RATE;
+	priv->baud_rate = baud_rate;
+
+	if (baud_rate) {
+		spin_lock_irqsave(&priv->lock, flags);
+		priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
+		spin_unlock_irqrestore(&priv->lock, flags);
+		ch341_set_baudrate(port->serial->dev, priv);
+	} else {
+		spin_lock_irqsave(&priv->lock, flags);
+		priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
+		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 
-	ch341_set_baudrate(port->serial->dev, priv);
+	ch341_set_handshake(port->serial->dev, priv->line_control);
 
 	/* Unimplemented:
 	 * (cflag & CSIZE) : data bits [5, 8]
 	 * (cflag & PARENB) : parity {NONE, EVEN, ODD}
 	 * (cflag & CSTOPB) : stop bits [1, 2]
 	 */
+}
 
-	 /* Copy back the old hardware settings */
-	 tty_termios_copy_hw(tty->termios, old_termios);
-	 /* And re-encode with the new baud */
-	 tty_encode_baud_rate(tty, baud_rate, baud_rate);
+static int ch341_tiocmset(struct tty_struct *tty, struct file *file,
+			  unsigned int set, unsigned int clear)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ch341_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 |= CH341_BIT_RTS;
+	if (set & TIOCM_DTR)
+		priv->line_control |= CH341_BIT_DTR;
+	if (clear & TIOCM_RTS)
+		priv->line_control &= ~CH341_BIT_RTS;
+	if (clear & TIOCM_DTR)
+		priv->line_control &= ~CH341_BIT_DTR;
+	control = priv->line_control;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return ch341_set_handshake(port->serial->dev, control);
+}
+
+static void ch341_read_int_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+	unsigned char *data = urb->transfer_buffer;
+	unsigned int actual_length = urb->actual_length;
+	int status;
+
+	dbg("%s (%d)", __func__, port->number);
+
+	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", __func__,
+		    urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d", __func__,
+		    urb->status);
+		goto exit;
+	}
+
+	usb_serial_debug_data(debug, &port->dev, __func__,
+			      urb->actual_length, urb->transfer_buffer);
+
+	if (actual_length >= 4) {
+		struct ch341_private *priv = usb_get_serial_port_data(port);
+		unsigned long flags;
+
+		spin_lock_irqsave(&priv->lock, flags);
+		priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT;
+		if ((data[1] & CH341_MULT_STAT))
+			priv->multi_status_change = 1;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		wake_up_interruptible(&priv->delta_msr_wait);
+	}
+
+exit:
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status)
+		dev_err(&urb->dev->dev,
+			"%s - usb_submit_urb failed with result %d\n",
+			__func__, status);
+}
+
+static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+{
+	struct ch341_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	u8 prevstatus;
+	u8 status;
+	u8 changed;
+	u8 multi_change = 0;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	prevstatus = priv->line_status;
+	priv->multi_status_change = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	while (!multi_change) {
+		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;
+		multi_change = priv->multi_status_change;
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		changed = prevstatus ^ status;
+
+		if (((arg & TIOCM_RNG) && (changed & CH341_BIT_RI)) ||
+		    ((arg & TIOCM_DSR) && (changed & CH341_BIT_DSR)) ||
+		    ((arg & TIOCM_CD)  && (changed & CH341_BIT_DCD)) ||
+		    ((arg & TIOCM_CTS) && (changed & CH341_BIT_CTS))) {
+			return 0;
+		}
+		prevstatus = status;
+	}
+
+	return 0;
+}
+
+/*static int ch341_ioctl(struct usb_serial_port *port, struct file *file,*/
+static int ch341_ioctl(struct tty_struct *tty, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+
+	switch (cmd) {
+	case TIOCMIWAIT:
+		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
+		return wait_modem_info(port, arg);
+
+	default:
+		dbg("%s not supported = 0x%04x", __func__, cmd);
+		break;
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static int ch341_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ch341_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	u8 mcr;
+	u8 status;
+	unsigned int result;
+
+	dbg("%s (%d)", __func__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	mcr = priv->line_control;
+	status = priv->line_status;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	result = ((mcr & CH341_BIT_DTR)		? TIOCM_DTR : 0)
+		  | ((mcr & CH341_BIT_RTS)	? TIOCM_RTS : 0)
+		  | ((status & CH341_BIT_CTS)	? TIOCM_CTS : 0)
+		  | ((status & CH341_BIT_DSR)	? TIOCM_DSR : 0)
+		  | ((status & CH341_BIT_RI)	? TIOCM_RI  : 0)
+		  | ((status & CH341_BIT_DCD)	? TIOCM_CD  : 0);
+
+	dbg("%s - result = %x", __func__, result);
+
+	return result;
+}
+
+
+static int ch341_reset_resume(struct usb_interface *intf)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_serial *serial = NULL;
+	struct ch341_private *priv;
+
+	serial = usb_get_intfdata(intf);
+	priv = usb_get_serial_port_data(serial->port[0]);
+
+	/*reconfigure ch341 serial port after bus-reset*/
+	ch341_configure(dev, priv);
+
+	usb_serial_resume(intf);
+
+	return 0;
 }
 
 static struct usb_driver ch341_driver = {
 	.name		= "ch341",
 	.probe		= usb_serial_probe,
 	.disconnect	= usb_serial_disconnect,
+	.suspend	= usb_serial_suspend,
+	.resume		= usb_serial_resume,
+	.reset_resume	= ch341_reset_resume,
 	.id_table	= id_table,
 	.no_dynamic_id	= 1,
+	.supports_autosuspend =	1,
 };
 
 static struct usb_serial_driver ch341_device = {
@@ -317,12 +564,17 @@
 		.owner	= THIS_MODULE,
 		.name	= "ch341-uart",
 	},
-	.id_table         = id_table,
-	.usb_driver       = &ch341_driver,
-	.num_ports        = 1,
-	.open             = ch341_open,
-	.set_termios      = ch341_set_termios,
-	.attach           = ch341_attach,
+	.id_table          = id_table,
+	.usb_driver        = &ch341_driver,
+	.num_ports         = 1,
+	.open              = ch341_open,
+	.close             = ch341_close,
+	.ioctl             = ch341_ioctl,
+	.set_termios       = ch341_set_termios,
+	.tiocmget          = ch341_tiocmget,
+	.tiocmset          = ch341_tiocmset,
+	.read_int_callback = ch341_read_int_callback,
+	.attach            = ch341_attach,
 };
 
 static int __init ch341_init(void)
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp210x.c
similarity index 84%
rename from drivers/usb/serial/cp2101.c
rename to drivers/usb/serial/cp210x.c
index 027f4b7..e8d5133 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp210x.c
@@ -11,10 +11,6 @@
  * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow
  * control thanks to Munir Nassar nassarmu@real-time.com
  *
- * Outstanding Issues:
- *  Buffers are not flushed when the port is opened.
- *  Multiple calls to write() may fail with "Resource temporarily unavailable"
- *
  */
 
 #include <linux/kernel.h>
@@ -31,7 +27,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.07"
+#define DRIVER_VERSION "v0.08"
 #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
 
 /*
@@ -42,17 +38,21 @@
 static void cp2101_cleanup(struct usb_serial_port *);
 static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
 							struct file*);
-static void cp2101_get_termios(struct tty_struct *);
+static void cp2101_get_termios(struct tty_struct *,
+	struct usb_serial_port *port);
+static void cp2101_get_termios_port(struct usb_serial_port *port,
+	unsigned int *cflagp, unsigned int *baudp);
 static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *,
 							struct ktermios*);
 static int cp2101_tiocmget(struct tty_struct *, struct file *);
 static int cp2101_tiocmset(struct tty_struct *, struct file *,
 		unsigned int, unsigned int);
+static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *,
+		unsigned int, unsigned int);
 static void cp2101_break_ctl(struct tty_struct *, int);
 static int cp2101_startup(struct usb_serial *);
 static void cp2101_shutdown(struct usb_serial *);
 
-
 static int debug;
 
 static struct usb_device_id id_table [] = {
@@ -79,6 +79,7 @@
 	{ 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, 0x819F) }, /* MJS USB Toslink Switcher */
 	{ USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
 	{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
 	{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
@@ -90,6 +91,7 @@
 	{ USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
 	{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
 	{ USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
+	{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
@@ -224,7 +226,7 @@
 	kfree(buf);
 
 	if (result != size) {
-		dev_err(&port->dev, "%s - Unable to send config request, "
+		dbg("%s - Unable to send config request, "
 				"request=0x%x size=%d result=%d\n",
 				__func__, request, size, result);
 		return -EPROTO;
@@ -275,7 +277,7 @@
 	kfree(buf);
 
 	if ((size > 2 && result != size) || result < 0) {
-		dev_err(&port->dev, "%s - Unable to send request, "
+		dbg("%s - Unable to send request, "
 				"request=0x%x size=%d result=%d\n",
 				__func__, request, size, result);
 		return -EPROTO;
@@ -300,6 +302,47 @@
 	return cp2101_set_config(port, request, &data, 2);
 }
 
+/*
+ * cp2101_quantise_baudrate
+ * Quantises the baud rate as per AN205 Table 1
+ */
+static unsigned int cp2101_quantise_baudrate(unsigned int baud) {
+	if      (baud <= 56)       baud = 0;
+	else if (baud <= 300)      baud = 300;
+	else if (baud <= 600)      baud = 600;
+	else if (baud <= 1200)     baud = 1200;
+	else if (baud <= 1800)     baud = 1800;
+	else if (baud <= 2400)     baud = 2400;
+	else if (baud <= 4000)     baud = 4000;
+	else if (baud <= 4803)     baud = 4800;
+	else if (baud <= 7207)     baud = 7200;
+	else if (baud <= 9612)     baud = 9600;
+	else if (baud <= 14428)    baud = 14400;
+	else if (baud <= 16062)    baud = 16000;
+	else if (baud <= 19250)    baud = 19200;
+	else if (baud <= 28912)    baud = 28800;
+	else if (baud <= 38601)    baud = 38400;
+	else if (baud <= 51558)    baud = 51200;
+	else if (baud <= 56280)    baud = 56000;
+	else if (baud <= 58053)    baud = 57600;
+	else if (baud <= 64111)    baud = 64000;
+	else if (baud <= 77608)    baud = 76800;
+	else if (baud <= 117028)   baud = 115200;
+	else if (baud <= 129347)   baud = 128000;
+	else if (baud <= 156868)   baud = 153600;
+	else if (baud <= 237832)   baud = 230400;
+	else if (baud <= 254234)   baud = 250000;
+	else if (baud <= 273066)   baud = 256000;
+	else if (baud <= 491520)   baud = 460800;
+	else if (baud <= 567138)   baud = 500000;
+	else if (baud <= 670254)   baud = 576000;
+	else if (baud <= 1053257)  baud = 921600;
+	else if (baud <= 1474560)  baud = 1228800;
+	else if (baud <= 2457600)  baud = 1843200;
+	else                       baud = 3686400;
+	return baud;
+}
+
 static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port,
 				struct file *filp)
 {
@@ -330,10 +373,12 @@
 	}
 
 	/* Configure the termios structure */
-	cp2101_get_termios(tty);
+	cp2101_get_termios(tty, port);
 
 	/* Set the DTR and RTS pins low */
-	cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0);
+	cp2101_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data
+			: port,
+		NULL, TIOCM_DTR | TIOCM_RTS, 0);
 
 	return 0;
 }
@@ -375,9 +420,31 @@
  * from the device, corrects any unsupported values, and configures the
  * termios structure to reflect the state of the device
  */
-static void cp2101_get_termios (struct tty_struct *tty)
+static void cp2101_get_termios(struct tty_struct *tty,
+	struct usb_serial_port *port)
 {
-	struct usb_serial_port *port = tty->driver_data;
+	unsigned int baud;
+
+	if (tty) {
+		cp2101_get_termios_port(tty->driver_data,
+			&tty->termios->c_cflag, &baud);
+		tty_encode_baud_rate(tty, baud, baud);
+	}
+
+	else {
+		unsigned int cflag;
+		cflag = 0;
+		cp2101_get_termios_port(port, &cflag, &baud);
+	}
+}
+
+/*
+ * cp2101_get_termios_port
+ * This is the heart of cp2101_get_termios which always uses a &usb_serial_port.
+ */
+static void cp2101_get_termios_port(struct usb_serial_port *port,
+	unsigned int *cflagp, unsigned int *baudp)
+{
 	unsigned int cflag, modem_ctl[4];
 	unsigned int baud;
 	unsigned int bits;
@@ -387,12 +454,12 @@
 	cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2);
 	/* Convert to baudrate */
 	if (baud)
-		baud = BAUD_RATE_GEN_FREQ / baud;
+		baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
 
 	dbg("%s - baud rate = %d", __func__, baud);
+	*baudp = baud;
 
-	tty_encode_baud_rate(tty, baud, baud);
-	cflag = tty->termios->c_cflag;
+	cflag = *cflagp;
 
 	cp2101_get_config(port, CP2101_BITS, &bits, 2);
 	cflag &= ~CSIZE;
@@ -498,7 +565,7 @@
 		cflag &= ~CRTSCTS;
 	}
 
-	tty->termios->c_cflag = cflag;
+	*cflagp = cflag;
 }
 
 static void cp2101_set_termios(struct tty_struct *tty,
@@ -516,46 +583,16 @@
 	tty->termios->c_cflag &= ~CMSPAR;
 	cflag = tty->termios->c_cflag;
 	old_cflag = old_termios->c_cflag;
-	baud = tty_get_baud_rate(tty);
+	baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty));
 
 	/* If the baud rate is to be updated*/
-	if (baud != tty_termios_baud_rate(old_termios)) {
-		switch (baud) {
-		case 0:
-		case 600:
-		case 1200:
-		case 1800:
-		case 2400:
-		case 4800:
-		case 7200:
-		case 9600:
-		case 14400:
-		case 19200:
-		case 28800:
-		case 38400:
-		case 55854:
-		case 57600:
-		case 115200:
-		case 127117:
-		case 230400:
-		case 460800:
-		case 921600:
-		case 3686400:
-			break;
-		default:
-			baud = 9600;
-			break;
-		}
-
-		if (baud) {
-			dbg("%s - Setting baud rate to %d baud", __func__,
-					baud);
-			if (cp2101_set_config_single(port, CP2101_BAUDRATE,
-						(BAUD_RATE_GEN_FREQ / baud))) {
-				dev_err(&port->dev, "Baud rate requested not "
-						"supported by device\n");
-				baud = tty_termios_baud_rate(old_termios);
-			}
+	if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
+		dbg("%s - Setting baud rate to %d baud", __func__,
+				baud);
+		if (cp2101_set_config_single(port, CP2101_BAUDRATE,
+					((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
+			dbg("Baud rate requested not supported by device\n");
+			baud = tty_termios_baud_rate(old_termios);
 		}
 	}
 	/* Report back the resulting baud rate */
@@ -587,14 +624,14 @@
 			dbg("%s - data bits = 9", __func__);
 			break;*/
 		default:
-			dev_err(&port->dev, "cp2101 driver does not "
+			dbg("cp2101 driver does not "
 					"support the number of bits requested,"
 					" using 8 bit mode\n");
 				bits |= BITS_DATA_8;
 				break;
 		}
 		if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
-			dev_err(&port->dev, "Number of data bits requested "
+			dbg("Number of data bits requested "
 					"not supported by device\n");
 	}
 
@@ -611,7 +648,7 @@
 			}
 		}
 		if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
-			dev_err(&port->dev, "Parity mode not supported "
+			dbg("Parity mode not supported "
 					"by device\n");
 	}
 
@@ -626,7 +663,7 @@
 			dbg("%s - stop bits = 1", __func__);
 		}
 		if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
-			dev_err(&port->dev, "Number of stop bits requested "
+			dbg("Number of stop bits requested "
 					"not supported by device\n");
 	}
 
@@ -660,6 +697,12 @@
 		unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
+	return cp2101_tiocmset_port(port, file, set, clear);
+}
+
+static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *file,
+		unsigned int set, unsigned int clear)
+{
 	unsigned int control = 0;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -684,7 +727,6 @@
 	dbg("%s - control = 0x%.4x", __func__, control);
 
 	return cp2101_set_config(port, CP2101_CONTROL, &control, 2);
-
 }
 
 static int cp2101_tiocmget (struct tty_struct *tty, struct file *file)
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index f92f4d7..dcc87aa 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -663,6 +663,11 @@
 	{ USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) },
 	{ USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) },
+	{ USB_DEVICE(ATMEL_VID, STK541_PID) },
+	{ USB_DEVICE(DE_VID, STB_PID) },
+	{ USB_DEVICE(DE_VID, WHT_PID) },
+	{ USB_DEVICE(ADI_VID, ADI_GNICE_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -1933,18 +1938,16 @@
 		/* Compare new line status to the old one, signal if different/
 		   N.B. packet may be processed more than once, but differences
 		   are only processed once.  */
-		if (priv != NULL) {
-			char new_status = data[packet_offset + 0] &
-							FTDI_STATUS_B0_MASK;
-			if (new_status != priv->prev_status) {
-				priv->diff_status |=
-					new_status ^ priv->prev_status;
-				wake_up_interruptible(&priv->delta_msr_wait);
-				priv->prev_status = new_status;
-			}
+		char new_status = data[packet_offset + 0] &
+						FTDI_STATUS_B0_MASK;
+		if (new_status != priv->prev_status) {
+			priv->diff_status |=
+				new_status ^ priv->prev_status;
+			wake_up_interruptible(&priv->delta_msr_wait);
+			priv->prev_status = new_status;
 		}
 
-		length = min(PKTSZ, urb->actual_length-packet_offset)-2;
+		length = min_t(u32, PKTSZ, urb->actual_length-packet_offset)-2;
 		if (length < 0) {
 			dev_err(&port->dev, "%s - bad packet length: %d\n",
 				__func__, length+2);
@@ -2289,11 +2292,8 @@
 			   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
 			   0, 0,
 			   buf, 1, WDR_TIMEOUT);
-		if (ret < 0) {
-			dbg("%s Could not get modem status of device - err: %d", __func__,
-			    ret);
+		if (ret < 0)
 			return ret;
-		}
 		break;
 	case FT8U232AM:
 	case FT232BM:
@@ -2308,15 +2308,11 @@
 				   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
 				   0, priv->interface,
 				   buf, 2, WDR_TIMEOUT);
-		if (ret < 0) {
-			dbg("%s Could not get modem status of device - err: %d", __func__,
-			    ret);
+		if (ret < 0)
 			return ret;
-		}
 		break;
 	default:
 		return -EFAULT;
-		break;
 	}
 
 	return  (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index e300c84..daaf63d 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -893,6 +893,26 @@
 #define DIEBOLD_BCS_SE923_PID	0xfb99
 
 /*
+ * Atmel STK541
+ */
+#define ATMEL_VID		0x03eb /* Vendor ID */
+#define STK541_PID		0x2109 /* Zigbee Controller */
+
+/*
+ * Dresden Elektronic Sensor Terminal Board
+ */
+#define DE_VID			0x1cf1 /* Vendor ID */
+#define STB_PID			0x0001 /* Sensor Terminal Board */
+#define WHT_PID			0x0004 /* Wireless Handheld Terminal */
+
+/*
+ * Blackfin gnICE JTAG
+ * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice
+ */
+#define ADI_VID 		0x0456
+#define ADI_GNICE_PID 		0xF000
+
+/*
  *   BmRequestType:  1100 0000b
  *   bRequest:       FTDI_E2_READ
  *   wValue:         0
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 814909f..9d57cac 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -177,14 +177,6 @@
 	struct usb_serial_port *port;
 	int i, c = 0, r;
 
-#ifdef CONFIG_PM
-	/*
-	 * If this is an autoresume, don't submit URBs.
-	 * They will be submitted in the open function instead.
-	 */
-	if (serial->dev->auto_pm)
-		return 0;
-#endif
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
 		if (port->port.count && port->read_urb) {
@@ -196,6 +188,7 @@
 
 	return c ? -EIO : 0;
 }
+EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
 
 void usb_serial_generic_close(struct tty_struct *tty,
 			struct usb_serial_port *port, struct file *filp)
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 132be74..ef92095 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -78,6 +78,7 @@
 			struct usb_serial_port *port, struct file *filp);
 static void ipaq_close(struct tty_struct *tty,
 			struct usb_serial_port *port, struct file *filp);
+static int  ipaq_calc_num_ports(struct usb_serial *serial);
 static int  ipaq_startup(struct usb_serial *serial);
 static void ipaq_shutdown(struct usb_serial *serial);
 static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -572,15 +573,10 @@
 	.description =		"PocketPC PDA",
 	.usb_driver = 		&ipaq_driver,
 	.id_table =		ipaq_id_table,
-	/*
-	 * some devices have an extra endpoint, which
-	 * must be ignored as it would make the core
-	 * create a second port which oopses when used
-	 */
-	.num_ports =		1,
 	.open =			ipaq_open,
 	.close =		ipaq_close,
 	.attach =		ipaq_startup,
+	.calc_num_ports =	ipaq_calc_num_ports,
 	.shutdown =		ipaq_shutdown,
 	.write =		ipaq_write,
 	.write_room =		ipaq_write_room,
@@ -956,14 +952,49 @@
 }
 
 
+static int ipaq_calc_num_ports(struct usb_serial *serial)
+{
+	/*
+	 * some devices have 3 endpoints, the 3rd of which
+	 * must be ignored as it would make the core
+	 * create a second port which oopses when used
+	 */
+	int ipaq_num_ports = 1;
+
+	dbg("%s - numberofendpoints: %d", __FUNCTION__,
+		(int)serial->interface->cur_altsetting->desc.bNumEndpoints);
+
+	/*
+	 * a few devices have 4 endpoints, seemingly Yakuma devices,
+	 * and we need the second pair, so let them have 2 ports
+	 *
+	 * TODO: can we drop port 1 ?
+	 */
+	if (serial->interface->cur_altsetting->desc.bNumEndpoints > 3) {
+		ipaq_num_ports = 2;
+	}
+
+	return ipaq_num_ports;
+}
+
+
 static int ipaq_startup(struct usb_serial *serial)
 {
 	dbg("%s", __func__);
 	if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
+		/*
+		 * FIXME: HP iPaq rx3715, possibly others, have 1 config that
+		 * is labeled as 2
+		 */
+
 		dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
 			serial->dev->actconfig->desc.bConfigurationValue);
 		return -ENODEV;
 	}
+
+	dbg("%s - iPAQ module configured for %d ports",
+		__FUNCTION__, serial->num_ports);
+
 	return usb_reset_configuration(serial->dev);
 }
 
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 9878c0f..00daa8f 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1507,7 +1507,7 @@
 	} else {
 		dev_warn(&serial->interface->dev,
 			 "unsupported endpoint type %x\n",
-			 ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+			 usb_endpoint_type(ep_desc));
 		usb_free_urb(urb);
 		return NULL;
 	}
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index cea326f..839583d 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -1,8 +1,8 @@
 /*
  * Opticon USB barcode to serial driver
  *
- * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de>
- * Copyright (C) 2008 Novell Inc.
+ * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de>
+ * Copyright (C) 2008 - 2009 Novell Inc.
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License version
@@ -14,6 +14,7 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
+#include <linux/serial.h>
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
@@ -40,8 +41,12 @@
 	bool throttled;
 	bool actually_throttled;
 	bool rts;
+	int outstanding_urbs;
 };
 
+/* max number of write urbs in flight */
+#define URB_UPPER_LIMIT	4
+
 static void opticon_bulk_callback(struct urb *urb)
 {
 	struct opticon_private *priv = urb->context;
@@ -106,7 +111,6 @@
 					priv->rts = false;
 				else
 					priv->rts = true;
-				/* FIXME change the RTS level */
 			} else {
 			dev_dbg(&priv->udev->dev,
 				"Unknown data packet received from the device:"
@@ -188,6 +192,120 @@
 	usb_kill_urb(priv->bulk_read_urb);
 }
 
+static void opticon_write_bulk_callback(struct urb *urb)
+{
+	struct opticon_private *priv = urb->context;
+	int status = urb->status;
+	unsigned long flags;
+
+	/* 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",
+		    __func__, status);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	--priv->outstanding_urbs;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	usb_serial_port_softint(priv->port);
+}
+
+static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
+			 const unsigned char *buf, int count)
+{
+	struct opticon_private *priv = usb_get_serial_data(port->serial);
+	struct usb_serial *serial = port->serial;
+	struct urb *urb;
+	unsigned char *buffer;
+	unsigned long flags;
+	int status;
+
+	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", __func__);
+		return 0;
+	}
+	priv->outstanding_urbs++;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	buffer = kmalloc(count, GFP_ATOMIC);
+	if (!buffer) {
+		dev_err(&port->dev, "out of memory\n");
+		count = -ENOMEM;
+		goto error_no_buffer;
+	}
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		dev_err(&port->dev, "no more free urbs\n");
+		count = -ENOMEM;
+		goto error_no_urb;
+	}
+
+	memcpy(buffer, buf, count);
+
+	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+
+	usb_fill_bulk_urb(urb, serial->dev,
+			  usb_sndbulkpipe(serial->dev,
+					  port->bulk_out_endpointAddress),
+			  buffer, count, opticon_write_bulk_callback, priv);
+
+	/* 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",
+							__func__, status);
+		count = status;
+		goto error;
+	}
+
+	/* we are done with this urb, so let the host driver
+	 * really free it when it is finished with it */
+	usb_free_urb(urb);
+
+	return count;
+error:
+	usb_free_urb(urb);
+error_no_urb:
+	kfree(buffer);
+error_no_buffer:
+	spin_lock_irqsave(&priv->lock, flags);
+	--priv->outstanding_urbs;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return count;
+}
+
+static int opticon_write_room(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct opticon_private *priv = usb_get_serial_data(port->serial);
+	unsigned long flags;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	/*
+	 * We really can take almost anything the user throws at us
+	 * but let's pick a nice big number to tell the tty
+	 * layer that we have lots of free space, unless we don't.
+	 */
+	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", __func__);
+		return 0;
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 2048;
+}
+
 static void opticon_throttle(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -223,6 +341,67 @@
 							__func__, result);
 }
 
+static int opticon_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct opticon_private *priv = usb_get_serial_data(port->serial);
+	unsigned long flags;
+	int result = 0;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->rts)
+		result = TIOCM_RTS;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	dbg("%s - %x", __func__, result);
+	return result;
+}
+
+static int get_serial_info(struct opticon_private *priv,
+			   struct serial_struct __user *serial)
+{
+	struct serial_struct tmp;
+
+	if (!serial)
+		return -EFAULT;
+
+	memset(&tmp, 0x00, sizeof(tmp));
+
+	/* fake emulate a 16550 uart to make userspace code happy */
+	tmp.type		= PORT_16550A;
+	tmp.line		= priv->serial->minor;
+	tmp.port		= 0;
+	tmp.irq			= 0;
+	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+	tmp.xmit_fifo_size	= 1024;
+	tmp.baud_base		= 9600;
+	tmp.close_delay		= 5*HZ;
+	tmp.closing_wait	= 30*HZ;
+
+	if (copy_to_user(serial, &tmp, sizeof(*serial)))
+		return -EFAULT;
+	return 0;
+}
+
+static int opticon_ioctl(struct tty_struct *tty, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct opticon_private *priv = usb_get_serial_data(port->serial);
+
+	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		return get_serial_info(priv,
+				       (struct serial_struct __user *)arg);
+	}
+
+	return -ENOIOCTLCMD;
+}
+
 static int opticon_startup(struct usb_serial *serial)
 {
 	struct opticon_private *priv;
@@ -306,11 +485,37 @@
 	usb_set_serial_data(serial, NULL);
 }
 
+static int opticon_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usb_serial *serial = usb_get_intfdata(intf);
+	struct opticon_private *priv = usb_get_serial_data(serial);
+
+	usb_kill_urb(priv->bulk_read_urb);
+	return 0;
+}
+
+static int opticon_resume(struct usb_interface *intf)
+{
+	struct usb_serial *serial = usb_get_intfdata(intf);
+	struct opticon_private *priv = usb_get_serial_data(serial);
+	struct usb_serial_port *port = serial->port[0];
+	int result;
+
+	mutex_lock(&port->mutex);
+	if (port->port.count)
+		result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO);
+	else
+		result = 0;
+	mutex_unlock(&port->mutex);
+	return result;
+}
 
 static struct usb_driver opticon_driver = {
 	.name =		"opticon",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
+	.suspend =	opticon_suspend,
+	.resume =	opticon_resume,
 	.id_table =	id_table,
 	.no_dynamic_id = 	1,
 };
@@ -326,9 +531,13 @@
 	.attach =		opticon_startup,
 	.open =			opticon_open,
 	.close =		opticon_close,
+	.write =		opticon_write,
+	.write_room = 		opticon_write_room,
 	.shutdown =		opticon_shutdown,
 	.throttle = 		opticon_throttle,
 	.unthrottle =		opticon_unthrottle,
+	.ioctl =		opticon_ioctl,
+	.tiocmget =		opticon_tiocmget,
 };
 
 static int __init opticon_init(void)
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index b7c132b..d560c0b 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -62,6 +62,8 @@
 static int  option_tiocmset(struct tty_struct *tty, struct file *file,
 				unsigned int set, unsigned int clear);
 static int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *port);
+static int  option_suspend(struct usb_serial *serial, pm_message_t message);
+static int  option_resume(struct usb_serial *serial);
 
 /* Vendor and product IDs */
 #define OPTION_VENDOR_ID			0x0AF0
@@ -89,6 +91,7 @@
 #define OPTION_PRODUCT_ETNA_MODEM_GT		0x7041
 #define OPTION_PRODUCT_ETNA_MODEM_EX		0x7061
 #define OPTION_PRODUCT_ETNA_KOI_MODEM		0x7100
+#define OPTION_PRODUCT_GTM380_MODEM		0x7201
 
 #define HUAWEI_VENDOR_ID			0x12D1
 #define HUAWEI_PRODUCT_E600			0x1001
@@ -197,6 +200,7 @@
 /* OVATION PRODUCTS */
 #define NOVATELWIRELESS_PRODUCT_MC727		0x4100
 #define NOVATELWIRELESS_PRODUCT_MC950D		0x4400
+#define NOVATELWIRELESS_PRODUCT_U727		0x5010
 
 /* FUTURE NOVATEL PRODUCTS */
 #define NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED	0X6000
@@ -288,15 +292,11 @@
 
 /* ZTE PRODUCTS */
 #define ZTE_VENDOR_ID				0x19d2
+#define ZTE_PRODUCT_MF622			0x0001
 #define ZTE_PRODUCT_MF628			0x0015
 #define ZTE_PRODUCT_MF626			0x0031
 #define ZTE_PRODUCT_CDMA_TECH			0xfffe
 
-/* Ericsson products */
-#define ERICSSON_VENDOR_ID			0x0bdb
-#define ERICSSON_PRODUCT_F3507G_1		0x1900
-#define ERICSSON_PRODUCT_F3507G_2		0x1902
-
 #define BENQ_VENDOR_ID				0x04a5
 #define BENQ_PRODUCT_H10			0x4068
 
@@ -325,6 +325,7 @@
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTM380_MODEM) },
 	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q101) },
 	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q111) },
 	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
@@ -415,6 +416,7 @@
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED) }, /* Novatel EVDO product */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */
@@ -442,7 +444,6 @@
 	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_CINGULAR) },	/* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */
 	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_L) },	/* Dell Wireless HSDPA 5520 */
 	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_I) },	/* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */
-	{ USB_DEVICE(DELL_VENDOR_ID, 0x8147) },					/* Dell Wireless 5530 Mobile Broadband (3G HSPA) Mini-Card */
 	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) },	/* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
 	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) },	/* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
 	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, 	/* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
@@ -510,11 +511,10 @@
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
 	{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
+	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
-	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) },
-	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) },
 	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
 	{ USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
 	{ } /* Terminating entry */
@@ -525,6 +525,8 @@
 	.name       = "option",
 	.probe      = usb_serial_probe,
 	.disconnect = usb_serial_disconnect,
+	.suspend    = usb_serial_suspend,
+	.resume     = usb_serial_resume,
 	.id_table   = option_ids,
 	.no_dynamic_id = 	1,
 };
@@ -553,6 +555,8 @@
 	.attach            = option_startup,
 	.shutdown          = option_shutdown,
 	.read_int_callback = option_instat_callback,
+	.suspend           = option_suspend,
+	.resume            = option_resume,
 };
 
 static int debug;
@@ -823,10 +827,10 @@
 				req_pkt->bRequestType, req_pkt->bRequest);
 		}
 	} else
-		dbg("%s: error %d", __func__, status);
+		err("%s: error %d", __func__, status);
 
 	/* Resubmit urb so we continue receiving IRQ data */
-	if (status != -ESHUTDOWN) {
+	if (status != -ESHUTDOWN && status != -ENOENT) {
 		urb->dev = serial->dev;
 		err = usb_submit_urb(urb, GFP_ATOMIC);
 		if (err)
@@ -845,7 +849,6 @@
 
 	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))
@@ -1107,14 +1110,12 @@
 	return 1;
 }
 
-static void option_shutdown(struct usb_serial *serial)
+static void stop_read_write_urbs(struct usb_serial *serial)
 {
 	int i, j;
 	struct usb_serial_port *port;
 	struct option_port_private *portdata;
 
-	dbg("%s", __func__);
-
 	/* Stop reading/writing urbs */
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
@@ -1124,6 +1125,17 @@
 		for (j = 0; j < N_OUT_URB; j++)
 			usb_kill_urb(portdata->out_urbs[j]);
 	}
+}
+
+static void option_shutdown(struct usb_serial *serial)
+{
+	int i, j;
+	struct usb_serial_port *port;
+	struct option_port_private *portdata;
+
+	dbg("%s", __func__);
+
+	stop_read_write_urbs(serial);
 
 	/* Now free them */
 	for (i = 0; i < serial->num_ports; ++i) {
@@ -1154,6 +1166,66 @@
 	}
 }
 
+static int option_suspend(struct usb_serial *serial, pm_message_t message)
+{
+	dbg("%s entered", __func__);
+	stop_read_write_urbs(serial);
+
+	return 0;
+}
+
+static int option_resume(struct usb_serial *serial)
+{
+	int err, i, j;
+	struct usb_serial_port *port;
+	struct urb *urb;
+	struct option_port_private *portdata;
+
+	dbg("%s entered", __func__);
+	/* get the interrupt URBs resubmitted unconditionally */
+	for (i = 0; i < serial->num_ports; i++) {
+		port = serial->port[i];
+		if (!port->interrupt_in_urb) {
+			dbg("%s: No interrupt URB for port %d\n", __func__, i);
+			continue;
+		}
+		port->interrupt_in_urb->dev = serial->dev;
+		err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
+		dbg("Submitted interrupt URB for port %d (result %d)", i, err);
+		if (err < 0) {
+			err("%s: Error %d for interrupt URB of port%d",
+				 __func__, err, i);
+			return err;
+		}
+	}
+
+	for (i = 0; i < serial->num_ports; i++) {
+		/* walk all ports */
+		port = serial->port[i];
+		portdata = usb_get_serial_port_data(port);
+		mutex_lock(&port->mutex);
+
+		/* skip closed ports */
+		if (!port->port.count) {
+			mutex_unlock(&port->mutex);
+			continue;
+		}
+
+		for (j = 0; j < N_IN_URB; j++) {
+			urb = portdata->in_urbs[j];
+			err = usb_submit_urb(urb, GFP_NOIO);
+			if (err < 0) {
+				mutex_unlock(&port->mutex);
+				err("%s: Error %d for bulk URB %d",
+					 __func__, err, i);
+				return err;
+			}
+		}
+		mutex_unlock(&port->mutex);
+	}
+	return 0;
+}
+
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
new file mode 100644
index 0000000..e6d6b0c
--- /dev/null
+++ b/drivers/usb/serial/qcserial.c
@@ -0,0 +1,147 @@
+/*
+ * Qualcomm Serial USB driver
+ *
+ *	Copyright (c) 2008 QUALCOMM Incorporated.
+ *	Copyright (c) 2009 Greg Kroah-Hartman <gregkh@suse.de>
+ *	Copyright (c) 2009 Novell Inc.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+#define DRIVER_AUTHOR "Qualcomm Inc"
+#define DRIVER_DESC "Qualcomm USB Serial driver"
+
+static int debug;
+
+static struct usb_device_id id_table[] = {
+	{USB_DEVICE(0x05c6, 0x9211)},	/* Acer Gobi QDL device */
+	{USB_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
+	{USB_DEVICE(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
+	{USB_DEVICE(0x03f0, 0x201d)},	/* HP un2400 Gobi QDL Device */
+	{ }				/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver qcdriver = {
+	.name			= "qcserial",
+	.probe			= usb_serial_probe,
+	.disconnect		= usb_serial_disconnect,
+	.id_table		= id_table,
+	.suspend		= usb_serial_suspend,
+	.resume			= usb_serial_resume,
+	.supports_autosuspend	= true,
+};
+
+static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
+{
+	int retval = -ENODEV;
+	__u8 nintf;
+	__u8 ifnum;
+
+	dbg("%s", __func__);
+
+	nintf = serial->dev->actconfig->desc.bNumInterfaces;
+	dbg("Num Interfaces = %d", nintf);
+	ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+	dbg("This Interface = %d", ifnum);
+
+	switch (nintf) {
+	case 1:
+		/* QDL mode */
+		if (serial->interface->num_altsetting == 2) {
+			struct usb_host_interface *intf;
+
+			intf = &serial->interface->altsetting[1];
+			if (intf->desc.bNumEndpoints == 2) {
+				if (usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
+				    usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
+					dbg("QDL port found");
+					retval = usb_set_interface(serial->dev, ifnum, 1);
+					if (retval < 0) {
+						dev_err(&serial->dev->dev,
+							"Could not set interface, error %d\n",
+							retval);
+						retval = -ENODEV;
+					}
+					return retval;
+				}
+			}
+		}
+		break;
+
+	case 4:
+		/* Composite mode */
+		if (ifnum == 2) {
+			dbg("Modem port found");
+			retval = usb_set_interface(serial->dev, ifnum, 0);
+			if (retval < 0) {
+				dev_err(&serial->dev->dev,
+					"Could not set interface, error %d\n",
+					retval);
+				retval = -ENODEV;
+			}
+			return retval;
+		}
+		break;
+
+	default:
+		dev_err(&serial->dev->dev,
+			"unknown number of interfaces: %d\n", nintf);
+		return -ENODEV;
+	}
+
+	return retval;
+}
+
+static struct usb_serial_driver qcdevice = {
+	.driver = {
+		.owner     = THIS_MODULE,
+		.name      = "qcserial",
+	},
+	.description         = "Qualcomm USB modem",
+	.id_table            = id_table,
+	.usb_driver          = &qcdriver,
+	.num_ports           = 1,
+	.probe               = qcprobe,
+};
+
+static int __init qcinit(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&qcdevice);
+	if (retval)
+		return retval;
+
+	retval = usb_register(&qcdriver);
+	if (retval) {
+		usb_serial_deregister(&qcdevice);
+		return retval;
+	}
+
+	return 0;
+}
+
+static void __exit qcexit(void)
+{
+	usb_deregister(&qcdriver);
+	usb_serial_deregister(&qcdevice);
+}
+
+module_init(qcinit);
+module_exit(qcexit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
new file mode 100644
index 0000000..8b3cbc8
--- /dev/null
+++ b/drivers/usb/serial/symbolserial.c
@@ -0,0 +1,399 @@
+/*
+ * Symbol USB barcode to serial driver
+ *
+ * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de>
+ * Copyright (C) 2009 Novell Inc.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/uaccess.h>
+
+static int debug;
+
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE(0x05e0, 0x0600) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* This structure holds all of the individual device information */
+struct symbol_private {
+	struct usb_device *udev;
+	struct usb_serial *serial;
+	struct usb_serial_port *port;
+	unsigned char *int_buffer;
+	struct urb *int_urb;
+	int buffer_size;
+	u8 bInterval;
+	u8 int_address;
+	spinlock_t lock;	/* protects the following flags */
+	bool throttled;
+	bool actually_throttled;
+	bool rts;
+};
+
+static void symbol_int_callback(struct urb *urb)
+{
+	struct symbol_private *priv = urb->context;
+	unsigned char *data = urb->transfer_buffer;
+	struct usb_serial_port *port = priv->port;
+	int status = urb->status;
+	struct tty_struct *tty;
+	int result;
+	int available_room = 0;
+	int data_length;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	switch (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",
+		    __func__, status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d",
+		    __func__, status);
+		goto exit;
+	}
+
+	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length,
+			      data);
+
+	if (urb->actual_length > 1) {
+		data_length = urb->actual_length - 1;
+
+		/*
+		 * Data from the device comes with a 1 byte header:
+		 *
+		 * <size of data>data...
+		 * 	This is real data to be sent to the tty layer
+		 * we pretty much just ignore the size and send everything
+		 * else to the tty layer.
+		 */
+		tty = tty_port_tty_get(&port->port);
+		if (tty) {
+			available_room = tty_buffer_request_room(tty,
+							data_length);
+			if (available_room) {
+				tty_insert_flip_string(tty, &data[1],
+						       available_room);
+				tty_flip_buffer_push(tty);
+			}
+			tty_kref_put(tty);
+		}
+	} else {
+		dev_dbg(&priv->udev->dev,
+			"Improper ammount of data received from the device, "
+			"%d bytes", urb->actual_length);
+	}
+
+exit:
+	spin_lock(&priv->lock);
+
+	/* Continue trying to always read if we should */
+	if (!priv->throttled) {
+		usb_fill_int_urb(priv->int_urb, priv->udev,
+				 usb_rcvintpipe(priv->udev,
+				 		priv->int_address),
+				 priv->int_buffer, priv->buffer_size,
+				 symbol_int_callback, priv, priv->bInterval);
+		result = usb_submit_urb(priv->int_urb, GFP_ATOMIC);
+		if (result)
+			dev_err(&port->dev,
+			    "%s - failed resubmitting read urb, error %d\n",
+							__func__, result);
+	} else
+		priv->actually_throttled = true;
+	spin_unlock(&priv->lock);
+}
+
+static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port,
+			struct file *filp)
+{
+	struct symbol_private *priv = usb_get_serial_data(port->serial);
+	unsigned long flags;
+	int result = 0;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->throttled = false;
+	priv->actually_throttled = false;
+	priv->port = port;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/*
+	 * 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 can get lost.
+	 */
+	if (tty)
+		tty->low_latency = 1;
+
+	/* Start reading from the device */
+	usb_fill_int_urb(priv->int_urb, priv->udev,
+			 usb_rcvintpipe(priv->udev, priv->int_address),
+			 priv->int_buffer, priv->buffer_size,
+			 symbol_int_callback, priv, priv->bInterval);
+	result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
+	if (result)
+		dev_err(&port->dev,
+			"%s - failed resubmitting read urb, error %d\n",
+			__func__, result);
+	return result;
+}
+
+static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port,
+			  struct file *filp)
+{
+	struct symbol_private *priv = usb_get_serial_data(port->serial);
+
+	dbg("%s - port %d", __func__, port->number);
+
+	/* shutdown our urbs */
+	usb_kill_urb(priv->int_urb);
+}
+
+static void symbol_throttle(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct symbol_private *priv = usb_get_serial_data(port->serial);
+	unsigned long flags;
+
+	dbg("%s - port %d", __func__, port->number);
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->throttled = true;
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void symbol_unthrottle(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct symbol_private *priv = usb_get_serial_data(port->serial);
+	unsigned long flags;
+	int result;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->throttled = false;
+	priv->actually_throttled = false;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	priv->int_urb->dev = port->serial->dev;
+	result = usb_submit_urb(priv->int_urb, GFP_ATOMIC);
+	if (result)
+		dev_err(&port->dev,
+			"%s - failed submitting read urb, error %d\n",
+							__func__, result);
+}
+
+static int symbol_ioctl(struct tty_struct *tty, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct device *dev = &port->dev;
+
+	/*
+	 * Right now we need to figure out what commands
+	 * most userspace tools want to see for this driver,
+	 * so just log the things.
+	 */
+	switch (cmd) {
+	case TIOCSERGETLSR:
+		dev_info(dev, "%s: TIOCSERGETLSR\n", __func__);
+		break;
+
+	case TIOCGSERIAL:
+		dev_info(dev, "%s: TIOCGSERIAL\n", __func__);
+		break;
+
+	case TIOCMIWAIT:
+		dev_info(dev, "%s: TIOCMIWAIT\n", __func__);
+		break;
+
+	case TIOCGICOUNT:
+		dev_info(dev, "%s: TIOCGICOUNT\n", __func__);
+		break;
+	default:
+		dev_info(dev, "%s: unknown (%d)\n", __func__, cmd);
+	}
+	return -ENOIOCTLCMD;
+}
+
+static int symbol_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct device *dev = &port->dev;
+
+	/* TODO */
+	/* probably just need to shadow whatever was sent to us here */
+	dev_info(dev, "%s\n", __func__);
+	return 0;
+}
+
+static int symbol_tiocmset(struct tty_struct *tty, struct file *file,
+			   unsigned int set, unsigned int clear)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct device *dev = &port->dev;
+
+	/* TODO */
+	/* probably just need to shadow whatever was sent to us here */
+	dev_info(dev, "%s\n", __func__);
+	return 0;
+}
+
+static int symbol_startup(struct usb_serial *serial)
+{
+	struct symbol_private *priv;
+	struct usb_host_interface *intf;
+	int i;
+	int retval = -ENOMEM;
+	bool int_in_found = false;
+
+	/* create our private serial structure */
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (priv == NULL) {
+		dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+		return -ENOMEM;
+	}
+	spin_lock_init(&priv->lock);
+	priv->serial = serial;
+	priv->port = serial->port[0];
+	priv->udev = serial->dev;
+
+	/* find our interrupt endpoint */
+	intf = serial->interface->altsetting;
+	for (i = 0; i < intf->desc.bNumEndpoints; ++i) {
+		struct usb_endpoint_descriptor *endpoint;
+
+		endpoint = &intf->endpoint[i].desc;
+		if (!usb_endpoint_is_int_in(endpoint))
+			continue;
+
+		priv->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!priv->int_urb) {
+			dev_err(&priv->udev->dev, "out of memory\n");
+			goto error;
+		}
+
+		priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2;
+		priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL);
+		if (!priv->int_buffer) {
+			dev_err(&priv->udev->dev, "out of memory\n");
+			goto error;
+		}
+
+		priv->int_address = endpoint->bEndpointAddress;
+		priv->bInterval = endpoint->bInterval;
+
+		/* set up our int urb */
+		usb_fill_int_urb(priv->int_urb, priv->udev,
+				 usb_rcvintpipe(priv->udev,
+				 		endpoint->bEndpointAddress),
+				 priv->int_buffer, priv->buffer_size,
+				 symbol_int_callback, priv, priv->bInterval);
+
+		int_in_found = true;
+		break;
+		}
+
+	if (!int_in_found) {
+		dev_err(&priv->udev->dev,
+			"Error - the proper endpoints were not found!\n");
+		goto error;
+	}
+
+	usb_set_serial_data(serial, priv);
+	return 0;
+
+error:
+	usb_free_urb(priv->int_urb);
+	kfree(priv->int_buffer);
+	kfree(priv);
+	return retval;
+}
+
+static void symbol_shutdown(struct usb_serial *serial)
+{
+	struct symbol_private *priv = usb_get_serial_data(serial);
+
+	dbg("%s", __func__);
+
+	usb_kill_urb(priv->int_urb);
+	usb_free_urb(priv->int_urb);
+	kfree(priv->int_buffer);
+	kfree(priv);
+	usb_set_serial_data(serial, NULL);
+}
+
+static struct usb_driver symbol_driver = {
+	.name =			"symbol",
+	.probe =		usb_serial_probe,
+	.disconnect =		usb_serial_disconnect,
+	.id_table =		id_table,
+	.no_dynamic_id = 	1,
+};
+
+static struct usb_serial_driver symbol_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"symbol",
+	},
+	.id_table =		id_table,
+	.usb_driver = 		&symbol_driver,
+	.num_ports =		1,
+	.attach =		symbol_startup,
+	.open =			symbol_open,
+	.close =		symbol_close,
+	.shutdown =		symbol_shutdown,
+	.throttle = 		symbol_throttle,
+	.unthrottle =		symbol_unthrottle,
+	.ioctl = 		symbol_ioctl,
+	.tiocmget = 		symbol_tiocmget,
+	.tiocmset = 		symbol_tiocmset,
+};
+
+static int __init symbol_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&symbol_device);
+	if (retval)
+		return retval;
+	retval = usb_register(&symbol_driver);
+	if (retval)
+		usb_serial_deregister(&symbol_device);
+	return retval;
+}
+
+static void __exit symbol_exit(void)
+{
+	usb_deregister(&symbol_driver);
+	usb_serial_deregister(&symbol_device);
+}
+
+module_init(symbol_init);
+module_exit(symbol_exit);
+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/usb-serial.c b/drivers/usb/serial/usb-serial.c
index cfcfd5a..742a5bc 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -204,6 +204,11 @@
 		goto bailout_kref_put;
 	}
 
+	if (port->serial->disconnected) {
+		retval = -ENODEV;
+		goto bailout_kref_put;
+	}
+
 	if (mutex_lock_interruptible(&port->mutex)) {
 		retval = -ERESTARTSYS;
 		goto bailout_kref_put;
@@ -1067,6 +1072,8 @@
 	struct usb_serial_port *port;
 	int i, r = 0;
 
+	serial->suspending = 1;
+
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
 		if (port)
@@ -1083,10 +1090,15 @@
 int usb_serial_resume(struct usb_interface *intf)
 {
 	struct usb_serial *serial = usb_get_intfdata(intf);
+	int rv;
 
+	serial->suspending = 0;
 	if (serial->type->resume)
-		return serial->type->resume(serial);
-	return 0;
+		rv = serial->type->resume(serial);
+	else
+		rv = usb_serial_generic_resume(serial);
+
+	return rv;
 }
 EXPORT_SYMBOL(usb_serial_resume);
 
@@ -1222,7 +1234,6 @@
 	set_to_generic_if_null(device, read_bulk_callback);
 	set_to_generic_if_null(device, write_bulk_callback);
 	set_to_generic_if_null(device, shutdown);
-	set_to_generic_if_null(device, resume);
 }
 
 int usb_serial_register(struct usb_serial_driver *driver)
@@ -1230,6 +1241,9 @@
 	/* must be called with BKL held */
 	int retval;
 
+	if (usb_disabled())
+		return -ENODEV;
+
 	fixup_generic(driver);
 
 	if (!driver->description)
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 9df6887..8a372ba 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -2,8 +2,8 @@
 # USB Storage driver configuration
 #
 
-comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;"
-comment "see USB_STORAGE Help for more information"
+comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may"
+comment "also be needed; see USB_STORAGE Help for more info"
 	depends on USB
 
 config USB_STORAGE
@@ -32,21 +32,25 @@
 	  verbose debugging messages.
 
 config USB_STORAGE_DATAFAB
-	bool "Datafab Compact Flash Reader support"
+	tristate "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/>.
 
+	  If this driver is compiled as a module, it will be named ums-datafab.
+
 config USB_STORAGE_FREECOM
-	bool "Freecom USB/ATAPI Bridge support"
+	tristate "Freecom USB/ATAPI Bridge support"
 	depends on USB_STORAGE
 	help
 	  Support for the Freecom USB to IDE/ATAPI adaptor.
 	  Freecom has a web page at <http://www.freecom.de/>.
 
+	  If this driver is compiled as a module, it will be named ums-freecom.
+
 config USB_STORAGE_ISD200
-	bool "ISD-200 USB/ATA Bridge support"
+	tristate "ISD-200 USB/ATA Bridge support"
 	depends on USB_STORAGE
 	---help---
 	  Say Y here if you want to use USB Mass Store devices based
@@ -61,8 +65,10 @@
 	  - CyQ've CQ8060A CDRW drive
 	  - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U)
 
+	  If this driver is compiled as a module, it will be named ums-isd200.
+
 config USB_STORAGE_USBAT
-	bool "USBAT/USBAT02-based storage support"
+	tristate "USBAT/USBAT02-based storage support"
 	depends on USB_STORAGE
 	help
 	  Say Y here to include additional code to support storage devices
@@ -82,30 +88,38 @@
 	  - RCA LYRA MP3 portable
 	  - Sandisk ImageMate SDDR-05b
 
+	  If this driver is compiled as a module, it will be named ums-usbat.
+
 config USB_STORAGE_SDDR09
-	bool "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support"
+	tristate "SanDisk SDDR-09 (and other SmartMedia, including DPCM) 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! CompactFlash/SmartMedia reader.
 
+	  If this driver is compiled as a module, it will be named ums-sddr09.
+
 config USB_STORAGE_SDDR55
-	bool "SanDisk SDDR-55 SmartMedia support"
+	tristate "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.
 
+	  If this driver is compiled as a module, it will be named ums-sddr55.
+
 config USB_STORAGE_JUMPSHOT
-	bool "Lexar Jumpshot Compact Flash Reader"
+	tristate "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.
 
+	  If this driver is compiled as a module, it will be named ums-jumpshot.
+
 config USB_STORAGE_ALAUDA
-	bool "Olympus MAUSB-10/Fuji DPC-R1 support"
+	tristate "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
@@ -114,8 +128,10 @@
 	  These devices are based on the Alauda chip and support both
 	  XD and SmartMedia cards.
 
+	  If this driver is compiled as a module, it will be named ums-alauda.
+
 config USB_STORAGE_ONETOUCH
-	bool "Support OneTouch Button on Maxtor Hard Drives"
+	tristate "Support OneTouch Button on Maxtor Hard Drives"
 	depends on USB_STORAGE
 	depends on INPUT=y || INPUT=USB_STORAGE
 	help
@@ -127,8 +143,10 @@
 	  this input in any keybinding software. (e.g. gnome's keyboard short-
 	  cuts)
 
+	  If this driver is compiled as a module, it will be named ums-onetouch.
+
 config USB_STORAGE_KARMA
-	bool "Support for Rio Karma music player"
+	tristate "Support for Rio Karma music player"
 	depends on USB_STORAGE
 	help
 	  Say Y here to include additional code to support the Rio Karma
@@ -139,8 +157,10 @@
 	  on the resulting scsi device node returns the Karma to normal
 	  operation.
 
+	  If this driver is compiled as a module, it will be named ums-karma.
+
 config USB_STORAGE_CYPRESS_ATACB
-	bool "SAT emulation on Cypress USB/ATA Bridge with ATACB"
+	tristate "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
@@ -150,6 +170,8 @@
 	  If you say no here your device will still work with the standard usb
 	  mass storage class.
 
+	  If this driver is compiled as a module, it will be named ums-cypress.
+
 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 b320693..5be54c0 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -10,21 +10,36 @@
 obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
 
 usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT)	+= shuttle_usbat.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09)	+= sddr09.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55)	+= sddr55.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200)	+= isd200.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
-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 sierra_ms.o option_ms.o $(usb-storage-obj-y)
 
-ifneq ($(CONFIG_USB_LIBUSUAL),)
-	obj-$(CONFIG_USB)	+= libusual.o
+ifeq ($(CONFIG_USB_LIBUSUAL),)
+	usb-storage-objs	+= usual-tables.o
+else
+	obj-$(CONFIG_USB)	+= libusual.o usual-tables.o
 endif
+
+obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= ums-alauda.o
+obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o
+obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= ums-datafab.o
+obj-$(CONFIG_USB_STORAGE_FREECOM)	+= ums-freecom.o
+obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
+obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= ums-jumpshot.o
+obj-$(CONFIG_USB_STORAGE_KARMA)		+= ums-karma.o
+obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= ums-onetouch.o
+obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
+obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
+
+ums-alauda-objs		:= alauda.o
+ums-cypress-objs	:= cypress_atacb.o
+ums-datafab-objs	:= datafab.o
+ums-freecom-objs	:= freecom.o
+ums-isd200-objs		:= isd200.o
+ums-jumpshot-objs	:= jumpshot.o
+ums-karma-objs		:= karma.o
+ums-onetouch-objs	:= onetouch.o
+ums-sddr09-objs		:= sddr09.o
+ums-sddr55-objs		:= sddr55.o
+ums-usbat-objs		:= shuttle_usbat.o
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
index 8d3711a..67edc65 100644
--- a/drivers/usb/storage/alauda.c
+++ b/drivers/usb/storage/alauda.c
@@ -31,6 +31,8 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/module.h>
+
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -39,7 +41,79 @@
 #include "transport.h"
 #include "protocol.h"
 #include "debug.h"
-#include "alauda.h"
+
+MODULE_DESCRIPTION("Driver for Alauda-based card readers");
+MODULE_AUTHOR("Daniel Drake <dsd@gentoo.org>");
+MODULE_LICENSE("GPL");
+
+/*
+ * Status bytes
+ */
+#define ALAUDA_STATUS_ERROR		0x01
+#define ALAUDA_STATUS_READY		0x40
+
+/*
+ * Control opcodes (for request field)
+ */
+#define ALAUDA_GET_XD_MEDIA_STATUS	0x08
+#define ALAUDA_GET_SM_MEDIA_STATUS	0x98
+#define ALAUDA_ACK_XD_MEDIA_CHANGE	0x0a
+#define ALAUDA_ACK_SM_MEDIA_CHANGE	0x9a
+#define ALAUDA_GET_XD_MEDIA_SIG		0x86
+#define ALAUDA_GET_SM_MEDIA_SIG		0x96
+
+/*
+ * Bulk command identity (byte 0)
+ */
+#define ALAUDA_BULK_CMD			0x40
+
+/*
+ * Bulk opcodes (byte 1)
+ */
+#define ALAUDA_BULK_GET_REDU_DATA	0x85
+#define ALAUDA_BULK_READ_BLOCK		0x94
+#define ALAUDA_BULK_ERASE_BLOCK		0xa3
+#define ALAUDA_BULK_WRITE_BLOCK		0xb4
+#define ALAUDA_BULK_GET_STATUS2		0xb7
+#define ALAUDA_BULK_RESET_MEDIA		0xe0
+
+/*
+ * Port to operate on (byte 8)
+ */
+#define ALAUDA_PORT_XD			0x00
+#define ALAUDA_PORT_SM			0x01
+
+/*
+ * LBA and PBA are unsigned ints. Special values.
+ */
+#define UNDEF    0xffff
+#define SPARE    0xfffe
+#define UNUSABLE 0xfffd
+
+struct alauda_media_info {
+	unsigned long capacity;		/* total media size in bytes */
+	unsigned int pagesize;		/* page size in bytes */
+	unsigned int blocksize;		/* number of pages per block */
+	unsigned int uzonesize;		/* number of usable blocks per zone */
+	unsigned int zonesize;		/* number of blocks per zone */
+	unsigned int blockmask;		/* mask to get page from address */
+
+	unsigned char pageshift;
+	unsigned char blockshift;
+	unsigned char zoneshift;
+
+	u16 **lba_to_pba;		/* logical to physical block map */
+	u16 **pba_to_lba;		/* physical to logical block map */
+};
+
+struct alauda_info {
+	struct alauda_media_info port[2];
+	int wr_ep;			/* endpoint to write data out of */
+
+	unsigned char sense_key;
+	unsigned long sense_asc;	/* additional sense code */
+	unsigned long sense_ascq;	/* additional sense code qualifier */
+};
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
@@ -52,6 +126,48 @@
 #define PBA_HI(pba) (pba >> 3)
 #define PBA_ZONE(pba) (pba >> 11)
 
+static int init_alauda(struct us_data *us);
+
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id alauda_usb_ids[] = {
+#	include "unusual_alauda.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, alauda_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev alauda_unusual_dev_list[] = {
+#	include "unusual_alauda.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+
 /*
  * Media handling
  */
@@ -307,7 +423,8 @@
 		data[0], data[1], data[2], data[3]);
 	media_info = alauda_card_find_id(data[1]);
 	if (media_info == NULL) {
-		printk("alauda_init_media: Unrecognised media signature: "
+		printk(KERN_WARNING
+			"alauda_init_media: Unrecognised media signature: "
 			"%02X %02X %02X %02X\n",
 			data[0], data[1], data[2], data[3]);
 		return USB_STOR_TRANSPORT_ERROR;
@@ -518,7 +635,8 @@
 
 		/* check even parity */
 		if (parity[data[6] ^ data[7]]) {
-			printk("alauda_read_map: Bad parity in LBA for block %d"
+			printk(KERN_WARNING
+			       "alauda_read_map: Bad parity in LBA for block %d"
 			       " (%02X %02X)\n", i, data[6], data[7]);
 			pba_to_lba[i] = UNUSABLE;
 			continue;
@@ -538,13 +656,16 @@
 		 */
 
 		if (lba_offset >= uzonesize) {
-			printk("alauda_read_map: Bad low LBA %d for block %d\n",
+			printk(KERN_WARNING
+			       "alauda_read_map: Bad low LBA %d for block %d\n",
 			       lba_real, blocknum);
 			continue;
 		}
 
 		if (lba_to_pba[lba_offset] != UNDEF) {
-			printk("alauda_read_map: LBA %d seen for PBA %d and %d\n",
+			printk(KERN_WARNING
+			       "alauda_read_map: "
+			       "LBA %d seen for PBA %d and %d\n",
 			       lba_real, lba_to_pba[lba_offset], blocknum);
 			continue;
 		}
@@ -712,13 +833,15 @@
 	if (pba == 1) {
 		/* Maybe it is impossible to write to PBA 1.
 		   Fake success, but don't do anything. */
-		printk("alauda_write_lba: avoid writing to pba 1\n");
+		printk(KERN_WARNING
+		       "alauda_write_lba: avoid writing to pba 1\n");
 		return USB_STOR_TRANSPORT_GOOD;
 	}
 
 	new_pba = alauda_find_unused_pba(&MEDIA_INFO(us), zone);
 	if (!new_pba) {
-		printk("alauda_write_lba: Out of unused blocks\n");
+		printk(KERN_WARNING
+		       "alauda_write_lba: Out of unused blocks\n");
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
@@ -818,7 +941,7 @@
 	len = min(sectors, blocksize) * (pagesize + 64);
 	buffer = kmalloc(len, GFP_NOIO);
 	if (buffer == NULL) {
-		printk("alauda_read_data: Out of memory\n");
+		printk(KERN_WARNING "alauda_read_data: Out of memory\n");
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
@@ -911,7 +1034,7 @@
 	len = min(sectors, blocksize) * pagesize;
 	buffer = kmalloc(len, GFP_NOIO);
 	if (buffer == NULL) {
-		printk("alauda_write_data: Out of memory\n");
+		printk(KERN_WARNING "alauda_write_data: Out of memory\n");
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
@@ -921,7 +1044,7 @@
 	 */
 	blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO);
 	if (blockbuffer == NULL) {
-		printk("alauda_write_data: Out of memory\n");
+		printk(KERN_WARNING "alauda_write_data: Out of memory\n");
 		kfree(buffer);
 		return USB_STOR_TRANSPORT_ERROR;
 	}
@@ -991,7 +1114,7 @@
 /*
  * Initialize alauda_info struct and find the data-write endpoint
  */
-int init_alauda(struct us_data *us)
+static int init_alauda(struct us_data *us)
 {
 	struct alauda_info *info;
 	struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting;
@@ -1013,7 +1136,7 @@
 	return USB_STOR_TRANSPORT_GOOD;
 }
 
-int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
+static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int rc;
 	struct alauda_info *info = (struct alauda_info *) us->extra;
@@ -1121,3 +1244,48 @@
 	return USB_STOR_TRANSPORT_FAILED;
 }
 
+static int alauda_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - alauda_usb_ids) + alauda_unusual_dev_list);
+	if (result)
+		return result;
+
+	us->transport_name  = "Alauda Control/Bulk";
+	us->transport = alauda_transport;
+	us->transport_reset = usb_stor_Bulk_reset;
+	us->max_lun = 1;
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver alauda_driver = {
+	.name =		"ums-alauda",
+	.probe =	alauda_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	alauda_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init alauda_init(void)
+{
+	return usb_register(&alauda_driver);
+}
+
+static void __exit alauda_exit(void)
+{
+	usb_deregister(&alauda_driver);
+}
+
+module_init(alauda_init);
+module_exit(alauda_exit);
diff --git a/drivers/usb/storage/alauda.h b/drivers/usb/storage/alauda.h
deleted file mode 100644
index a700f87..0000000
--- a/drivers/usb/storage/alauda.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Driver for Alauda-based card readers
- *
- * Current development and maintenance by:
- *    (c) 2005 Daniel Drake <dsd@gentoo.org>
- *
- * See alauda.c for more explanation.
- *
- * This program is free software; you can redistribute 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 _USB_ALAUDA_H
-#define _USB_ALAUDA_H
-
-/*
- * Status bytes
- */
-#define ALAUDA_STATUS_ERROR		0x01
-#define ALAUDA_STATUS_READY		0x40
-
-/*
- * Control opcodes (for request field)
- */
-#define ALAUDA_GET_XD_MEDIA_STATUS	0x08
-#define ALAUDA_GET_SM_MEDIA_STATUS	0x98
-#define ALAUDA_ACK_XD_MEDIA_CHANGE	0x0a
-#define ALAUDA_ACK_SM_MEDIA_CHANGE	0x9a
-#define ALAUDA_GET_XD_MEDIA_SIG		0x86
-#define ALAUDA_GET_SM_MEDIA_SIG		0x96
-
-/*
- * Bulk command identity (byte 0)
- */
-#define ALAUDA_BULK_CMD			0x40
-
-/*
- * Bulk opcodes (byte 1)
- */
-#define ALAUDA_BULK_GET_REDU_DATA	0x85
-#define ALAUDA_BULK_READ_BLOCK		0x94
-#define ALAUDA_BULK_ERASE_BLOCK		0xa3
-#define ALAUDA_BULK_WRITE_BLOCK		0xb4
-#define ALAUDA_BULK_GET_STATUS2		0xb7
-#define ALAUDA_BULK_RESET_MEDIA		0xe0
-
-/*
- * Port to operate on (byte 8)
- */
-#define ALAUDA_PORT_XD			0x00
-#define ALAUDA_PORT_SM			0x01
-
-/*
- * LBA and PBA are unsigned ints. Special values.
- */
-#define UNDEF    0xffff
-#define SPARE    0xfffe
-#define UNUSABLE 0xfffd
-
-int init_alauda(struct us_data *us);
-int alauda_transport(struct scsi_cmnd *srb, struct us_data *us);
-
-struct alauda_media_info {
-	unsigned long capacity;		/* total media size in bytes */
-	unsigned int pagesize;		/* page size in bytes */
-	unsigned int blocksize;		/* number of pages per block */
-	unsigned int uzonesize;		/* number of usable blocks per zone */
-	unsigned int zonesize;		/* number of blocks per zone */
-	unsigned int blockmask;		/* mask to get page from address */
-
-	unsigned char pageshift;
-	unsigned char blockshift;
-	unsigned char zoneshift;
-
-	u16 **lba_to_pba;		/* logical to physical block map */
-	u16 **pba_to_lba;		/* physical to logical block map */
-};
-
-struct alauda_info {
-	struct alauda_media_info port[2];
-	int wr_ep;			/* endpoint to write data out of */
-
-	unsigned char sense_key;
-	unsigned long sense_asc;	/* additional sense code */
-	unsigned long sense_ascq;	/* additional sense code qualifier */
-};
-
-#endif
-
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
index 898e67d..c844718 100644
--- a/drivers/usb/storage/cypress_atacb.c
+++ b/drivers/usb/storage/cypress_atacb.c
@@ -19,6 +19,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/module.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_eh.h>
@@ -29,6 +30,49 @@
 #include "scsiglue.h"
 #include "debug.h"
 
+MODULE_DESCRIPTION("SAT support for Cypress USB/ATA bridges with ATACB");
+MODULE_AUTHOR("Matthieu Castet <castet.matthieu@free.fr>");
+MODULE_LICENSE("GPL");
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id cypress_usb_ids[] = {
+#	include "unusual_cypress.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, cypress_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev cypress_unusual_dev_list[] = {
+#	include "unusual_cypress.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+
 /*
  * ATACB is a protocol used on cypress usb<->ata bridge to
  * send raw ATA command over mass storage
@@ -36,7 +80,7 @@
  * 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)
+static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
 {
 	unsigned char save_cmnd[MAX_COMMAND_SIZE];
 
@@ -133,19 +177,18 @@
 
 		/* 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;
+		scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sizeof(regs));
+
 		/* 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->cmd_len = 16;
+		srb->cmnd = ses.cmnd;
 		srb->cmnd[2] = 1;
 
 		usb_stor_transparent_scsi_command(srb, us);
+		memcpy(regs, srb->sense_buffer, sizeof(regs));
 		tmp_result = srb->result;
 		scsi_eh_restore_cmnd(srb, &ses);
 		/* we fail to get registers, report invalid command */
@@ -162,8 +205,8 @@
 
 		/* 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.
+		 * (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. */
@@ -198,3 +241,48 @@
 	if (srb->cmnd[0] == ATA_12)
 		srb->cmd_len = 12;
 }
+
+
+static int cypress_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - cypress_usb_ids) + cypress_unusual_dev_list);
+	if (result)
+		return result;
+
+	us->protocol_name = "Transparent SCSI with Cypress ATACB";
+	us->proto_handler = cypress_atacb_passthrough;
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver cypress_driver = {
+	.name =		"ums-cypress",
+	.probe =	cypress_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	cypress_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init cypress_init(void)
+{
+	return usb_register(&cypress_driver);
+}
+
+static void __exit cypress_exit(void)
+{
+	usb_deregister(&cypress_driver);
+}
+
+module_init(cypress_init);
+module_exit(cypress_exit);
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 17f1ae2..2b6e565 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -49,6 +49,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -58,12 +59,65 @@
 #include "transport.h"
 #include "protocol.h"
 #include "debug.h"
-#include "datafab.h"
+
+MODULE_DESCRIPTION("Driver for Datafab USB Compact Flash reader");
+MODULE_AUTHOR("Jimmie Mayfield <mayfield+datafab@sackheads.org>");
+MODULE_LICENSE("GPL");
+
+struct datafab_info {
+	unsigned long   sectors;	/* total sector count */
+	unsigned long   ssize;		/* sector size in bytes */
+	signed char	lun;		/* used for dual-slot readers */
+
+	/* the following aren't used yet */
+	unsigned char   sense_key;
+	unsigned long   sense_asc;	/* additional sense code */
+	unsigned long   sense_ascq;	/* additional sense code qualifier */
+};
 
 static int datafab_determine_lun(struct us_data *us,
 				 struct datafab_info *info);
 
 
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id datafab_usb_ids[] = {
+#	include "unusual_datafab.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, datafab_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev datafab_unusual_dev_list[] = {
+#	include "unusual_datafab.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+
 static inline int
 datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) {
 	if (len == 0)
@@ -500,7 +554,7 @@
 
 // Transport for the Datafab MDCFE-B
 //
-int datafab_transport(struct scsi_cmnd * srb, struct us_data *us)
+static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	struct datafab_info *info;
 	int rc;
@@ -665,3 +719,49 @@
 	info->sense_ascq = 0x00;
 	return USB_STOR_TRANSPORT_FAILED;
 }
+
+static int datafab_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - datafab_usb_ids) + datafab_unusual_dev_list);
+	if (result)
+		return result;
+
+	us->transport_name  = "Datafab Bulk-Only";
+	us->transport = datafab_transport;
+	us->transport_reset = usb_stor_Bulk_reset;
+	us->max_lun = 1;
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver datafab_driver = {
+	.name =		"ums-datafab",
+	.probe =	datafab_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	datafab_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init datafab_init(void)
+{
+	return usb_register(&datafab_driver);
+}
+
+static void __exit datafab_exit(void)
+{
+	usb_deregister(&datafab_driver);
+}
+
+module_init(datafab_init);
+module_exit(datafab_exit);
diff --git a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h
deleted file mode 100644
index 32e3f27..0000000
--- a/drivers/usb/storage/datafab.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Driver for Datafab MDCFE-B USB Compact Flash reader
- * Header File
- *
- * Current development and maintenance by:
- *   (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org)
- *
- * See datafab.c for more explanation
- *
- * This program is free software; you can redistribute 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 _USB_DATAFAB_MDCFE_B_H
-#define _USB_DATAFAB_MDCFE_B_H
-
-extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us);
-
-struct datafab_info {
-	unsigned long   sectors;	// total sector count
-	unsigned long   ssize;		// sector size in bytes
-	signed char	lun;		// used for dual-slot readers
-	
-	// the following aren't used yet
-	unsigned char   sense_key;
-	unsigned long   sense_asc;	// additional sense code
-	unsigned long   sense_ascq;	// additional sense code qualifier
-};
-
-#endif
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index 73ac726..54cc942 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -26,6 +26,7 @@
  * (http://www.freecom.de/)
  */
 
+#include <linux/module.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
@@ -33,7 +34,10 @@
 #include "transport.h"
 #include "protocol.h"
 #include "debug.h"
-#include "freecom.h"
+
+MODULE_DESCRIPTION("Driver for Freecom USB/IDE adaptor");
+MODULE_AUTHOR("David Brown <usb-storage@davidb.org>");
+MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
 static void pdump (void *, int);
@@ -103,6 +107,47 @@
 #define FCM_PACKET_LENGTH		64
 #define FCM_STATUS_PACKET_LENGTH	4
 
+static int init_freecom(struct us_data *us);
+
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id freecom_usb_ids[] = {
+#	include "unusual_freecom.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, freecom_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev freecom_unusual_dev_list[] = {
+#	include "unusual_freecom.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
 static int
 freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
 		unsigned int ipipe, unsigned int opipe, int count)
@@ -173,7 +218,7 @@
  * Transport for the Freecom USB/IDE adaptor.
  *
  */
-int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
+static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	struct freecom_cb_wrap *fcb;
 	struct freecom_status  *fst;
@@ -377,8 +422,7 @@
 	return USB_STOR_TRANSPORT_GOOD;
 }
 
-int
-freecom_init (struct us_data *us)
+static int init_freecom(struct us_data *us)
 {
 	int result;
 	char *buffer = us->iobuf;
@@ -417,7 +461,7 @@
 	return USB_STOR_TRANSPORT_GOOD;
 }
 
-int usb_stor_freecom_reset(struct us_data *us)
+static int usb_stor_freecom_reset(struct us_data *us)
 {
 	printk (KERN_CRIT "freecom reset called\n");
 
@@ -479,3 +523,48 @@
 }
 #endif
 
+static int freecom_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - freecom_usb_ids) + freecom_unusual_dev_list);
+	if (result)
+		return result;
+
+	us->transport_name = "Freecom";
+	us->transport = freecom_transport;
+	us->transport_reset = usb_stor_freecom_reset;
+	us->max_lun = 0;
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver freecom_driver = {
+	.name =		"ums-freecom",
+	.probe =	freecom_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	freecom_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init freecom_init(void)
+{
+	return usb_register(&freecom_driver);
+}
+
+static void __exit freecom_exit(void)
+{
+	usb_deregister(&freecom_driver);
+}
+
+module_init(freecom_init);
+module_exit(freecom_exit);
diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h
deleted file mode 100644
index 20d0fe6..0000000
--- a/drivers/usb/storage/freecom.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Driver for Freecom USB/IDE adaptor
- *
- * Freecom v0.1:
- *
- * First release
- *
- * Current development and maintenance by:
- *   (c) 2000 David Brown <usb-storage@davidb.org>
- *
- * See freecom.c for more explanation
- *
- * This program is free software; you can redistribute 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 _FREECOM_USB_H
-#define _FREECOM_USB_H
-
-extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us);
-extern int usb_stor_freecom_reset(struct us_data *us);
-extern int freecom_init (struct us_data *us);
-
-#endif
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 383abf2..882c57b 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -44,6 +44,7 @@
 
 #include <linux/jiffies.h>
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/hdreg.h>
 #include <linux/scatterlist.h>
@@ -57,7 +58,53 @@
 #include "protocol.h"
 #include "debug.h"
 #include "scsiglue.h"
-#include "isd200.h"
+
+MODULE_DESCRIPTION("Driver for In-System Design, Inc. ISD200 ASIC");
+MODULE_AUTHOR("Björn Stenberg <bjorn@haxx.se>");
+MODULE_LICENSE("GPL");
+
+static int isd200_Initialization(struct us_data *us);
+
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id isd200_usb_ids[] = {
+#	include "unusual_isd200.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, isd200_usb_ids);
+
+#undef UNUSUAL_DEV
+#undef USUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev isd200_unusual_dev_list[] = {
+#	include "unusual_isd200.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+#undef USUAL_DEV
 
 
 /* Timeout defines (in Seconds) */
@@ -1518,7 +1565,7 @@
  * Initialization for the ISD200 
  */
 
-int isd200_Initialization(struct us_data *us)
+static int isd200_Initialization(struct us_data *us)
 {
 	US_DEBUGP("ISD200 Initialization...\n");
 
@@ -1549,7 +1596,7 @@
  *
  */
 
-void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
+static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int sendToTransport = 1, orig_bufflen;
 	union ata_cdb ataCdb;
@@ -1570,3 +1617,47 @@
 
 	isd200_srb_set_bufflen(srb, orig_bufflen);
 }
+
+static int isd200_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - isd200_usb_ids) + isd200_unusual_dev_list);
+	if (result)
+		return result;
+
+	us->protocol_name = "ISD200 ATA/ATAPI";
+	us->proto_handler = isd200_ata_command;
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver isd200_driver = {
+	.name =		"ums-isd200",
+	.probe =	isd200_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	isd200_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init isd200_init(void)
+{
+	return usb_register(&isd200_driver);
+}
+
+static void __exit isd200_exit(void)
+{
+	usb_deregister(&isd200_driver);
+}
+
+module_init(isd200_init);
+module_exit(isd200_exit);
diff --git a/drivers/usb/storage/isd200.h b/drivers/usb/storage/isd200.h
deleted file mode 100644
index 0a35f4f..0000000
--- a/drivers/usb/storage/isd200.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Header File for In-System Design, Inc. ISD200 ASIC
- *
- * First release
- *
- * Current development and maintenance by:
- *   (c) 2000 In-System Design, Inc. (support@in-system.com)
- *
- * See isd200.c for more 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.
- */
-
-#ifndef _USB_ISD200_H
-#define _USB_ISD200_H
-
-extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us);
-extern int isd200_Initialization(struct us_data *us);
-
-#endif
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index df67f13..1c69420 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -46,6 +46,7 @@
   */
 
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -55,9 +56,61 @@
 #include "transport.h"
 #include "protocol.h"
 #include "debug.h"
-#include "jumpshot.h"
 
 
+MODULE_DESCRIPTION("Driver for Lexar \"Jumpshot\" Compact Flash reader");
+MODULE_AUTHOR("Jimmie Mayfield <mayfield+usb@sackheads.org>");
+MODULE_LICENSE("GPL");
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id jumpshot_usb_ids[] = {
+#	include "unusual_jumpshot.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, jumpshot_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev jumpshot_unusual_dev_list[] = {
+#	include "unusual_jumpshot.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+
+struct jumpshot_info {
+   unsigned long   sectors;     /* total sector count */
+   unsigned long   ssize;       /* sector size in bytes */
+
+   /* the following aren't used yet */
+   unsigned char   sense_key;
+   unsigned long   sense_asc;   /* additional sense code */
+   unsigned long   sense_ascq;  /* additional sense code qualifier */
+};
+
 static inline int jumpshot_bulk_read(struct us_data *us,
 				     unsigned char *data, 
 				     unsigned int len)
@@ -429,7 +482,7 @@
 
 // Transport for the Lexar 'Jumpshot'
 //
-int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us)
+static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	struct jumpshot_info *info;
 	int rc;
@@ -592,3 +645,49 @@
 	info->sense_ascq = 0x00;
 	return USB_STOR_TRANSPORT_FAILED;
 }
+
+static int jumpshot_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - jumpshot_usb_ids) + jumpshot_unusual_dev_list);
+	if (result)
+		return result;
+
+	us->transport_name  = "Lexar Jumpshot Control/Bulk";
+	us->transport = jumpshot_transport;
+	us->transport_reset = usb_stor_Bulk_reset;
+	us->max_lun = 1;
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver jumpshot_driver = {
+	.name =		"ums-jumpshot",
+	.probe =	jumpshot_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	jumpshot_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init jumpshot_init(void)
+{
+	return usb_register(&jumpshot_driver);
+}
+
+static void __exit jumpshot_exit(void)
+{
+	usb_deregister(&jumpshot_driver);
+}
+
+module_init(jumpshot_init);
+module_exit(jumpshot_exit);
diff --git a/drivers/usb/storage/jumpshot.h b/drivers/usb/storage/jumpshot.h
deleted file mode 100644
index 19bac9d..0000000
--- a/drivers/usb/storage/jumpshot.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Driver for Lexar "Jumpshot" USB Compact Flash reader
- * Header File
- *
- * Current development and maintenance by:
- *   (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org)
- *
- * See jumpshot.c for more explanation
- *
- * This program is free software; you can redistribute 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 _USB_JUMPSHOT_H
-#define _USB_JUMPSHOT_H
-
-extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us);
-
-struct jumpshot_info {
-   unsigned long   sectors;     // total sector count
-   unsigned long   ssize;       // sector size in bytes
- 
-   // the following aren't used yet
-   unsigned char   sense_key;
-   unsigned long   sense_asc;   // additional sense code
-   unsigned long   sense_ascq;  // additional sense code qualifier
-};
-
-#endif
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
index 0d79ae5..7953d93 100644
--- a/drivers/usb/storage/karma.c
+++ b/drivers/usb/storage/karma.c
@@ -18,6 +18,8 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/module.h>
+
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -25,7 +27,10 @@
 #include "usb.h"
 #include "transport.h"
 #include "debug.h"
-#include "karma.h"
+
+MODULE_DESCRIPTION("Driver for Rio Karma");
+MODULE_AUTHOR("Bob Copeland <me@bobcopeland.com>, Keith Bennett <keith@mcs.st-and.ac.uk>");
+MODULE_LICENSE("GPL");
 
 #define RIO_PREFIX "RIOP\x00"
 #define RIO_PREFIX_LEN 5
@@ -36,13 +41,53 @@
 #define RIO_LEAVE_STORAGE 0x2
 #define RIO_RESET 0xC
 
-extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *);
-
 struct karma_data {
 	int in_storage;
 	char *recv;
 };
 
+static int rio_karma_init(struct us_data *us);
+
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id karma_usb_ids[] = {
+#	include "unusual_karma.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, karma_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev karma_unusual_dev_list[] = {
+#	include "unusual_karma.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+
 /*
  * Send commands to Rio Karma.
  *
@@ -104,7 +149,7 @@
  * Trap START_STOP and READ_10 to leave/re-enter storage mode.
  * Everything else is propagated to the normal bulk layer.
  */
-int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
+static int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int ret;
 	struct karma_data *data = (struct karma_data *) us->extra;
@@ -133,7 +178,7 @@
 	kfree(data->recv);
 }
 
-int rio_karma_init(struct us_data *us)
+static int rio_karma_init(struct us_data *us)
 {
 	int ret = 0;
 	struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
@@ -153,3 +198,48 @@
 out:
 	return ret;
 }
+
+static int karma_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - karma_usb_ids) + karma_unusual_dev_list);
+	if (result)
+		return result;
+
+	us->transport_name = "Rio Karma/Bulk";
+	us->transport = rio_karma_transport;
+	us->transport_reset = usb_stor_Bulk_reset;
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver karma_driver = {
+	.name =		"ums-karma",
+	.probe =	karma_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	karma_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init karma_init(void)
+{
+	return usb_register(&karma_driver);
+}
+
+static void __exit karma_exit(void)
+{
+	usb_deregister(&karma_driver);
+}
+
+module_init(karma_init);
+module_exit(karma_exit);
diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h
deleted file mode 100644
index 8a60972..0000000
--- a/drivers/usb/storage/karma.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _KARMA_USB_H
-#define _KARMA_USB_H
-
-extern int rio_karma_init(struct us_data *us);
-extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us);
-
-#endif
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
index f970b27..fe3ffe1 100644
--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -38,37 +38,6 @@
 static int usu_probe_thread(void *arg);
 
 /*
- * The table.
- */
-#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
-		    vendorName, productName,useProtocol, useTransport, \
-		    initFunction, flags) \
-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
-  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
-
-#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
-		    vendorName, productName, useProtocol, useTransport, \
-		    initFunction, flags) \
-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
-  .driver_info = (flags) }
-
-#define USUAL_DEV(useProto, useTrans, useType) \
-{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
-  .driver_info = ((useType)<<24) }
-
-struct usb_device_id storage_usb_ids [] = {
-#	include "unusual_devs.h"
-	{ } /* Terminating entry */
-};
-
-#undef USUAL_DEV
-#undef UNUSUAL_DEV
-#undef COMPLIANT_DEV
-
-MODULE_DEVICE_TABLE(usb, storage_usb_ids);
-EXPORT_SYMBOL_GPL(storage_usb_ids);
-
-/*
  * @type: the module type as an integer
  */
 void usb_usual_set_present(int type)
@@ -167,7 +136,7 @@
 	.name =		"libusual",
 	.probe =	usu_probe,
 	.disconnect =	usu_disconnect,
-	.id_table =	storage_usb_ids,
+	.id_table =	usb_storage_usb_ids,
 };
 
 /*
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index c7bf895..380233b 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -35,9 +35,16 @@
 #include <linux/module.h>
 #include <linux/usb/input.h>
 #include "usb.h"
-#include "onetouch.h"
 #include "debug.h"
 
+MODULE_DESCRIPTION("Maxtor USB OneTouch hard drive button driver");
+MODULE_AUTHOR("Nick Sillik <n.sillik@temple.edu>");
+MODULE_LICENSE("GPL");
+
+#define ONETOUCH_PKT_LEN        0x02
+#define ONETOUCH_BUTTON         KEY_PROG1
+
+static int onetouch_connect_input(struct us_data *ss);
 static void onetouch_release_input(void *onetouch_);
 
 struct usb_onetouch {
@@ -52,6 +59,46 @@
 	unsigned int is_open:1;
 };
 
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id onetouch_usb_ids[] = {
+#	include "unusual_onetouch.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, onetouch_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev onetouch_unusual_dev_list[] = {
+#	include "unusual_onetouch.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+
 static void usb_onetouch_irq(struct urb *urb)
 {
 	struct usb_onetouch *onetouch = urb->context;
@@ -127,7 +174,7 @@
 }
 #endif /* CONFIG_PM */
 
-int onetouch_connect_input(struct us_data *ss)
+static int onetouch_connect_input(struct us_data *ss)
 {
 	struct usb_device *udev = ss->pusb_dev;
 	struct usb_host_interface *interface;
@@ -236,3 +283,46 @@
 				onetouch->data, onetouch->data_dma);
 	}
 }
+
+static int onetouch_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - onetouch_usb_ids) + onetouch_unusual_dev_list);
+	if (result)
+		return result;
+
+	/* Use default transport and protocol */
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver onetouch_driver = {
+	.name =		"ums-onetouch",
+	.probe =	onetouch_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	onetouch_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init onetouch_init(void)
+{
+	return usb_register(&onetouch_driver);
+}
+
+static void __exit onetouch_exit(void)
+{
+	usb_deregister(&onetouch_driver);
+}
+
+module_init(onetouch_init);
+module_exit(onetouch_exit);
diff --git a/drivers/usb/storage/onetouch.h b/drivers/usb/storage/onetouch.h
deleted file mode 100644
index 41c7aa8..0000000
--- a/drivers/usb/storage/onetouch.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ONETOUCH_H_
-#define _ONETOUCH_H_
-
-#define ONETOUCH_PKT_LEN        0x02
-#define ONETOUCH_BUTTON         KEY_PROG1
-
-int onetouch_connect_input(struct us_data *ss);
-
-#endif
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index be441d8..fc310f7 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -121,6 +121,7 @@
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
 }
+EXPORT_SYMBOL_GPL(usb_stor_transparent_scsi_command);
 
 /***********************************************************************
  * Scatter-gather transfer buffer access routines
@@ -199,6 +200,7 @@
 	/* Return the amount actually transferred */
 	return cnt;
 }
+EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf);
 
 /* Store the contents of buffer into srb's transfer buffer and set the
  * SCSI residue.
@@ -215,3 +217,4 @@
 	if (buflen < scsi_bufflen(srb))
 		scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
 }
+EXPORT_SYMBOL_GPL(usb_stor_set_xfer_buf);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 727c506..4ca3b58 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -135,6 +135,12 @@
 		if (sdev->request_queue->max_sectors > max_sectors)
 			blk_queue_max_sectors(sdev->request_queue,
 					      max_sectors);
+	} else if (sdev->type == TYPE_TAPE) {
+		/* Tapes need much higher max_sector limits, so just
+		 * raise it to the maximum possible (4 GB / 512) and
+		 * let the queue segment size sort out the real limit.
+		 */
+		blk_queue_max_sectors(sdev->request_queue, 0x7FFFFF);
 	}
 
 	/* Some USB host controllers can't do DMA; they have to use PIO.
@@ -563,4 +569,4 @@
 	[7]	= 0x0a,			    /* additional length */
 	[12]	= 0x24			    /* Invalid Field in CDB */
 };
-
+EXPORT_SYMBOL_GPL(usb_stor_sense_invalidCDB);
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 531ae5c..ab5f9f3 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -41,6 +41,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -51,7 +52,53 @@
 #include "transport.h"
 #include "protocol.h"
 #include "debug.h"
-#include "sddr09.h"
+
+MODULE_DESCRIPTION("Driver for SanDisk SDDR-09 SmartMedia reader");
+MODULE_AUTHOR("Andries Brouwer <aeb@cwi.nl>, Robert Baruch <autophile@starband.net>");
+MODULE_LICENSE("GPL");
+
+static int usb_stor_sddr09_dpcm_init(struct us_data *us);
+static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
+static int usb_stor_sddr09_init(struct us_data *us);
+
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id sddr09_usb_ids[] = {
+#	include "unusual_sddr09.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, sddr09_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev sddr09_unusual_dev_list[] = {
+#	include "unusual_sddr09.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
 
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
@@ -723,7 +770,7 @@
 	len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;
 	buffer = kmalloc(len, GFP_NOIO);
 	if (buffer == NULL) {
-		printk("sddr09_read_data: Out of memory\n");
+		printk(KERN_WARNING "sddr09_read_data: Out of memory\n");
 		return -ENOMEM;
 	}
 
@@ -838,7 +885,8 @@
 	if (pba == UNDEF) {
 		pba = sddr09_find_unused_pba(info, lba);
 		if (!pba) {
-			printk("sddr09_write_lba: Out of unused blocks\n");
+			printk(KERN_WARNING
+			       "sddr09_write_lba: Out of unused blocks\n");
 			return -ENOSPC;
 		}
 		info->pba_to_lba[pba] = lba;
@@ -849,7 +897,7 @@
 	if (pba == 1) {
 		/* Maybe it is impossible to write to PBA 1.
 		   Fake success, but don't do anything. */
-		printk("sddr09: avoid writing to pba 1\n");
+		printk(KERN_WARNING "sddr09: avoid writing to pba 1\n");
 		return 0;
 	}
 
@@ -954,7 +1002,7 @@
 	blocklen = (pagelen << info->blockshift);
 	blockbuffer = kmalloc(blocklen, GFP_NOIO);
 	if (!blockbuffer) {
-		printk("sddr09_write_data: Out of memory\n");
+		printk(KERN_WARNING "sddr09_write_data: Out of memory\n");
 		return -ENOMEM;
 	}
 
@@ -965,7 +1013,7 @@
 	len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;
 	buffer = kmalloc(len, GFP_NOIO);
 	if (buffer == NULL) {
-		printk("sddr09_write_data: Out of memory\n");
+		printk(KERN_WARNING "sddr09_write_data: Out of memory\n");
 		kfree(blockbuffer);
 		return -ENOMEM;
 	}
@@ -1112,7 +1160,7 @@
 
 	if (result) {
 		US_DEBUGP("Result of read_deviceID is %d\n", result);
-		printk("sddr09: could not read card info\n");
+		printk(KERN_WARNING "sddr09: could not read card info\n");
 		return NULL;
 	}
 
@@ -1153,7 +1201,7 @@
 		sprintf(blurbtxt + strlen(blurbtxt),
 			", WP");
 
-	printk("%s\n", blurbtxt);
+	printk(KERN_WARNING "%s\n", blurbtxt);
 
 	return cardinfo;
 }
@@ -1184,7 +1232,7 @@
 	alloc_len = (alloc_blocks << CONTROL_SHIFT);
 	buffer = kmalloc(alloc_len, GFP_NOIO);
 	if (buffer == NULL) {
-		printk("sddr09_read_map: out of memory\n");
+		printk(KERN_WARNING "sddr09_read_map: out of memory\n");
 		result = -1;
 		goto done;
 	}
@@ -1198,7 +1246,7 @@
 	info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
 
 	if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) {
-		printk("sddr09_read_map: out of memory\n");
+		printk(KERN_WARNING "sddr09_read_map: out of memory\n");
 		result = -1;
 		goto done;
 	}
@@ -1238,7 +1286,8 @@
 			if (ptr[j] != 0)
 				goto nonz;
 		info->pba_to_lba[i] = UNUSABLE;
-		printk("sddr09: PBA %d has no logical mapping\n", i);
+		printk(KERN_WARNING "sddr09: PBA %d has no logical mapping\n",
+		       i);
 		continue;
 
 	nonz:
@@ -1251,7 +1300,8 @@
 	nonff:
 		/* normal PBAs start with six FFs */
 		if (j < 6) {
-			printk("sddr09: PBA %d has no logical mapping: "
+			printk(KERN_WARNING
+			       "sddr09: PBA %d has no logical mapping: "
 			       "reserved area = %02X%02X%02X%02X "
 			       "data status %02X block status %02X\n",
 			       i, ptr[0], ptr[1], ptr[2], ptr[3],
@@ -1261,7 +1311,8 @@
 		}
 
 		if ((ptr[6] >> 4) != 0x01) {
-			printk("sddr09: PBA %d has invalid address field "
+			printk(KERN_WARNING
+			       "sddr09: PBA %d has invalid address field "
 			       "%02X%02X/%02X%02X\n",
 			       i, ptr[6], ptr[7], ptr[11], ptr[12]);
 			info->pba_to_lba[i] = UNUSABLE;
@@ -1270,7 +1321,8 @@
 
 		/* check even parity */
 		if (parity[ptr[6] ^ ptr[7]]) {
-			printk("sddr09: Bad parity in LBA for block %d"
+			printk(KERN_WARNING
+			       "sddr09: Bad parity in LBA for block %d"
 			       " (%02X %02X)\n", i, ptr[6], ptr[7]);
 			info->pba_to_lba[i] = UNUSABLE;
 			continue;
@@ -1289,7 +1341,8 @@
 		 */
 
 		if (lba >= 1000) {
-			printk("sddr09: Bad low LBA %d for block %d\n",
+			printk(KERN_WARNING
+			       "sddr09: Bad low LBA %d for block %d\n",
 			       lba, i);
 			goto possibly_erase;
 		}
@@ -1297,7 +1350,8 @@
 		lba += 1000*(i/0x400);
 
 		if (info->lba_to_pba[lba] != UNDEF) {
-			printk("sddr09: LBA %d seen for PBA %d and %d\n",
+			printk(KERN_WARNING
+			       "sddr09: LBA %d seen for PBA %d and %d\n",
 			       lba, info->lba_to_pba[lba], i);
 			goto possibly_erase;
 		}
@@ -1399,7 +1453,7 @@
  * unusual devices list but called from here then LUN 0 of the combo reader
  * is not recognized. But I do not know what precisely these calls do.
  */
-int
+static int
 usb_stor_sddr09_dpcm_init(struct us_data *us) {
 	int result;
 	unsigned char *data = us->iobuf;
@@ -1449,7 +1503,7 @@
 /*
  * Transport for the Microtech DPCM-USB
  */
-int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
+static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int ret;
 
@@ -1491,7 +1545,7 @@
 /*
  * Transport for the Sandisk SDDR-09
  */
-int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
+static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	static unsigned char sensekey = 0, sensecode = 0;
 	static unsigned char havefakesense = 0;
@@ -1690,7 +1744,60 @@
 /*
  * Initialization routine for the sddr09 subdriver
  */
-int
+static int
 usb_stor_sddr09_init(struct us_data *us) {
 	return sddr09_common_init(us);
 }
+
+static int sddr09_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - sddr09_usb_ids) + sddr09_unusual_dev_list);
+	if (result)
+		return result;
+
+	if (us->protocol == US_PR_DPCM_USB) {
+		us->transport_name = "Control/Bulk-EUSB/SDDR09";
+		us->transport = dpcm_transport;
+		us->transport_reset = usb_stor_CB_reset;
+		us->max_lun = 1;
+	} else {
+		us->transport_name = "EUSB/SDDR09";
+		us->transport = sddr09_transport;
+		us->transport_reset = usb_stor_CB_reset;
+		us->max_lun = 0;
+	}
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver sddr09_driver = {
+	.name =		"ums-sddr09",
+	.probe =	sddr09_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	sddr09_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init sddr09_init(void)
+{
+	return usb_register(&sddr09_driver);
+}
+
+static void __exit sddr09_exit(void)
+{
+	usb_deregister(&sddr09_driver);
+}
+
+module_init(sddr09_init);
+module_exit(sddr09_exit);
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
deleted file mode 100644
index b701172..0000000
--- a/drivers/usb/storage/sddr09.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Driver for SanDisk SDDR-09 SmartMedia reader
- * Header File
- *
- * Current development and maintenance by:
- *   (c) 2000 Robert Baruch (autophile@dol.net)
- *   (c) 2002 Andries Brouwer (aeb@cwi.nl)
- *
- * See sddr09.c for more explanation
- *
- * This program is free software; you can redistribute 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 _USB_SHUTTLE_EUSB_SDDR09_H
-#define _USB_SHUTTLE_EUSB_SDDR09_H
-
-/* Sandisk SDDR-09 stuff */
-
-extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
-extern int usb_stor_sddr09_init(struct us_data *us);
-
-/* Microtech DPCM-USB stuff */
-
-extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us);
-extern int usb_stor_sddr09_dpcm_init(struct us_data *us);
-
-#endif
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index 0d8df75..44dfed7 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -24,6 +24,7 @@
 
 #include <linux/jiffies.h>
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -33,7 +34,48 @@
 #include "transport.h"
 #include "protocol.h"
 #include "debug.h"
-#include "sddr55.h"
+
+MODULE_DESCRIPTION("Driver for SanDisk SDDR-55 SmartMedia reader");
+MODULE_AUTHOR("Simon Munton");
+MODULE_LICENSE("GPL");
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id sddr55_usb_ids[] = {
+#	include "unusual_sddr55.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, sddr55_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev sddr55_unusual_dev_list[] = {
+#	include "unusual_sddr55.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
 
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
@@ -513,7 +555,8 @@
 }
 
 
-int sddr55_reset(struct us_data *us) {
+static int sddr55_reset(struct us_data *us)
+{
 	return 0;
 }
 
@@ -703,7 +746,9 @@
 		
 		if (info->lba_to_pba[lba + zone * 1000] != NOT_ALLOCATED &&
 		    !info->force_read_only) {
-			printk("sddr55: map inconsistency at LBA %04X\n", lba + zone * 1000);
+			printk(KERN_WARNING
+			       "sddr55: map inconsistency at LBA %04X\n",
+			       lba + zone * 1000);
 			info->force_read_only = 1;
 		}
 
@@ -732,7 +777,7 @@
 /*
  * Transport for the Sandisk SDDR-55
  */
-int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
+static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int result;
 	static unsigned char inquiry_response[8] = {
@@ -929,3 +974,49 @@
 	return USB_STOR_TRANSPORT_FAILED; // FIXME: sense buffer?
 }
 
+
+static int sddr55_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - sddr55_usb_ids) + sddr55_unusual_dev_list);
+	if (result)
+		return result;
+
+	us->transport_name = "SDDR55";
+	us->transport = sddr55_transport;
+	us->transport_reset = sddr55_reset;
+	us->max_lun = 0;
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver sddr55_driver = {
+	.name =		"ums-sddr55",
+	.probe =	sddr55_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	sddr55_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init sddr55_init(void)
+{
+	return usb_register(&sddr55_driver);
+}
+
+static void __exit sddr55_exit(void)
+{
+	usb_deregister(&sddr55_driver);
+}
+
+module_init(sddr55_init);
+module_exit(sddr55_exit);
diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h
deleted file mode 100644
index a815a04..0000000
--- a/drivers/usb/storage/sddr55.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Driver for SanDisk SDDR-55 SmartMedia reader
- * Header File
- *
- * Current development and maintenance by:
- *   (c) 2002 Simon Munton
- *
- * See sddr55.c for more explanation
- *
- * This program is free software; you can redistribute 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 _USB_SHUTTLE_EUSB_SDDR55_H
-#define _USB_SHUTTLE_EUSB_SDDR55_H
-
-/* Sandisk SDDR-55 stuff */
-
-extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us);
-extern int sddr55_reset(struct us_data *us);
-
-#endif
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index ae6d6481..b62a288 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -42,6 +42,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/cdrom.h>
 
@@ -52,7 +53,100 @@
 #include "transport.h"
 #include "protocol.h"
 #include "debug.h"
-#include "shuttle_usbat.h"
+
+MODULE_DESCRIPTION("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable");
+MODULE_AUTHOR("Daniel Drake <dsd@gentoo.org>, Robert Baruch <autophile@starband.net>");
+MODULE_LICENSE("GPL");
+
+/* Supported device types */
+#define USBAT_DEV_HP8200	0x01
+#define USBAT_DEV_FLASH		0x02
+
+#define USBAT_EPP_PORT		0x10
+#define USBAT_EPP_REGISTER	0x30
+#define USBAT_ATA		0x40
+#define USBAT_ISA		0x50
+
+/* Commands (need to be logically OR'd with an access type */
+#define USBAT_CMD_READ_REG		0x00
+#define USBAT_CMD_WRITE_REG		0x01
+#define USBAT_CMD_READ_BLOCK	0x02
+#define USBAT_CMD_WRITE_BLOCK	0x03
+#define USBAT_CMD_COND_READ_BLOCK	0x04
+#define USBAT_CMD_COND_WRITE_BLOCK	0x05
+#define USBAT_CMD_WRITE_REGS	0x07
+
+/* Commands (these don't need an access type) */
+#define USBAT_CMD_EXEC_CMD	0x80
+#define USBAT_CMD_SET_FEAT	0x81
+#define USBAT_CMD_UIO		0x82
+
+/* Methods of accessing UIO register */
+#define USBAT_UIO_READ	1
+#define USBAT_UIO_WRITE	0
+
+/* Qualifier bits */
+#define USBAT_QUAL_FCQ	0x20	/* full compare */
+#define USBAT_QUAL_ALQ	0x10	/* auto load subcount */
+
+/* USBAT Flash Media status types */
+#define USBAT_FLASH_MEDIA_NONE	0
+#define USBAT_FLASH_MEDIA_CF	1
+
+/* USBAT Flash Media change types */
+#define USBAT_FLASH_MEDIA_SAME	0
+#define USBAT_FLASH_MEDIA_CHANGED	1
+
+/* USBAT ATA registers */
+#define USBAT_ATA_DATA      0x10  /* read/write data (R/W) */
+#define USBAT_ATA_FEATURES  0x11  /* set features (W) */
+#define USBAT_ATA_ERROR     0x11  /* error (R) */
+#define USBAT_ATA_SECCNT    0x12  /* sector count (R/W) */
+#define USBAT_ATA_SECNUM    0x13  /* sector number (R/W) */
+#define USBAT_ATA_LBA_ME    0x14  /* cylinder low (R/W) */
+#define USBAT_ATA_LBA_HI    0x15  /* cylinder high (R/W) */
+#define USBAT_ATA_DEVICE    0x16  /* head/device selection (R/W) */
+#define USBAT_ATA_STATUS    0x17  /* device status (R) */
+#define USBAT_ATA_CMD       0x17  /* device command (W) */
+#define USBAT_ATA_ALTSTATUS 0x0E  /* status (no clear IRQ) (R) */
+
+/* USBAT User I/O Data registers */
+#define USBAT_UIO_EPAD		0x80 /* Enable Peripheral Control Signals */
+#define USBAT_UIO_CDT		0x40 /* Card Detect (Read Only) */
+				     /* CDT = ACKD & !UI1 & !UI0 */
+#define USBAT_UIO_1		0x20 /* I/O 1 */
+#define USBAT_UIO_0		0x10 /* I/O 0 */
+#define USBAT_UIO_EPP_ATA	0x08 /* 1=EPP mode, 0=ATA mode */
+#define USBAT_UIO_UI1		0x04 /* Input 1 */
+#define USBAT_UIO_UI0		0x02 /* Input 0 */
+#define USBAT_UIO_INTR_ACK	0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */
+
+/* USBAT User I/O Enable registers */
+#define USBAT_UIO_DRVRST	0x80 /* Reset Peripheral */
+#define USBAT_UIO_ACKD		0x40 /* Enable Card Detect */
+#define USBAT_UIO_OE1		0x20 /* I/O 1 set=output/clr=input */
+				     /* If ACKD=1, set OE1 to 1 also. */
+#define USBAT_UIO_OE0		0x10 /* I/O 0 set=output/clr=input */
+#define USBAT_UIO_ADPRST	0x01 /* Reset SCM chip */
+
+/* USBAT Features */
+#define USBAT_FEAT_ETEN	0x80	/* External trigger enable */
+#define USBAT_FEAT_U1	0x08
+#define USBAT_FEAT_U0	0x04
+#define USBAT_FEAT_ET1	0x02
+#define USBAT_FEAT_ET2	0x01
+
+struct usbat_info {
+	int devicetype;
+
+	/* Used for Flash readers only */
+	unsigned long sectors;     /* total sector count */
+	unsigned long ssize;       /* sector size in bytes */
+
+	unsigned char sense_key;
+	unsigned long sense_asc;   /* additional sense code */
+	unsigned long sense_ascq;  /* additional sense code qualifier */
+};
 
 #define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
@@ -63,6 +157,48 @@
 static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
 static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
 
+static int init_usbat_cd(struct us_data *us);
+static int init_usbat_flash(struct us_data *us);
+
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id usbat_usb_ids[] = {
+#	include "unusual_usbat.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, usbat_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev usbat_unusual_dev_list[] = {
+#	include "unusual_usbat.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
 /*
  * Convenience function to produce an ATA read/write sectors command
  * Use cmd=0x20 for read, cmd=0x30 for write
@@ -1684,37 +1820,61 @@
 	return USB_STOR_TRANSPORT_FAILED;
 }
 
-int init_usbat_cd(struct us_data *us)
+static int init_usbat_cd(struct us_data *us)
 {
 	return init_usbat(us, USBAT_DEV_HP8200);
 }
 
-
-int init_usbat_flash(struct us_data *us)
+static int init_usbat_flash(struct us_data *us)
 {
 	return init_usbat(us, USBAT_DEV_FLASH);
 }
 
-int init_usbat_probe(struct us_data *us)
+static int usbat_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
 {
-	return init_usbat(us, 0);
+	struct us_data *us;
+	int result;
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - usbat_usb_ids) + usbat_unusual_dev_list);
+	if (result)
+		return result;
+
+	/* The actual transport will be determined later by the
+	 * initialization routine; this is just a placeholder.
+	 */
+	us->transport_name = "Shuttle USBAT";
+	us->transport = usbat_flash_transport;
+	us->transport_reset = usb_stor_CB_reset;
+	us->max_lun = 1;
+
+	result = usb_stor_probe2(us);
+	return result;
 }
 
-/*
- * Default transport function. Attempts to detect which transport function
- * should be called, makes it the new default, and calls it.
- *
- * This function should never be called. Our usbat_init() function detects the
- * device type and changes the us->transport ptr to the transport function
- * relevant to the device.
- * However, we'll support this impossible(?) case anyway.
- */
-int usbat_transport(struct scsi_cmnd *srb, struct us_data *us)
+static struct usb_driver usbat_driver = {
+	.name =		"ums-usbat",
+	.probe =	usbat_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	usbat_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init usbat_init(void)
 {
-	struct usbat_info *info = (struct usbat_info*) (us->extra);
-
-	if (usbat_set_transport(us, info, 0))
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return us->transport(srb, us);	
+	return usb_register(&usbat_driver);
 }
+
+static void __exit usbat_exit(void)
+{
+	usb_deregister(&usbat_driver);
+}
+
+module_init(usbat_init);
+module_exit(usbat_exit);
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
deleted file mode 100644
index d8bfc43..0000000
--- a/drivers/usb/storage/shuttle_usbat.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Driver for SCM Microsystems USB-ATAPI cable
- * Header File
- *
- * Current development and maintenance by:
- *   (c) 2000 Robert Baruch (autophile@dol.net)
- *   (c) 2004, 2005 Daniel Drake <dsd@gentoo.org>
- *
- * See shuttle_usbat.c for more explanation
- *
- * This program is free software; you can redistribute 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 _USB_SHUTTLE_USBAT_H
-#define _USB_SHUTTLE_USBAT_H
-
-/* Supported device types */
-#define USBAT_DEV_HP8200	0x01
-#define USBAT_DEV_FLASH		0x02
-
-#define USBAT_EPP_PORT		0x10
-#define USBAT_EPP_REGISTER	0x30
-#define USBAT_ATA		0x40
-#define USBAT_ISA		0x50
-
-/* Commands (need to be logically OR'd with an access type */
-#define USBAT_CMD_READ_REG		0x00
-#define USBAT_CMD_WRITE_REG		0x01
-#define USBAT_CMD_READ_BLOCK	0x02
-#define USBAT_CMD_WRITE_BLOCK	0x03
-#define USBAT_CMD_COND_READ_BLOCK	0x04
-#define USBAT_CMD_COND_WRITE_BLOCK	0x05
-#define USBAT_CMD_WRITE_REGS	0x07
-
-/* Commands (these don't need an access type) */
-#define USBAT_CMD_EXEC_CMD	0x80
-#define USBAT_CMD_SET_FEAT	0x81
-#define USBAT_CMD_UIO		0x82
-
-/* Methods of accessing UIO register */
-#define USBAT_UIO_READ	1
-#define USBAT_UIO_WRITE	0
-
-/* Qualifier bits */
-#define USBAT_QUAL_FCQ	0x20	/* full compare */
-#define USBAT_QUAL_ALQ	0x10	/* auto load subcount */
-
-/* USBAT Flash Media status types */
-#define USBAT_FLASH_MEDIA_NONE	0
-#define USBAT_FLASH_MEDIA_CF	1
-
-/* USBAT Flash Media change types */
-#define USBAT_FLASH_MEDIA_SAME	0
-#define USBAT_FLASH_MEDIA_CHANGED	1
-
-/* USBAT ATA registers */
-#define USBAT_ATA_DATA      0x10  /* read/write data (R/W) */
-#define USBAT_ATA_FEATURES  0x11  /* set features (W) */
-#define USBAT_ATA_ERROR     0x11  /* error (R) */
-#define USBAT_ATA_SECCNT    0x12  /* sector count (R/W) */
-#define USBAT_ATA_SECNUM    0x13  /* sector number (R/W) */
-#define USBAT_ATA_LBA_ME    0x14  /* cylinder low (R/W) */
-#define USBAT_ATA_LBA_HI    0x15  /* cylinder high (R/W) */
-#define USBAT_ATA_DEVICE    0x16  /* head/device selection (R/W) */
-#define USBAT_ATA_STATUS    0x17  /* device status (R) */
-#define USBAT_ATA_CMD       0x17  /* device command (W) */
-#define USBAT_ATA_ALTSTATUS 0x0E  /* status (no clear IRQ) (R) */
-
-/* USBAT User I/O Data registers */
-#define USBAT_UIO_EPAD		0x80 /* Enable Peripheral Control Signals */
-#define USBAT_UIO_CDT		0x40 /* Card Detect (Read Only) */
-				     /* CDT = ACKD & !UI1 & !UI0 */
-#define USBAT_UIO_1		0x20 /* I/O 1 */
-#define USBAT_UIO_0		0x10 /* I/O 0 */
-#define USBAT_UIO_EPP_ATA	0x08 /* 1=EPP mode, 0=ATA mode */
-#define USBAT_UIO_UI1		0x04 /* Input 1 */
-#define USBAT_UIO_UI0		0x02 /* Input 0 */
-#define USBAT_UIO_INTR_ACK	0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */
-
-/* USBAT User I/O Enable registers */
-#define USBAT_UIO_DRVRST	0x80 /* Reset Peripheral */
-#define USBAT_UIO_ACKD		0x40 /* Enable Card Detect */
-#define USBAT_UIO_OE1		0x20 /* I/O 1 set=output/clr=input */
-				     /* If ACKD=1, set OE1 to 1 also. */
-#define USBAT_UIO_OE0		0x10 /* I/O 0 set=output/clr=input */
-#define USBAT_UIO_ADPRST	0x01 /* Reset SCM chip */
-
-/* USBAT Features */
-#define USBAT_FEAT_ETEN	0x80	/* External trigger enable */
-#define USBAT_FEAT_U1	0x08
-#define USBAT_FEAT_U0	0x04
-#define USBAT_FEAT_ET1	0x02
-#define USBAT_FEAT_ET2	0x01
-
-extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us);
-extern int init_usbat_cd(struct us_data *us);
-extern int init_usbat_flash(struct us_data *us);
-extern int init_usbat_probe(struct us_data *us);
-
-struct usbat_info {
-	int devicetype;
-
-	/* Used for Flash readers only */
-	unsigned long sectors;     /* total sector count */
-	unsigned long ssize;       /* sector size in bytes */
-
-	unsigned char sense_key;
-	unsigned long sense_asc;   /* additional sense code */
-	unsigned long sense_ascq;  /* additional sense code qualifier */
-};
-
-#endif
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index fb65d221..d48c855 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -220,6 +220,7 @@
 		status = us->current_urb->actual_length;
 	return status;
 }
+EXPORT_SYMBOL_GPL(usb_stor_control_msg);
 
 /* This is a version of usb_clear_halt() that allows early termination and
  * doesn't read the status from the device -- this is because some devices
@@ -254,6 +255,7 @@
 	US_DEBUGP("%s: result = %d\n", __func__, result);
 	return result;
 }
+EXPORT_SYMBOL_GPL(usb_stor_clear_halt);
 
 
 /*
@@ -352,6 +354,7 @@
 	return interpret_urb_result(us, pipe, size, result,
 			us->current_urb->actual_length);
 }
+EXPORT_SYMBOL_GPL(usb_stor_ctrl_transfer);
 
 /*
  * Receive one interrupt buffer, without timeouts, but allowing early
@@ -407,6 +410,7 @@
 	return interpret_urb_result(us, pipe, length, result, 
 			us->current_urb->actual_length);
 }
+EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_buf);
 
 /*
  * Transfer a scatter-gather list via bulk transfer
@@ -474,6 +478,7 @@
 	scsi_set_resid(srb, scsi_bufflen(srb) - partial);
 	return result;
 }
+EXPORT_SYMBOL_GPL(usb_stor_bulk_srb);
 
 /*
  * Transfer an entire SCSI command's worth of data payload over the bulk
@@ -509,6 +514,7 @@
 		*residual = length_left;
 	return result;
 }
+EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_sg);
 
 /***********************************************************************
  * Transport routines
@@ -940,6 +946,7 @@
 		usb_stor_clear_halt(us, pipe);
 	return USB_STOR_TRANSPORT_FAILED;
 }
+EXPORT_SYMBOL_GPL(usb_stor_CB_transport);
 
 /*
  * Bulk only transport
@@ -1156,6 +1163,7 @@
 	/* we should never get here, but if we do, we're in trouble */
 	return USB_STOR_TRANSPORT_ERROR;
 }
+EXPORT_SYMBOL_GPL(usb_stor_Bulk_transport);
 
 /***********************************************************************
  * Reset routines
@@ -1230,6 +1238,7 @@
 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 				 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE);
 }
+EXPORT_SYMBOL_GPL(usb_stor_CB_reset);
 
 /* This issues a Bulk-only Reset to the device in question, including
  * clearing the subsequent endpoint halts that may occur.
@@ -1242,6 +1251,7 @@
 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 				 0, us->ifnum, NULL, 0);
 }
+EXPORT_SYMBOL_GPL(usb_stor_Bulk_reset);
 
 /* Issue a USB port reset to the device.  The caller must not hold
  * us->dev_mutex.
diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/unusual_alauda.h
similarity index 60%
copy from drivers/usb/storage/cypress_atacb.h
copy to drivers/usb/storage/unusual_alauda.h
index fbada89..8c412f8 100644
--- a/drivers/usb/storage/cypress_atacb.h
+++ b/drivers/usb/storage/unusual_alauda.h
@@ -1,8 +1,4 @@
-/*
- * 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@free.fr)
+/* Unusual Devices File for the Alauda-based card readers
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -19,7 +15,17 @@
  * 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
+#if defined(CONFIG_USB_STORAGE_ALAUDA) || \
+		defined(CONFIG_USB_STORAGE_ALAUDA_MODULE)
+
+UNUSUAL_DEV(  0x0584, 0x0008, 0x0102, 0x0102,
+		"Fujifilm",
+		"DPC-R1 (Alauda)",
+		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0),
+
+UNUSUAL_DEV(  0x07b4, 0x010a, 0x0102, 0x0102,
+		"Olympus",
+		"MAUSB-10 (Alauda)",
+		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0),
+
+#endif /* defined(CONFIG_USB_STORAGE_ALAUDA) || ... */
diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h
new file mode 100644
index 0000000..44be6d7
--- /dev/null
+++ b/drivers/usb/storage/unusual_cypress.h
@@ -0,0 +1,34 @@
+/* Unusual Devices File for devices based on the Cypress USB/ATA bridge
+ *	with support for ATACB
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || \
+		defined(CONFIG_USB_STORAGE_CYPRESS_ATACB_MODULE)
+
+/* CY7C68300 : support atacb */
+UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
+		"Cypress",
+		"Cypress AT2LP",
+		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
+
+/* CY7C68310 : support atacb and atacb2 */
+UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x9999,
+		"Cypress",
+		"Cypress ISD-300LP",
+		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
+
+#endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */
diff --git a/drivers/usb/storage/unusual_datafab.h b/drivers/usb/storage/unusual_datafab.h
new file mode 100644
index 0000000..c9298ce
--- /dev/null
+++ b/drivers/usb/storage/unusual_datafab.h
@@ -0,0 +1,98 @@
+/* Unusual Devices File for the Datafab USB Compact Flash reader
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(CONFIG_USB_STORAGE_DATAFAB) || \
+		defined(CONFIG_USB_STORAGE_DATAFAB_MODULE)
+
+UNUSUAL_DEV(  0x07c4, 0xa000, 0x0000, 0x0015,
+		"Datafab",
+		"MDCFE-B USB CF Reader",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		0),
+
+/*
+ * The following Datafab-based devices may or may not work
+ * using the current driver...the 0xffff is arbitrary since I
+ * don't know what device versions exist for these guys.
+ *
+ * The 0xa003 and 0xa004 devices in particular I'm curious about.
+ * I'm told they exist but so far nobody has come forward to say that
+ * they work with this driver.  Given the success we've had getting
+ * other Datafab-based cards operational with this driver, I've decided
+ * to leave these two devices in the list.
+ */
+UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
+		"SIIG/Datafab",
+		"SIIG/Datafab Memory Stick+CF Reader/Writer",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		0),
+
+/* Reported by Josef Reisinger <josef.reisinger@netcologne.de> */
+UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff,
+		"Datafab/Unknown",
+		"MD2/MD3 Disk enclosure",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		US_FL_SINGLE_LUN),
+
+UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
+		"Datafab/Unknown",
+		"Datafab-based Reader",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		0),
+
+UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
+		"Datafab/Unknown",
+		"Datafab-based Reader",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		0),
+
+UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
+		"PNY/Datafab",
+		"PNY/Datafab CF+SM Reader",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		0),
+
+UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
+		"Simple Tech/Datafab",
+		"Simple Tech/Datafab CF+SM Reader",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		0),
+
+/* Submitted by Olaf Hering <olh@suse.de> */
+UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
+		"Datafab Systems, Inc.",
+		"USB to CF + SM Combo (LC1)",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		0),
+
+/* Reported by Felix Moeller <felix@derklecks.de>
+ * in Germany this is sold by Hama with the productnumber 46952
+ * as "DualSlot CompactFlash(TM) & MStick Drive USB"
+ */
+UNUSUAL_DEV(  0x07c4, 0xa10b, 0x0000, 0xffff,
+		"DataFab Systems Inc.",
+		"USB CF+MS",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		0),
+
+UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
+		"Acomdata",
+		"CF",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		US_FL_SINGLE_LUN),
+
+#endif /* defined(CONFIG_USB_STORAGE_DATAFAB) || ... */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 6f59c8e..1c1f643 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -53,6 +53,11 @@
  * as opposed to devices that do something strangely or wrongly.
  */
 
+#if !defined(CONFIG_USB_STORAGE_SDDR09) && \
+		!defined(CONFIG_USB_STORAGE_SDDR09_MODULE)
+#define NO_SDDR09
+#endif
+
 /* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr>
  */
 UNUSUAL_DEV(  0x03eb, 0x2002, 0x0100, 0x0100,
@@ -80,18 +85,6 @@
 		"CD-Writer+",
 		US_SC_8070, US_PR_CB, NULL, 0),
 
-#ifdef CONFIG_USB_STORAGE_USBAT
-UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001,
-		"HP",
-		"CD-Writer+ 8200e",
-		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
-
-UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001,
-		"HP",
-		"CD-Writer+ CD-4e",
-		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
-#endif
-
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV(  0x03f0, 0x070c, 0x0000, 0x0000,
 		"HP",
@@ -226,7 +219,7 @@
 		US_FL_MAX_SECTORS_64 ),
 
 /* Reported by Manuel Osdoba <manuel.osdoba@tu-ilmenau.de> */
-UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x0452,
+UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x9999,
 		"Nokia",
 		"Nokia 6233",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -246,12 +239,7 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
-#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
-		"Microtech",
-		"CameraMate (DPCM_USB)",
- 		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
-#else
+#ifdef NO_SDDR09
 UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate",
@@ -288,13 +276,6 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_NOT_LOCKABLE ),
 
-#ifdef CONFIG_USB_STORAGE_KARMA
-UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
-		"Rio",
-		"Rio Karma",
-		US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
-#endif
-
 /* Reported by Tamas Kerecsen <kerecsen@bigfoot.com>
  * Obviously the PROM has not been customized by the VAR;
  * the Vendor and Product string descriptors are:
@@ -375,22 +356,6 @@
 		US_SC_DEVICE, US_PR_CB, NULL,
 		US_FL_MAX_SECTORS_MIN),
 
-#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
-/* CY7C68300 : support atacb */
-UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
-		"Cypress",
-		"Cypress AT2LP",
-		US_SC_CYP_ATACB, US_PR_DEVICE, NULL,
-		0),
-
-/* CY7C68310 : support atacb and atacb2 */
-UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x9999,
-		"Cypress",
-		"Cypress ISD-300LP",
-		US_SC_CYP_ATACB, US_PR_DEVICE, NULL,
-		0),
-#endif
-
 /* Reported by Simon Levitt <simon@whattf.com>
  * This entry needs Sub and Proto fields */
 UNUSUAL_DEV(  0x04b8, 0x0601, 0x0100, 0x0100,
@@ -467,20 +432,7 @@
 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, 
 		US_FL_SCM_MULT_TARG ),
 
-#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999,
-		"Sandisk",
-		"ImageMate SDDR09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
-		0),
-
-/* This entry is from Andries.Brouwer@cwi.nl */
-UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
-		"SCM Microsystems",
-		"eUSB SmartMedia / CompactFlash Adapter",
-		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
-		0),
-#else
+#ifdef NO_SDDR09
 UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
 		"SCM Microsystems",
 		"eUSB CompactFlash Adapter",
@@ -535,14 +487,6 @@
 		"CD-RW Device",
 		US_SC_8020, US_PR_CB, NULL, 0),
 
-#ifdef CONFIG_USB_STORAGE_USBAT
-UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
-		"Shuttle/SCM",
-		"USBAT-02",
-		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
-		US_FL_SINGLE_LUN),
-#endif
-
 /* Reported by Dmitry Khlystov <adminimus@gmail.com> */
 UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,
 		"Samsung",
@@ -645,14 +589,6 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
-#ifdef CONFIG_USB_STORAGE_ISD200
-UNUSUAL_DEV(  0x054c, 0x002b, 0x0100, 0x0110,
-		"Sony",
-		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
-		0 ),
-#endif
-
 /* Submitted by Olaf Hering, <olh@suse.de> SuSE Bugzilla #49049 */
 UNUSUAL_DEV(  0x054c, 0x002c, 0x0501, 0x2000,
 		"Sony",
@@ -749,13 +685,6 @@
 		"Silicon Media R/W",
 		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
 
-#ifdef CONFIG_USB_STORAGE_ALAUDA
-UNUSUAL_DEV(  0x0584, 0x0008, 0x0102, 0x0102,
-		"Fujifilm",
-		"DPC-R1 (Alauda)",
- 		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
-#endif
-
 /* Reported by RTE <raszilki@yandex.ru> */
 UNUSUAL_DEV(  0x058f, 0x6387, 0x0141, 0x0141,
 		"JetFlash",
@@ -798,32 +727,6 @@
 		US_SC_SCSI, US_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
-#ifdef CONFIG_USB_STORAGE_ISD200
-UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
-		"In-System",
-		"USB/IDE Bridge (ATA/ATAPI)",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
-		0 ),
-
-UNUSUAL_DEV(  0x05ab, 0x0301, 0x0100, 0x0110,
-		"In-System",
-		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
-		0 ),
-
-UNUSUAL_DEV(  0x05ab, 0x0351, 0x0100, 0x0110,
-		"In-System",
-		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
-		0 ),
-
-UNUSUAL_DEV(  0x05ab, 0x5701, 0x0100, 0x0110,
-		"In-System",
-		"USB Storage Adapter V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
-		0 ),
-#endif
-
 /* Submitted by Sven Anderson <sven-linux@anderson.de>
  * There are at least four ProductIDs used for iPods, so I added 0x1202 and
  * 0x1204. They just need the US_FL_FIX_CAPACITY. As the bcdDevice appears
@@ -877,14 +780,6 @@
 		US_SC_DEVICE, US_PR_DEVICE, option_ms_init,
 		0),
 
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
-		"Lexar",
-		"Jumpshot USB CF Reader",
-		US_SC_SCSI, US_PR_JUMPSHOT, NULL,
-		US_FL_NEED_OVERRIDE ),
-#endif
-
 /* Reported by Blake Matheny <bmatheny@purdue.edu> */
 UNUSUAL_DEV(  0x05dc, 0xb002, 0x0000, 0x0113,
 		"Lexar",
@@ -935,14 +830,6 @@
 		"Floppy Drive",
 		US_SC_UFI, US_PR_CB, NULL, 0 ),
 
-#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100,
-		"Olympus",
-		"Camedia MAUSB-2",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
-		0),
-#endif
-
 /* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */
 UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
 		"SigmaTel",
@@ -951,7 +838,9 @@
 		US_FL_FIX_CAPACITY ),
 
 /* Reported by Richard -=[]=- <micro_flyer@hotmail.com> */
-UNUSUAL_DEV( 0x067b, 0x2507, 0x0100, 0x0100,
+/* Change to bcdDeviceMin (0x0100 to 0x0001) reported by
+ * Thomas Bartosik <tbartdev@gmx-topmail.de> */
+UNUSUAL_DEV( 0x067b, 0x2507, 0x0001, 0x0100,
 		"Prolific Technology Inc.",
 		"Mass Storage Device",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -1041,35 +930,12 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
-#ifdef CONFIG_USB_STORAGE_USBAT
-UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
-		"Sandisk",
-		"ImageMate SDDR-05b",
-		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
-		US_FL_SINGLE_LUN ),
-#endif
-
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
 		"Sandisk",
 		"ImageMate SDDR-12",
 		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
-#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999,
-		"Sandisk",
-		"ImageMate SDDR-09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
-		0),
-#endif
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
-UNUSUAL_DEV(  0x07ab, 0xfc01, 0x0000, 0x9999,
-		"Freecom",
-		"USB-IDE",
-		US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
-#endif
-
 /* Reported by Eero Volotinen <eero@ping-viini.org> */
 UNUSUAL_DEV(  0x07ab, 0xfccd, 0x0000, 0x9999,
 		"Freecom Technologies",
@@ -1089,12 +955,7 @@
 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ),
 
-#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
-		"Microtech",
-		"CameraMate (DPCM_USB)",
- 		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
-#else
+#ifdef NO_SDDR09
 UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate",
@@ -1102,108 +963,6 @@
 		US_FL_SINGLE_LUN ),
 #endif
 
-#ifdef CONFIG_USB_STORAGE_ALAUDA
-UNUSUAL_DEV(  0x07b4, 0x010a, 0x0102, 0x0102,
-		"Olympus",
-		"MAUSB-10 (Alauda)",
- 		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-UNUSUAL_DEV(  0x07c4, 0xa000, 0x0000, 0x0015,
-		"Datafab",
-		"MDCFE-B USB CF Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		0 ),
-
-/*
- * The following Datafab-based devices may or may not work
- * using the current driver...the 0xffff is arbitrary since I
- * don't know what device versions exist for these guys.
- *
- * The 0xa003 and 0xa004 devices in particular I'm curious about.
- * I'm told they exist but so far nobody has come forward to say that
- * they work with this driver.  Given the success we've had getting
- * other Datafab-based cards operational with this driver, I've decided
- * to leave these two devices in the list.
- */
-UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
-		"SIIG/Datafab",
-		"SIIG/Datafab Memory Stick+CF Reader/Writer",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		0 ),
-
-/* Reported by Josef Reisinger <josef.reisinger@netcologne.de> */
-UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff,
-		"Datafab/Unknown",
-		"MD2/MD3 Disk enclosure",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_SINGLE_LUN ),
-
-UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
-		"Datafab/Unknown",
-		"Datafab-based Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		0 ),
-
-UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
-		"Datafab/Unknown",
-		"Datafab-based Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		0 ),
-
-UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
-		"PNY/Datafab",
-		"PNY/Datafab CF+SM Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		0 ),
-
-UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
-		"Simple Tech/Datafab",
-		"Simple Tech/Datafab CF+SM Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		0 ),
-#endif
-		
-#ifdef CONFIG_USB_STORAGE_SDDR55
-/* Contributed by Peter Waechtler */
-UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
-		"Datafab",
-		"MDSM-B reader",
-		US_SC_SCSI, US_PR_SDDR55, NULL,
-		US_FL_FIX_INQUIRY ),
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-/* Submitted by Olaf Hering <olh@suse.de> */
-UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
-		"Datafab Systems, Inc.",
-		"USB to CF + SM Combo (LC1)",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		0 ),
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR55
-/* SM part - aeb <Andries.Brouwer@cwi.nl> */
-UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
-		"Datafab Systems, Inc.",
-		"USB to CF + SM Combo (LC1)",
-		US_SC_SCSI, US_PR_SDDR55, NULL,
-		US_FL_SINGLE_LUN ),
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-/* Reported by Felix Moeller <felix@derklecks.de>
- * in Germany this is sold by Hama with the productnumber 46952
- * as "DualSlot CompactFlash(TM) & MStick Drive USB"
- */
-UNUSUAL_DEV(  0x07c4, 0xa10b, 0x0000, 0xffff,
-		"DataFab Systems Inc.",
-		"USB CF+MS",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		0 ),
-
-#endif
-
 /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100
  * Only revision 1.13 tested (same for all of the above devices,
  * based on the Datafab DF-UG-07 chip).  Needed for US_FL_FIX_INQUIRY.
@@ -1390,6 +1149,16 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		0 ),
 
+/* Reported by Jan Dumon <j.dumon@option.com>
+ * This device (wrongly) has a vendor-specific device descriptor.
+ * The entry is needed so usb-storage can bind to it's mass-storage
+ * interface as an interface driver */
+UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000,
+		"Option",
+		"GI 0431 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
 		"Seagate",
@@ -1397,29 +1166,6 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE ),
 
-#ifdef CONFIG_USB_STORAGE_ISD200
-UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
-		"ATI",
-		"USB Cable 205",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
-		0 ),
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
-		"Acomdata",
-		"CF",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_SINGLE_LUN ),
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR55
-UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
-		"Acomdata",
-		"SM",
-		US_SC_SCSI, US_PR_SDDR55, NULL,
-		US_FL_SINGLE_LUN ),
-#endif
-
 UNUSUAL_DEV(  0x0d49, 0x7310, 0x0000, 0x9999,
 		"Maxtor",
 		"USB to SATA",
@@ -1436,23 +1182,6 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
-/* Submitted by: Nick Sillik <n.sillik@temple.edu>
- * Needed for OneTouch extension to usb-storage
- *
- */
-#ifdef CONFIG_USB_STORAGE_ONETOUCH
-	UNUSUAL_DEV(  0x0d49, 0x7000, 0x0000, 0x9999,
-			"Maxtor",
-			"OneTouch External Harddrive",
-			US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
-			0),
-	UNUSUAL_DEV(  0x0d49, 0x7010, 0x0000, 0x9999,
-			"Maxtor",
-			"OneTouch External Harddrive",
-			US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
-			0),
-#endif
-
 /* Submitted by Joris Struyve <joris@struyve.be> */
 UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
 		"Medion",
@@ -2105,14 +1834,6 @@
 		"Micro Mini 1GB",
 		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
 
-#ifdef CONFIG_USB_STORAGE_SDDR55
-UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999, 
-		"Sandisk",
-		"ImageMate SDDR55",
-		US_SC_SCSI, US_PR_SDDR55, NULL,
-		US_FL_SINGLE_LUN),
-#endif
-
 /* Reported by Andrew Simmons <andrew.simmons@gmail.com> */
 UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
 		"DataStor",
diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/unusual_freecom.h
similarity index 67%
copy from drivers/usb/storage/cypress_atacb.h
copy to drivers/usb/storage/unusual_freecom.h
index fbada89..3758679 100644
--- a/drivers/usb/storage/cypress_atacb.h
+++ b/drivers/usb/storage/unusual_freecom.h
@@ -1,8 +1,4 @@
-/*
- * 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@free.fr)
+/* Unusual Devices File for the Freecom USB/IDE adaptor
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -19,7 +15,12 @@
  * 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
+#if defined(CONFIG_USB_STORAGE_FREECOM) || \
+		defined(CONFIG_USB_STORAGE_FREECOM_MODULE)
+
+UNUSUAL_DEV(  0x07ab, 0xfc01, 0x0000, 0x9999,
+		"Freecom",
+		"USB-IDE",
+		US_SC_QIC, US_PR_FREECOM, init_freecom, 0),
+
+#endif /* defined(CONFIG_USB_STORAGE_FREECOM) || ... */
diff --git a/drivers/usb/storage/unusual_isd200.h b/drivers/usb/storage/unusual_isd200.h
new file mode 100644
index 0000000..0d99dde
--- /dev/null
+++ b/drivers/usb/storage/unusual_isd200.h
@@ -0,0 +1,57 @@
+/* Unusual Devices File for In-System Design, Inc. ISD200 ASIC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(CONFIG_USB_STORAGE_ISD200) || \
+		defined(CONFIG_USB_STORAGE_ISD200_MODULE)
+
+UNUSUAL_DEV(  0x054c, 0x002b, 0x0100, 0x0110,
+		"Sony",
+		"Portable USB Harddrive V2",
+		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		0),
+
+UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
+		"In-System",
+		"USB/IDE Bridge (ATA/ATAPI)",
+		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		0),
+
+UNUSUAL_DEV(  0x05ab, 0x0301, 0x0100, 0x0110,
+		"In-System",
+		"Portable USB Harddrive V2",
+		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		0),
+
+UNUSUAL_DEV(  0x05ab, 0x0351, 0x0100, 0x0110,
+		"In-System",
+		"Portable USB Harddrive V2",
+		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		0),
+
+UNUSUAL_DEV(  0x05ab, 0x5701, 0x0100, 0x0110,
+		"In-System",
+		"USB Storage Adapter V2",
+		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		0),
+
+UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
+		"ATI",
+		"USB Cable 205",
+		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		0),
+
+#endif /* defined(CONFIG_USB_STORAGE_ISD200) || ... */
diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/unusual_jumpshot.h
similarity index 65%
copy from drivers/usb/storage/cypress_atacb.h
copy to drivers/usb/storage/unusual_jumpshot.h
index fbada89..2e549b1 100644
--- a/drivers/usb/storage/cypress_atacb.h
+++ b/drivers/usb/storage/unusual_jumpshot.h
@@ -1,8 +1,4 @@
-/*
- * 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@free.fr)
+/* Unusual Devices File for the Lexar "Jumpshot" Compact Flash reader
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -19,7 +15,13 @@
  * 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
+#if defined(CONFIG_USB_STORAGE_JUMPSHOT) || \
+		defined(CONFIG_USB_STORAGE_JUMPSHOT_MODULE)
+
+UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
+		"Lexar",
+		"Jumpshot USB CF Reader",
+		US_SC_SCSI, US_PR_JUMPSHOT, NULL,
+		US_FL_NEED_OVERRIDE),
+
+#endif /* defined(CONFIG_USB_STORAGE_JUMPSHOT) || ... */
diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/unusual_karma.h
similarity index 67%
rename from drivers/usb/storage/cypress_atacb.h
rename to drivers/usb/storage/unusual_karma.h
index fbada89..12ae3a0 100644
--- a/drivers/usb/storage/cypress_atacb.h
+++ b/drivers/usb/storage/unusual_karma.h
@@ -1,8 +1,4 @@
-/*
- * 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@free.fr)
+/* Unusual Devices File for the Rio Karma
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -19,7 +15,12 @@
  * 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
+#if defined(CONFIG_USB_STORAGE_KARMA) || \
+		defined(CONFIG_USB_STORAGE_KARMA_MODULE)
+
+UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
+		"Rio",
+		"Rio Karma",
+		US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
+
+#endif /* defined(CONFIG_USB_STORAGE_KARMA) || ... */
diff --git a/drivers/usb/storage/unusual_onetouch.h b/drivers/usb/storage/unusual_onetouch.h
new file mode 100644
index 0000000..bd9306b
--- /dev/null
+++ b/drivers/usb/storage/unusual_onetouch.h
@@ -0,0 +1,36 @@
+/* Unusual Devices File for the Maxtor OneTouch USB hard drive's button
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(CONFIG_USB_STORAGE_ONETOUCH) || \
+		defined(CONFIG_USB_STORAGE_ONETOUCH_MODULE)
+
+/* Submitted by: Nick Sillik <n.sillik@temple.edu>
+ * Needed for OneTouch extension to usb-storage
+ */
+UNUSUAL_DEV(  0x0d49, 0x7000, 0x0000, 0x9999,
+		"Maxtor",
+		"OneTouch External Harddrive",
+		US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+		0),
+
+UNUSUAL_DEV(  0x0d49, 0x7010, 0x0000, 0x9999,
+		"Maxtor",
+		"OneTouch External Harddrive",
+		US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+		0),
+
+#endif /* defined(CONFIG_USB_STORAGE_ONETOUCH) || ... */
diff --git a/drivers/usb/storage/unusual_sddr09.h b/drivers/usb/storage/unusual_sddr09.h
new file mode 100644
index 0000000..50cab51
--- /dev/null
+++ b/drivers/usb/storage/unusual_sddr09.h
@@ -0,0 +1,56 @@
+/* Unusual Devices File for SanDisk SDDR-09 SmartMedia reader
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(CONFIG_USB_STORAGE_SDDR09) || \
+		defined(CONFIG_USB_STORAGE_SDDR09_MODULE)
+
+UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
+		"Microtech",
+		"CameraMate (DPCM_USB)",
+		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0),
+
+UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999,
+		"Sandisk",
+		"ImageMate SDDR09",
+		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		0),
+
+/* This entry is from Andries.Brouwer@cwi.nl */
+UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
+		"SCM Microsystems",
+		"eUSB SmartMedia / CompactFlash Adapter",
+		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
+		0),
+
+UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100,
+		"Olympus",
+		"Camedia MAUSB-2",
+		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		0),
+
+UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999,
+		"Sandisk",
+		"ImageMate SDDR-09",
+		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		0),
+
+UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
+		"Microtech",
+		"CameraMate (DPCM_USB)",
+		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0),
+
+#endif /* defined(CONFIG_USB_STORAGE_SDDR09) || ... */
diff --git a/drivers/usb/storage/unusual_sddr55.h b/drivers/usb/storage/unusual_sddr55.h
new file mode 100644
index 0000000..ae81ef7
--- /dev/null
+++ b/drivers/usb/storage/unusual_sddr55.h
@@ -0,0 +1,44 @@
+/* Unusual Devices File for SanDisk SDDR-55 SmartMedia reader
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(CONFIG_USB_STORAGE_SDDR55) || \
+		defined(CONFIG_USB_STORAGE_SDDR55_MODULE)
+
+/* Contributed by Peter Waechtler */
+UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
+		"Datafab",
+		"MDSM-B reader",
+		US_SC_SCSI, US_PR_SDDR55, NULL,
+		US_FL_FIX_INQUIRY),
+
+/* SM part - aeb <Andries.Brouwer@cwi.nl> */
+UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
+		"Datafab Systems, Inc.",
+		"USB to CF + SM Combo (LC1)",
+		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
+
+UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
+		"Acomdata",
+		"SM",
+		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
+
+UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999,
+		"Sandisk",
+		"ImageMate SDDR55",
+		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
+
+#endif /* defined(CONFIG_USB_STORAGE_SDDR55) || ... */
diff --git a/drivers/usb/storage/unusual_usbat.h b/drivers/usb/storage/unusual_usbat.h
new file mode 100644
index 0000000..80e869f
--- /dev/null
+++ b/drivers/usb/storage/unusual_usbat.h
@@ -0,0 +1,43 @@
+/* Unusual Devices File for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(CONFIG_USB_STORAGE_USBAT) || \
+		defined(CONFIG_USB_STORAGE_USBAT_MODULE)
+
+UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001,
+		"HP",
+		"CD-Writer+ 8200e",
+		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+
+UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001,
+		"HP",
+		"CD-Writer+ CD-4e",
+		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+
+UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
+		"Shuttle/SCM",
+		"USBAT-02",
+		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+		US_FL_SINGLE_LUN),
+
+UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
+		"Sandisk",
+		"ImageMate SDDR-05b",
+		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+		US_FL_SINGLE_LUN),
+
+#endif /* defined(CONFIG_USB_STORAGE_USBAT) || ... */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 4becf49..8060b85 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -5,7 +5,7 @@
  *
  * Developed with the assistance of:
  *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
- *   (c) 2003 Alan Stern (stern@rowland.harvard.edu)
+ *   (c) 2003-2009 Alan Stern (stern@rowland.harvard.edu)
  *
  * Initial work by:
  *   (c) 1999 Michael Gee (michael@linuxspecific.com)
@@ -66,39 +66,6 @@
 #include "debug.h"
 #include "initializers.h"
 
-#ifdef CONFIG_USB_STORAGE_USBAT
-#include "shuttle_usbat.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR09
-#include "sddr09.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR55
-#include "sddr55.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_FREECOM
-#include "freecom.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_ISD200
-#include "isd200.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-#include "datafab.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-#include "jumpshot.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_ONETOUCH
-#include "onetouch.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_ALAUDA
-#include "alauda.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_KARMA
-#include "karma.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
-#include "cypress_atacb.h"
-#endif
 #include "sierra_ms.h"
 #include "option_ms.h"
 
@@ -118,36 +85,8 @@
 
 /*
  * The entries in this table correspond, line for line,
- * with the entries of us_unusual_dev_list[].
+ * with the entries in usb_storage_usb_ids[], defined in usual-tables.c.
  */
-#ifndef CONFIG_USB_LIBUSUAL
-
-#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
-		    vendorName, productName,useProtocol, useTransport, \
-		    initFunction, flags) \
-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
-  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
-
-#define COMPLIANT_DEV	UNUSUAL_DEV
-
-#define USUAL_DEV(useProto, useTrans, useType) \
-{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
-  .driver_info = (USB_US_TYPE_STOR<<24) }
-
-static struct usb_device_id storage_usb_ids [] = {
-
-#	include "unusual_devs.h"
-#undef UNUSUAL_DEV
-#undef COMPLIANT_DEV
-#undef USUAL_DEV
-	/* Terminating entry */
-	{ }
-};
-
-MODULE_DEVICE_TABLE (usb, storage_usb_ids);
-#endif /* CONFIG_USB_LIBUSUAL */
-
-/* This is the list of devices we recognize, along with their flag data */
 
 /* The vendor name should be kept at eight characters or less, and
  * the product name should be kept at 16 characters or less. If a device
@@ -179,18 +118,17 @@
 
 static struct us_unusual_dev us_unusual_dev_list[] = {
 #	include "unusual_devs.h" 
-#	undef UNUSUAL_DEV
-#	undef COMPLIANT_DEV
-#	undef USUAL_DEV
-
-	/* Terminating entry */
-	{ NULL }
+	{ }		/* Terminating entry */
 };
 
+#undef UNUSUAL_DEV
+#undef COMPLIANT_DEV
+#undef USUAL_DEV
+
 
 #ifdef CONFIG_PM	/* Minimal support for suspend and resume */
 
-static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+int usb_stor_suspend(struct usb_interface *iface, pm_message_t message)
 {
 	struct us_data *us = usb_get_intfdata(iface);
 
@@ -207,8 +145,9 @@
 	mutex_unlock(&us->dev_mutex);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_stor_suspend);
 
-static int storage_resume(struct usb_interface *iface)
+int usb_stor_resume(struct usb_interface *iface)
 {
 	struct us_data *us = usb_get_intfdata(iface);
 
@@ -221,8 +160,9 @@
 	mutex_unlock(&us->dev_mutex);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_stor_resume);
 
-static int storage_reset_resume(struct usb_interface *iface)
+int usb_stor_reset_resume(struct usb_interface *iface)
 {
 	struct us_data *us = usb_get_intfdata(iface);
 
@@ -235,6 +175,7 @@
 	 * the device */
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_stor_reset_resume);
 
 #endif /* CONFIG_PM */
 
@@ -243,7 +184,7 @@
  * a USB port reset, whether from this driver or a different one.
  */
 
-static int storage_pre_reset(struct usb_interface *iface)
+int usb_stor_pre_reset(struct usb_interface *iface)
 {
 	struct us_data *us = usb_get_intfdata(iface);
 
@@ -253,8 +194,9 @@
 	mutex_lock(&us->dev_mutex);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_stor_pre_reset);
 
-static int storage_post_reset(struct usb_interface *iface)
+int usb_stor_post_reset(struct usb_interface *iface)
 {
 	struct us_data *us = usb_get_intfdata(iface);
 
@@ -269,6 +211,7 @@
 	mutex_unlock(&us->dev_mutex);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_stor_post_reset);
 
 /*
  * fill_inquiry_response takes an unsigned char array (which must
@@ -311,6 +254,7 @@
 
 	usb_stor_set_xfer_buf(data, data_len, us->srb);
 }
+EXPORT_SYMBOL_GPL(fill_inquiry_response);
 
 static int usb_stor_control_thread(void * __us)
 {
@@ -551,20 +495,13 @@
 			vid, pid, f);
 }
 
-/* Find an unusual_dev descriptor (always succeeds in the current code) */
-static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
-{
-	const int id_index = id - storage_usb_ids;
-	return &us_unusual_dev_list[id_index];
-}
-
 /* Get the unusual_devs entries and the string descriptors */
-static int get_device_info(struct us_data *us, const struct usb_device_id *id)
+static int get_device_info(struct us_data *us, const struct usb_device_id *id,
+		struct us_unusual_dev *unusual_dev)
 {
 	struct usb_device *dev = us->pusb_dev;
 	struct usb_interface_descriptor *idesc =
 		&us->pusb_intf->cur_altsetting->desc;
-	struct us_unusual_dev *unusual_dev = find_unusual(id);
 
 	/* Store the entries */
 	us->unusual_dev = unusual_dev;
@@ -629,7 +566,7 @@
 }
 
 /* Get the transport settings */
-static int get_transport(struct us_data *us)
+static void get_transport(struct us_data *us)
 {
 	switch (us->protocol) {
 	case US_PR_CB:
@@ -651,100 +588,11 @@
 		us->transport = usb_stor_Bulk_transport;
 		us->transport_reset = usb_stor_Bulk_reset;
 		break;
-
-#ifdef CONFIG_USB_STORAGE_USBAT
-	case US_PR_USBAT:
-		us->transport_name = "Shuttle USBAT";
-		us->transport = usbat_transport;
-		us->transport_reset = usb_stor_CB_reset;
-		us->max_lun = 1;
-		break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
-	case US_PR_EUSB_SDDR09:
-		us->transport_name = "EUSB/SDDR09";
-		us->transport = sddr09_transport;
-		us->transport_reset = usb_stor_CB_reset;
-		us->max_lun = 0;
-		break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_SDDR55
-	case US_PR_SDDR55:
-		us->transport_name = "SDDR55";
-		us->transport = sddr55_transport;
-		us->transport_reset = sddr55_reset;
-		us->max_lun = 0;
-		break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DPCM
-	case US_PR_DPCM_USB:
-		us->transport_name = "Control/Bulk-EUSB/SDDR09";
-		us->transport = dpcm_transport;
-		us->transport_reset = usb_stor_CB_reset;
-		us->max_lun = 1;
-		break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
-	case US_PR_FREECOM:
-		us->transport_name = "Freecom";
-		us->transport = freecom_transport;
-		us->transport_reset = usb_stor_freecom_reset;
-		us->max_lun = 0;
-		break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-	case US_PR_DATAFAB:
-		us->transport_name  = "Datafab Bulk-Only";
-		us->transport = datafab_transport;
-		us->transport_reset = usb_stor_Bulk_reset;
-		us->max_lun = 1;
-		break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-	case US_PR_JUMPSHOT:
-		us->transport_name  = "Lexar Jumpshot Control/Bulk";
-		us->transport = jumpshot_transport;
-		us->transport_reset = usb_stor_Bulk_reset;
-		us->max_lun = 1;
-		break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_ALAUDA
-	case US_PR_ALAUDA:
-		us->transport_name  = "Alauda Control/Bulk";
-		us->transport = alauda_transport;
-		us->transport_reset = usb_stor_Bulk_reset;
-		us->max_lun = 1;
-		break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_KARMA
-	case US_PR_KARMA:
-		us->transport_name = "Rio Karma/Bulk";
-		us->transport = rio_karma_transport;
-		us->transport_reset = usb_stor_Bulk_reset;
-		break;
-#endif
-
-	default:
-		return -EIO;
 	}
-	US_DEBUGP("Transport: %s\n", us->transport_name);
-
-	/* fix for single-lun devices */
-	if (us->fflags & US_FL_SINGLE_LUN)
-		us->max_lun = 0;
-	return 0;
 }
 
 /* Get the protocol settings */
-static int get_protocol(struct us_data *us)
+static void get_protocol(struct us_data *us)
 {
 	switch (us->subclass) {
 	case US_SC_RBC:
@@ -779,26 +627,7 @@
 		us->protocol_name = "Uniform Floppy Interface (UFI)";
 		us->proto_handler = usb_stor_ufi_command;
 		break;
-
-#ifdef CONFIG_USB_STORAGE_ISD200
-	case US_SC_ISD200:
-		us->protocol_name = "ISD200 ATA/ATAPI";
-		us->proto_handler = isd200_ata_command;
-		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;
 	}
-	US_DEBUGP("Protocol: %s\n", us->protocol_name);
-	return 0;
 }
 
 /* Get the pipe settings */
@@ -846,12 +675,12 @@
 	us->send_ctrl_pipe = usb_sndctrlpipe(us->pusb_dev, 0);
 	us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
 	us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev,
-		ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+		usb_endpoint_num(ep_out));
 	us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev, 
-		ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+		usb_endpoint_num(ep_in));
 	if (ep_int) {
 		us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev,
-			ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+			usb_endpoint_num(ep_int));
 		us->ep_bInterval = ep_int->bInterval;
 	}
 	return 0;
@@ -1012,17 +841,15 @@
 }
 
 
-/* Probe to see if we can drive a newly-connected USB device */
-static int storage_probe(struct usb_interface *intf,
-			 const struct usb_device_id *id)
+/* First part of general USB mass-storage probing */
+int usb_stor_probe1(struct us_data **pus,
+		struct usb_interface *intf,
+		const struct usb_device_id *id,
+		struct us_unusual_dev *unusual_dev)
 {
 	struct Scsi_Host *host;
 	struct us_data *us;
 	int result;
-	struct task_struct *th;
-
-	if (usb_usual_check_type(id, USB_US_TYPE_STOR))
-		return -ENXIO;
 
 	US_DEBUGP("USB Mass Storage device detected\n");
 
@@ -1041,7 +868,7 @@
 	 * Allow 16-byte CDBs and thus > 2TB
 	 */
 	host->max_cmd_len = 16;
-	us = host_to_us(host);
+	*pus = us = host_to_us(host);
 	memset(us, 0, sizeof(struct us_data));
 	mutex_init(&(us->dev_mutex));
 	init_completion(&us->cmnd_ready);
@@ -1054,24 +881,46 @@
 	if (result)
 		goto BadDevice;
 
-	/*
-	 * Get the unusual_devs entries and the descriptors
-	 *
-	 * id_index is calculated in the declaration to be the index number
-	 * of the match from the usb_device_id table, so we can find the
-	 * corresponding entry in the private table.
-	 */
-	result = get_device_info(us, id);
+	/* Get the unusual_devs entries and the descriptors */
+	result = get_device_info(us, id, unusual_dev);
 	if (result)
 		goto BadDevice;
 
-	/* Get the transport, protocol, and pipe settings */
-	result = get_transport(us);
-	if (result)
+	/* Get standard transport and protocol settings */
+	get_transport(us);
+	get_protocol(us);
+
+	/* Give the caller a chance to fill in specialized transport
+	 * or protocol settings.
+	 */
+	return 0;
+
+BadDevice:
+	US_DEBUGP("storage_probe() failed\n");
+	release_everything(us);
+	return result;
+}
+EXPORT_SYMBOL_GPL(usb_stor_probe1);
+
+/* Second part of general USB mass-storage probing */
+int usb_stor_probe2(struct us_data *us)
+{
+	struct task_struct *th;
+	int result;
+
+	/* Make sure the transport and protocol have both been set */
+	if (!us->transport || !us->proto_handler) {
+		result = -ENXIO;
 		goto BadDevice;
-	result = get_protocol(us);
-	if (result)
-		goto BadDevice;
+	}
+	US_DEBUGP("Transport: %s\n", us->transport_name);
+	US_DEBUGP("Protocol: %s\n", us->protocol_name);
+
+	/* fix for single-lun devices */
+	if (us->fflags & US_FL_SINGLE_LUN)
+		us->max_lun = 0;
+
+	/* Find the endpoints and calculate pipe values */
 	result = get_pipes(us);
 	if (result)
 		goto BadDevice;
@@ -1080,7 +929,7 @@
 	result = usb_stor_acquire_resources(us);
 	if (result)
 		goto BadDevice;
-	result = scsi_add_host(host, &intf->dev);
+	result = scsi_add_host(us_to_host(us), &us->pusb_intf->dev);
 	if (result) {
 		printk(KERN_WARNING USB_STORAGE
 			"Unable to add the scsi host\n");
@@ -1108,9 +957,10 @@
 	release_everything(us);
 	return result;
 }
+EXPORT_SYMBOL_GPL(usb_stor_probe2);
 
-/* Handle a disconnect event from the USB core */
-static void storage_disconnect(struct usb_interface *intf)
+/* Handle a USB mass-storage disconnect */
+void usb_stor_disconnect(struct usb_interface *intf)
 {
 	struct us_data *us = usb_get_intfdata(intf);
 
@@ -1118,6 +968,42 @@
 	quiesce_and_remove_host(us);
 	release_everything(us);
 }
+EXPORT_SYMBOL_GPL(usb_stor_disconnect);
+
+/* The main probe routine for standard devices */
+static int storage_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	/*
+	 * If libusual is configured, let it decide whether a standard
+	 * device should be handled by usb-storage or by ub.
+	 * If the device isn't standard (is handled by a subdriver
+	 * module) then don't accept it.
+	 */
+	if (usb_usual_check_type(id, USB_US_TYPE_STOR) ||
+			usb_usual_ignore_device(intf))
+		return -ENXIO;
+
+	/*
+	 * Call the general probe procedures.
+	 *
+	 * The unusual_dev_list array is parallel to the usb_storage_usb_ids
+	 * table, so we use the index of the id entry to find the
+	 * corresponding unusual_devs entry.
+	 */
+	result = usb_stor_probe1(&us, intf, id,
+			(id - usb_storage_usb_ids) + us_unusual_dev_list);
+	if (result)
+		return result;
+
+	/* No special transport or protocol settings in the main module */
+
+	result = usb_stor_probe2(us);
+	return result;
+}
 
 /***********************************************************************
  * Initialization and registration
@@ -1126,15 +1012,13 @@
 static struct usb_driver usb_storage_driver = {
 	.name =		"usb-storage",
 	.probe =	storage_probe,
-	.disconnect =	storage_disconnect,
-#ifdef CONFIG_PM
-	.suspend =	storage_suspend,
-	.resume =	storage_resume,
-	.reset_resume =	storage_reset_resume,
-#endif
-	.pre_reset =	storage_pre_reset,
-	.post_reset =	storage_post_reset,
-	.id_table =	storage_usb_ids,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	usb_storage_usb_ids,
 	.soft_unbind =	1,
 };
 
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 65e674e..2609efb 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -177,4 +177,25 @@
 #define scsi_unlock(host)	spin_unlock_irq(host->host_lock)
 #define scsi_lock(host)		spin_lock_irq(host->host_lock)
 
+/* General routines provided by the usb-storage standard core */
+#ifdef CONFIG_PM
+extern int usb_stor_suspend(struct usb_interface *iface, pm_message_t message);
+extern int usb_stor_resume(struct usb_interface *iface);
+extern int usb_stor_reset_resume(struct usb_interface *iface);
+#else
+#define usb_stor_suspend	NULL
+#define usb_stor_resume		NULL
+#define usb_stor_reset_resume	NULL
+#endif
+
+extern int usb_stor_pre_reset(struct usb_interface *iface);
+extern int usb_stor_post_reset(struct usb_interface *iface);
+
+extern int usb_stor_probe1(struct us_data **pus,
+		struct usb_interface *intf,
+		const struct usb_device_id *id,
+		struct us_unusual_dev *unusual_dev);
+extern int usb_stor_probe2(struct us_data *us);
+extern void usb_stor_disconnect(struct usb_interface *intf);
+
 #endif
diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
new file mode 100644
index 0000000..468bde7
--- /dev/null
+++ b/drivers/usb/storage/usual-tables.c
@@ -0,0 +1,116 @@
+/* Driver for USB Mass Storage devices
+ * Usual Tables File for usb-storage and libusual
+ *
+ * Copyright (C) 2009 Alan Stern (stern@rowland.harvard.edu)
+ *
+ * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
+ * information about this driver.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb_usual.h>
+
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags) }
+
+#define USUAL_DEV(useProto, useTrans, useType) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+  .driver_info = ((useType)<<24) }
+
+struct usb_device_id usb_storage_usb_ids[] = {
+#	include "unusual_devs.h"
+	{ }		/* Terminating entry */
+};
+EXPORT_SYMBOL_GPL(usb_storage_usb_ids);
+
+MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids);
+
+#undef UNUSUAL_DEV
+#undef COMPLIANT_DEV
+#undef USUAL_DEV
+
+
+/*
+ * The table of devices to ignore
+ */
+struct ignore_entry {
+	u16	vid, pid, bcdmin, bcdmax;
+};
+
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{					\
+	.vid	= id_vendor,		\
+	.pid 	= id_product,		\
+	.bcdmin	= bcdDeviceMin,		\
+	.bcdmax = bcdDeviceMax,		\
+}
+
+static struct ignore_entry ignore_ids[] = {
+#	include "unusual_alauda.h"
+#	include "unusual_cypress.h"
+#	include "unusual_datafab.h"
+#	include "unusual_freecom.h"
+#	include "unusual_isd200.h"
+#	include "unusual_jumpshot.h"
+#	include "unusual_karma.h"
+#	include "unusual_onetouch.h"
+#	include "unusual_sddr09.h"
+#	include "unusual_sddr55.h"
+#	include "unusual_usbat.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+
+/* Return an error if a device is in the ignore_ids list */
+int usb_usual_ignore_device(struct usb_interface *intf)
+{
+	struct usb_device *udev;
+	unsigned vid, pid, bcd;
+	struct ignore_entry *p;
+
+	udev = interface_to_usbdev(intf);
+	vid = le16_to_cpu(udev->descriptor.idVendor);
+	pid = le16_to_cpu(udev->descriptor.idProduct);
+	bcd = le16_to_cpu(udev->descriptor.bcdDevice);
+
+	for (p = ignore_ids; p->vid; ++p) {
+		if (p->vid == vid && p->pid == pid &&
+				p->bcdmin <= bcd && p->bcdmax >= bcd)
+			return -ENXIO;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_usual_ignore_device);
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index be76084..60ba631 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -410,7 +410,9 @@
 	}
 
 	/* let the user know what node this device is now attached to */
-	info("USB Skeleton device now attached to USBSkel-%d", interface->minor);
+	dev_info(&interface->dev,
+		 "USB Skeleton device now attached to USBSkel-%d",
+		 interface->minor);
 	return 0;
 
 error:
@@ -441,7 +443,7 @@
 	/* decrement our usage count */
 	kref_put(&dev->kref, skel_delete);
 
-	info("USB Skeleton #%d now disconnected", minor);
+	dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor);
 }
 
 static void skel_draw_down(struct usb_skel *dev)
diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c
index 1335cbe..25eae40 100644
--- a/drivers/usb/wusbcore/cbaf.c
+++ b/drivers/usb/wusbcore/cbaf.c
@@ -638,8 +638,7 @@
 	usb_put_intf(iface);
 	kfree(cbaf->buffer);
 	/* paranoia: clean up crypto keys */
-	memset(cbaf, 0, sizeof(*cbaf));
-	kfree(cbaf);
+	kzfree(cbaf);
 }
 
 static struct usb_device_id cbaf_id_table[] = {
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index 8e18141..f0aac0c 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -889,6 +889,8 @@
 	if (usb_dev->wusb == 0 || usb_dev->devnum == 1)
 		return;		/* skip non wusb and wusb RHs */
 
+	usb_set_device_state(usb_dev, USB_STATE_UNAUTHENTICATED);
+
 	wusbhc = wusbhc_get_by_usb_dev(usb_dev);
 	if (wusbhc == NULL)
 		goto error_nodev;
diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c
index f4aa28e..8118db7 100644
--- a/drivers/usb/wusbcore/security.c
+++ b/drivers/usb/wusbcore/security.c
@@ -312,6 +312,7 @@
 	result = wusb_set_dev_addr(wusbhc, wusb_dev, 0);
 	if (result < 0)
 		goto error_addr0;
+	usb_set_device_state(usb_dev, USB_STATE_DEFAULT);
 	usb_ep0_reinit(usb_dev);
 
 	/* Set new (authenticated) address. */
@@ -327,6 +328,7 @@
 	result = wusb_set_dev_addr(wusbhc, wusb_dev, new_address);
 	if (result < 0)
 		goto error_addr;
+	usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
 	usb_ep0_reinit(usb_dev);
 	usb_dev->authenticated = 1;
 error_addr:
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 238a96a..613a5fc 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -921,8 +921,10 @@
 	result = -ENODEV;
 	/* FIXME: segmentation broken -- kills DWA */
 	mutex_lock(&wusbhc->mutex);		/* get a WUSB dev */
-	if (urb->dev == NULL)
+	if (urb->dev == NULL) {
+		mutex_unlock(&wusbhc->mutex);
 		goto error_dev_gone;
+	}
 	wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev);
 	if (wusb_dev == NULL) {
 		mutex_unlock(&wusbhc->mutex);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 2181ce4..35e8eb0 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1853,13 +1853,14 @@
  *  Initialisation
  */
 
-#ifdef CONFIG_PPC_PMAC
+#ifdef CONFIG_PPC_PMAC__disabled
 static void aty128_early_resume(void *data)
 {
         struct aty128fb_par *par = data;
 
 	if (try_acquire_console_sem())
 		return;
+	pci_restore_state(par->pdev);
 	aty128_do_resume(par->pdev);
 	release_console_sem();
 }
@@ -1907,7 +1908,14 @@
 		/* Indicate sleep capability */
 		if (par->chip_gen == rage_M3) {
 			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
+#if 0 /* Disable the early video resume hack for now as it's causing problems, among
+       * others we now rely on the PCI core restoring the config space for us, which
+       * isn't the case with that hack, and that code path causes various things to
+       * be called with interrupts off while they shouldn't. I'm leaving the code in
+       * as it can be useful for debugging purposes
+       */
 			pmac_set_early_video_resume(aty128_early_resume, par);
+#endif
 		}
 
 		/* Find default mode */
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index ca5f0dc..c6d7cc7 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2507,6 +2507,25 @@
 
 #endif /* CONFIG_PPC_OF */
 
+static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state)
+{
+	u16 pwr_cmd;
+
+	for (;;) {
+		pci_read_config_word(rinfo->pdev,
+				     rinfo->pm_reg+PCI_PM_CTRL,
+				     &pwr_cmd);
+		if (pwr_cmd & 2)
+			break;
+		pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2;
+		pci_write_config_word(rinfo->pdev,
+				      rinfo->pm_reg+PCI_PM_CTRL,
+				      pwr_cmd);
+		msleep(500);
+	}
+	rinfo->pdev->current_state = state;
+}
+
 static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
 {
 	u32 tmp;
@@ -2558,6 +2577,11 @@
 		/* Switch PCI power management to D2. */
 		pci_disable_device(rinfo->pdev);
 		pci_save_state(rinfo->pdev);
+		/* The chip seems to need us to whack the PM register
+		 * repeatedly until it sticks. We do that -prior- to
+		 * calling pci_set_power_state()
+		 */
+		radeonfb_whack_power_state(rinfo, PCI_D2);
 		pci_set_power_state(rinfo->pdev, PCI_D2);
 	} else {
 		printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
@@ -2762,12 +2786,13 @@
 	return rc;
 }
 
-#ifdef CONFIG_PPC_OF
+#ifdef CONFIG_PPC_OF__disabled
 static void radeonfb_early_resume(void *data)
 {
         struct radeonfb_info *rinfo = data;
 
 	rinfo->no_schedule = 1;
+	pci_restore_state(rinfo->pdev);
 	radeonfb_pci_resume(rinfo->pdev);
 	rinfo->no_schedule = 0;
 }
@@ -2834,7 +2859,14 @@
 		 */
 		if (rinfo->pm_mode != radeon_pm_none) {
 			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1);
+#if 0 /* Disable the early video resume hack for now as it's causing problems, among
+       * others we now rely on the PCI core restoring the config space for us, which
+       * isn't the case with that hack, and that code path causes various things to
+       * be called with interrupts off while they shouldn't. I'm leaving the code in
+       * as it can be useful for debugging purposes
+       */
 			pmac_set_early_video_resume(radeonfb_early_resume, rinfo);
+#endif
 		}
 
 #if 0
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 62bd444..378f277 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -457,7 +457,7 @@
 
 /* AU1100 LCD controller device driver */
 
-static int __init au1100fb_drv_probe(struct device *dev)
+static int __init au1100fb_drv_probe(struct platform_device *dev)
 {
 	struct au1100fb_device *fbdev = NULL;
 	struct resource *regs_res;
@@ -475,7 +475,7 @@
 
 	fbdev->panel = &known_lcd_panels[drv_info.panel_idx];
 
-	dev_set_drvdata(dev, (void*)fbdev);
+	platform_set_drvdata(dev, (void *)fbdev);
 
 	/* Allocate region for our registers and map them */
 	if (!(regs_res = platform_get_resource(to_platform_device(dev),
@@ -583,19 +583,19 @@
 		fb_dealloc_cmap(&fbdev->info.cmap);
 	}
 	kfree(fbdev);
-	dev_set_drvdata(dev, NULL);
+	platform_set_drvdata(dev, NULL);
 
 	return 0;
 }
 
-int au1100fb_drv_remove(struct device *dev)
+int au1100fb_drv_remove(struct platform_device *dev)
 {
 	struct au1100fb_device *fbdev = NULL;
 
 	if (!dev)
 		return -ENODEV;
 
-	fbdev = (struct au1100fb_device*) dev_get_drvdata(dev);
+	fbdev = (struct au1100fb_device *) platform_get_drvdata(dev);
 
 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
 	au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
@@ -620,9 +620,9 @@
 static u32 sys_clksrc;
 static struct au1100fb_regs fbregs;
 
-int au1100fb_drv_suspend(struct device *dev, pm_message_t state)
+int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state)
 {
-	struct au1100fb_device *fbdev = dev_get_drvdata(dev);
+	struct au1100fb_device *fbdev = platform_get_drvdata(dev);
 
 	if (!fbdev)
 		return 0;
@@ -641,9 +641,9 @@
 	return 0;
 }
 
-int au1100fb_drv_resume(struct device *dev)
+int au1100fb_drv_resume(struct platform_device *dev)
 {
-	struct au1100fb_device *fbdev = dev_get_drvdata(dev);
+	struct au1100fb_device *fbdev = platform_get_drvdata(dev);
 
 	if (!fbdev)
 		return 0;
@@ -663,10 +663,11 @@
 #define au1100fb_drv_resume NULL
 #endif
 
-static struct device_driver au1100fb_driver = {
-	.name		= "au1100-lcd",
-	.bus		= &platform_bus_type,
-
+static struct platform_driver au1100fb_driver = {
+	.driver = {
+		.name		= "au1100-lcd",
+		.owner          = THIS_MODULE,
+	},
 	.probe		= au1100fb_drv_probe,
         .remove		= au1100fb_drv_remove,
 	.suspend	= au1100fb_drv_suspend,
@@ -753,12 +754,12 @@
 		return ret;
 	}
 
-	return driver_register(&au1100fb_driver);
+	return platform_driver_register(&au1100fb_driver);
 }
 
 void __exit au1100fb_cleanup(void)
 {
-	driver_unregister(&au1100fb_driver);
+	platform_driver_unregister(&au1100fb_driver);
 
 	kfree(drv_info.opt_mode);
 }
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 03e57ef..0d96f1d 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1622,7 +1622,7 @@
 
 /* AU1200 LCD controller device driver */
 
-static int au1200fb_drv_probe(struct device *dev)
+static int au1200fb_drv_probe(struct platform_device *dev)
 {
 	struct au1200fb_device *fbdev;
 	unsigned long page;
@@ -1645,7 +1645,7 @@
 		/* Allocate the framebuffer to the maximum screen size */
 		fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
 
-		fbdev->fb_mem = dma_alloc_noncoherent(dev,
+		fbdev->fb_mem = dma_alloc_noncoherent(&dev->dev,
 				PAGE_ALIGN(fbdev->fb_len),
 				&fbdev->fb_phys, GFP_KERNEL);
 		if (!fbdev->fb_mem) {
@@ -1715,7 +1715,7 @@
 	return ret;
 }
 
-static int au1200fb_drv_remove(struct device *dev)
+static int au1200fb_drv_remove(struct platform_device *dev)
 {
 	struct au1200fb_device *fbdev;
 	int plane;
@@ -1733,7 +1733,8 @@
 		/* Clean up all probe data */
 		unregister_framebuffer(&fbdev->fb_info);
 		if (fbdev->fb_mem)
-			dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
+			dma_free_noncoherent(&dev->dev,
+					PAGE_ALIGN(fbdev->fb_len),
 					fbdev->fb_mem, fbdev->fb_phys);
 		if (fbdev->fb_info.cmap.len != 0)
 			fb_dealloc_cmap(&fbdev->fb_info.cmap);
@@ -1747,22 +1748,24 @@
 }
 
 #ifdef CONFIG_PM
-static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level)
+static int au1200fb_drv_suspend(struct platform_device *dev, u32 state)
 {
 	/* TODO */
 	return 0;
 }
 
-static int au1200fb_drv_resume(struct device *dev, u32 level)
+static int au1200fb_drv_resume(struct platform_device *dev)
 {
 	/* TODO */
 	return 0;
 }
 #endif /* CONFIG_PM */
 
-static struct device_driver au1200fb_driver = {
-	.name		= "au1200-lcd",
-	.bus		= &platform_bus_type,
+static struct platform_driver au1200fb_driver = {
+	.driver = {
+		.name		= "au1200-lcd",
+		.owner          = THIS_MODULE,
+	},
 	.probe		= au1200fb_drv_probe,
 	.remove		= au1200fb_drv_remove,
 #ifdef CONFIG_PM
@@ -1906,12 +1909,12 @@
 		printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n");
 	#endif
 
-	return driver_register(&au1200fb_driver);
+	return platform_driver_register(&au1200fb_driver);
 }
 
 static void __exit au1200fb_cleanup(void)
 {
-	driver_unregister(&au1200fb_driver);
+	platform_driver_unregister(&au1200fb_driver);
 }
 
 module_init(au1200fb_init);
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index a24e680..2e94019 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -993,6 +993,7 @@
 	struct i810fb_par *par = info->par;
 	int line_length, vidmem, mode_valid = 0, retval = 0;
 	u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
+
 	/*
 	 *  Memory limit
 	 */
@@ -1002,12 +1003,12 @@
 	if (vidmem > par->fb.size) {
 		vyres = par->fb.size/line_length;
 		if (vyres < var->yres) {
-			vyres = yres;
+			vyres = info->var.yres;
 			vxres = par->fb.size/vyres;
 			vxres /= var->bits_per_pixel >> 3;
 			line_length = get_line_length(par, vxres, 
 						      var->bits_per_pixel);
-			vidmem = line_length * yres;
+			vidmem = line_length * info->var.yres;
 			if (vxres < var->xres) {
 				printk("i810fb: required video memory, "
 				       "%d bytes, for %dx%d-%d (virtual) "
diff --git a/drivers/video/logo/logo_linux_clut224.ppm b/drivers/video/logo/logo_linux_clut224.ppm
index 3c14e43..de93ff3 100644
--- a/drivers/video/logo/logo_linux_clut224.ppm
+++ b/drivers/video/logo/logo_linux_clut224.ppm
@@ -1,1604 +1,2828 @@
 P3
-# Standard 224-color Linux logo
-80 80
+145 113
 255
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6   6   6   6  10  10  10  10  10  10
- 10  10  10   6   6   6   6   6   6   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   6   6   6  10  10  10  14  14  14
- 22  22  22  26  26  26  30  30  30  34  34  34
- 30  30  30  30  30  30  26  26  26  18  18  18
- 14  14  14  10  10  10   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   1   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6  14  14  14  26  26  26  42  42  42
- 54  54  54  66  66  66  78  78  78  78  78  78
- 78  78  78  74  74  74  66  66  66  54  54  54
- 42  42  42  26  26  26  18  18  18  10  10  10
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   1   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 22  22  22  42  42  42  66  66  66  86  86  86
- 66  66  66  38  38  38  38  38  38  22  22  22
- 26  26  26  34  34  34  54  54  54  66  66  66
- 86  86  86  70  70  70  46  46  46  26  26  26
- 14  14  14   6   6   6   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   1   0   0   1   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  10  10  10  26  26  26
- 50  50  50  82  82  82  58  58  58   6   6   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  6   6   6  54  54  54  86  86  86  66  66  66
- 38  38  38  18  18  18   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   6   6   6  22  22  22  50  50  50
- 78  78  78  34  34  34   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   6   6   6  70  70  70
- 78  78  78  46  46  46  22  22  22   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   1   0   0   1   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6  18  18  18  42  42  42  82  82  82
- 26  26  26   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  14  14  14
- 46  46  46  34  34  34   6   6   6   2   2   6
- 42  42  42  78  78  78  42  42  42  18  18  18
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   1   0   0   0   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 10  10  10  30  30  30  66  66  66  58  58  58
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  26  26  26
- 86  86  86 101 101 101  46  46  46  10  10  10
-  2   2   6  58  58  58  70  70  70  34  34  34
- 10  10  10   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   1   0   0   1   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 14  14  14  42  42  42  86  86  86  10  10  10
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  30  30  30
- 94  94  94  94  94  94  58  58  58  26  26  26
-  2   2   6   6   6   6  78  78  78  54  54  54
- 22  22  22   6   6   6   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 22  22  22  62  62  62  62  62  62   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  26  26  26
- 54  54  54  38  38  38  18  18  18  10  10  10
-  2   2   6   2   2   6  34  34  34  82  82  82
- 38  38  38  14  14  14   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   1   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 30  30  30  78  78  78  30  30  30   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  10  10  10
- 10  10  10   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  78  78  78
- 50  50  50  18  18  18   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   1   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 38  38  38  86  86  86  14  14  14   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  54  54  54
- 66  66  66  26  26  26   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   1   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 42  42  42  82  82  82   2   2   6   2   2   6
-  2   2   6   6   6   6  10  10  10   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   6   6   6
- 14  14  14  10  10  10   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  18  18  18
- 82  82  82  34  34  34  10  10  10   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   1   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 46  46  46  86  86  86   2   2   6   2   2   6
-  6   6   6   6   6   6  22  22  22  34  34  34
-  6   6   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6  18  18  18  34  34  34
- 10  10  10  50  50  50  22  22  22   2   2   6
-  2   2   6   2   2   6   2   2   6  10  10  10
- 86  86  86  42  42  42  14  14  14   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   1   0   0   1   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 46  46  46  86  86  86   2   2   6   2   2   6
- 38  38  38 116 116 116  94  94  94  22  22  22
- 22  22  22   2   2   6   2   2   6   2   2   6
- 14  14  14  86  86  86 138 138 138 162 162 162
-154 154 154  38  38  38  26  26  26   6   6   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 86  86  86  46  46  46  14  14  14   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 46  46  46  86  86  86   2   2   6  14  14  14
-134 134 134 198 198 198 195 195 195 116 116 116
- 10  10  10   2   2   6   2   2   6   6   6   6
-101  98  89 187 187 187 210 210 210 218 218 218
-214 214 214 134 134 134  14  14  14   6   6   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 86  86  86  50  50  50  18  18  18   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   1   0   0   0
-  0   0   1   0   0   1   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 46  46  46  86  86  86   2   2   6  54  54  54
-218 218 218 195 195 195 226 226 226 246 246 246
- 58  58  58   2   2   6   2   2   6  30  30  30
-210 210 210 253 253 253 174 174 174 123 123 123
-221 221 221 234 234 234  74  74  74   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 70  70  70  58  58  58  22  22  22   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 46  46  46  82  82  82   2   2   6 106 106 106
-170 170 170  26  26  26  86  86  86 226 226 226
-123 123 123  10  10  10  14  14  14  46  46  46
-231 231 231 190 190 190   6   6   6  70  70  70
- 90  90  90 238 238 238 158 158 158   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 70  70  70  58  58  58  22  22  22   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   1   0   0   0
-  0   0   1   0   0   1   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 42  42  42  86  86  86   6   6   6 116 116 116
-106 106 106   6   6   6  70  70  70 149 149 149
-128 128 128  18  18  18  38  38  38  54  54  54
-221 221 221 106 106 106   2   2   6  14  14  14
- 46  46  46 190 190 190 198 198 198   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 74  74  74  62  62  62  22  22  22   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   1   0   0   0
-  0   0   1   0   0   0   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 42  42  42  94  94  94  14  14  14 101 101 101
-128 128 128   2   2   6  18  18  18 116 116 116
-118  98  46 121  92   8 121  92   8  98  78  10
-162 162 162 106 106 106   2   2   6   2   2   6
-  2   2   6 195 195 195 195 195 195   6   6   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 74  74  74  62  62  62  22  22  22   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   1   0   0   1
-  0   0   1   0   0   0   0   0   1   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 38  38  38  90  90  90  14  14  14  58  58  58
-210 210 210  26  26  26  54  38   6 154 114  10
-226 170  11 236 186  11 225 175  15 184 144  12
-215 174  15 175 146  61  37  26   9   2   2   6
- 70  70  70 246 246 246 138 138 138   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 70  70  70  66  66  66  26  26  26   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 38  38  38  86  86  86  14  14  14  10  10  10
-195 195 195 188 164 115 192 133   9 225 175  15
-239 182  13 234 190  10 232 195  16 232 200  30
-245 207  45 241 208  19 232 195  16 184 144  12
-218 194 134 211 206 186  42  42  42   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 50  50  50  74  74  74  30  30  30   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 34  34  34  86  86  86  14  14  14   2   2   6
-121  87  25 192 133   9 219 162  10 239 182  13
-236 186  11 232 195  16 241 208  19 244 214  54
-246 218  60 246 218  38 246 215  20 241 208  19
-241 208  19 226 184  13 121  87  25   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 50  50  50  82  82  82  34  34  34  10  10  10
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 34  34  34  82  82  82  30  30  30  61  42   6
-180 123   7 206 145  10 230 174  11 239 182  13
-234 190  10 238 202  15 241 208  19 246 218  74
-246 218  38 246 215  20 246 215  20 246 215  20
-226 184  13 215 174  15 184 144  12   6   6   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 26  26  26  94  94  94  42  42  42  14  14  14
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 30  30  30  78  78  78  50  50  50 104  69   6
-192 133   9 216 158  10 236 178  12 236 186  11
-232 195  16 241 208  19 244 214  54 245 215  43
-246 215  20 246 215  20 241 208  19 198 155  10
-200 144  11 216 158  10 156 118  10   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  6   6   6  90  90  90  54  54  54  18  18  18
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 30  30  30  78  78  78  46  46  46  22  22  22
-137  92   6 210 162  10 239 182  13 238 190  10
-238 202  15 241 208  19 246 215  20 246 215  20
-241 208  19 203 166  17 185 133  11 210 150  10
-216 158  10 210 150  10 102  78  10   2   2   6
-  6   6   6  54  54  54  14  14  14   2   2   6
-  2   2   6  62  62  62  74  74  74  30  30  30
- 10  10  10   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 34  34  34  78  78  78  50  50  50   6   6   6
- 94  70  30 139 102  15 190 146  13 226 184  13
-232 200  30 232 195  16 215 174  15 190 146  13
-168 122  10 192 133   9 210 150  10 213 154  11
-202 150  34 182 157 106 101  98  89   2   2   6
-  2   2   6  78  78  78 116 116 116  58  58  58
-  2   2   6  22  22  22  90  90  90  46  46  46
- 18  18  18   6   6   6   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 38  38  38  86  86  86  50  50  50   6   6   6
-128 128 128 174 154 114 156 107  11 168 122  10
-198 155  10 184 144  12 197 138  11 200 144  11
-206 145  10 206 145  10 197 138  11 188 164 115
-195 195 195 198 198 198 174 174 174  14  14  14
-  2   2   6  22  22  22 116 116 116 116 116 116
- 22  22  22   2   2   6  74  74  74  70  70  70
- 30  30  30  10  10  10   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  18  18  18
- 50  50  50 101 101 101  26  26  26  10  10  10
-138 138 138 190 190 190 174 154 114 156 107  11
-197 138  11 200 144  11 197 138  11 192 133   9
-180 123   7 190 142  34 190 178 144 187 187 187
-202 202 202 221 221 221 214 214 214  66  66  66
-  2   2   6   2   2   6  50  50  50  62  62  62
-  6   6   6   2   2   6  10  10  10  90  90  90
- 50  50  50  18  18  18   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  10  10  10  34  34  34
- 74  74  74  74  74  74   2   2   6   6   6   6
-144 144 144 198 198 198 190 190 190 178 166 146
-154 121  60 156 107  11 156 107  11 168 124  44
-174 154 114 187 187 187 190 190 190 210 210 210
-246 246 246 253 253 253 253 253 253 182 182 182
-  6   6   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  62  62  62
- 74  74  74  34  34  34  14  14  14   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  10  10  10  22  22  22  54  54  54
- 94  94  94  18  18  18   2   2   6  46  46  46
-234 234 234 221 221 221 190 190 190 190 190 190
-190 190 190 187 187 187 187 187 187 190 190 190
-190 190 190 195 195 195 214 214 214 242 242 242
-253 253 253 253 253 253 253 253 253 253 253 253
- 82  82  82   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  14  14  14
- 86  86  86  54  54  54  22  22  22   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6  18  18  18  46  46  46  90  90  90
- 46  46  46  18  18  18   6   6   6 182 182 182
-253 253 253 246 246 246 206 206 206 190 190 190
-190 190 190 190 190 190 190 190 190 190 190 190
-206 206 206 231 231 231 250 250 250 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-202 202 202  14  14  14   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 42  42  42  86  86  86  42  42  42  18  18  18
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 14  14  14  38  38  38  74  74  74  66  66  66
-  2   2   6   6   6   6  90  90  90 250 250 250
-253 253 253 253 253 253 238 238 238 198 198 198
-190 190 190 190 190 190 195 195 195 221 221 221
-246 246 246 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253  82  82  82   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6  78  78  78  70  70  70  34  34  34
- 14  14  14   6   6   6   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 34  34  34  66  66  66  78  78  78   6   6   6
-  2   2   6  18  18  18 218 218 218 253 253 253
-253 253 253 253 253 253 253 253 253 246 246 246
-226 226 226 231 231 231 246 246 246 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 178 178 178   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6  18  18  18  90  90  90  62  62  62
- 30  30  30  10  10  10   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  10  10  10  26  26  26
- 58  58  58  90  90  90  18  18  18   2   2   6
-  2   2   6 110 110 110 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-250 250 250 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 231 231 231  18  18  18   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6  18  18  18  94  94  94
- 54  54  54  26  26  26  10  10  10   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   6   6   6  22  22  22  50  50  50
- 90  90  90  26  26  26   2   2   6   2   2   6
- 14  14  14 195 195 195 250 250 250 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-250 250 250 242 242 242  54  54  54   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6  38  38  38
- 86  86  86  50  50  50  22  22  22   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6  14  14  14  38  38  38  82  82  82
- 34  34  34   2   2   6   2   2   6   2   2   6
- 42  42  42 195 195 195 246 246 246 253 253 253
-253 253 253 253 253 253 253 253 253 250 250 250
-242 242 242 242 242 242 250 250 250 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 250 250 250 246 246 246 238 238 238
-226 226 226 231 231 231 101 101 101   6   6   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
- 38  38  38  82  82  82  42  42  42  14  14  14
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 10  10  10  26  26  26  62  62  62  66  66  66
-  2   2   6   2   2   6   2   2   6   6   6   6
- 70  70  70 170 170 170 206 206 206 234 234 234
-246 246 246 250 250 250 250 250 250 238 238 238
-226 226 226 231 231 231 238 238 238 250 250 250
-250 250 250 250 250 250 246 246 246 231 231 231
-214 214 214 206 206 206 202 202 202 202 202 202
-198 198 198 202 202 202 182 182 182  18  18  18
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6  62  62  62  66  66  66  30  30  30
- 10  10  10   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 14  14  14  42  42  42  82  82  82  18  18  18
-  2   2   6   2   2   6   2   2   6  10  10  10
- 94  94  94 182 182 182 218 218 218 242 242 242
-250 250 250 253 253 253 253 253 253 250 250 250
-234 234 234 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 246 246 246
-238 238 238 226 226 226 210 210 210 202 202 202
-195 195 195 195 195 195 210 210 210 158 158 158
-  6   6   6  14  14  14  50  50  50  14  14  14
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   6   6   6  86  86  86  46  46  46
- 18  18  18   6   6   6   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 22  22  22  54  54  54  70  70  70   2   2   6
-  2   2   6  10  10  10   2   2   6  22  22  22
-166 166 166 231 231 231 250 250 250 253 253 253
-253 253 253 253 253 253 253 253 253 250 250 250
-242 242 242 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 246 246 246
-231 231 231 206 206 206 198 198 198 226 226 226
- 94  94  94   2   2   6   6   6   6  38  38  38
- 30  30  30   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6  62  62  62  66  66  66
- 26  26  26  10  10  10   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 30  30  30  74  74  74  50  50  50   2   2   6
- 26  26  26  26  26  26   2   2   6 106 106 106
-238 238 238 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 246 246 246 218 218 218 202 202 202
-210 210 210  14  14  14   2   2   6   2   2   6
- 30  30  30  22  22  22   2   2   6   2   2   6
-  2   2   6   2   2   6  18  18  18  86  86  86
- 42  42  42  14  14  14   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 42  42  42  90  90  90  22  22  22   2   2   6
- 42  42  42   2   2   6  18  18  18 218 218 218
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 250 250 250 221 221 221
-218 218 218 101 101 101   2   2   6  14  14  14
- 18  18  18  38  38  38  10  10  10   2   2   6
-  2   2   6   2   2   6   2   2   6  78  78  78
- 58  58  58  22  22  22   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  18  18  18
- 54  54  54  82  82  82   2   2   6  26  26  26
- 22  22  22   2   2   6 123 123 123 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 250 250 250
-238 238 238 198 198 198   6   6   6  38  38  38
- 58  58  58  26  26  26  38  38  38   2   2   6
-  2   2   6   2   2   6   2   2   6  46  46  46
- 78  78  78  30  30  30  10  10  10   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  10  10  10  30  30  30
- 74  74  74  58  58  58   2   2   6  42  42  42
-  2   2   6  22  22  22 231 231 231 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 250 250 250
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 246 246 246  46  46  46  38  38  38
- 42  42  42  14  14  14  38  38  38  14  14  14
-  2   2   6   2   2   6   2   2   6   6   6   6
- 86  86  86  46  46  46  14  14  14   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   6   6   6  14  14  14  42  42  42
- 90  90  90  18  18  18  18  18  18  26  26  26
-  2   2   6 116 116 116 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 250 250 250 238 238 238
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253  94  94  94   6   6   6
-  2   2   6   2   2   6  10  10  10  34  34  34
-  2   2   6   2   2   6   2   2   6   2   2   6
- 74  74  74  58  58  58  22  22  22   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  10  10  10  26  26  26  66  66  66
- 82  82  82   2   2   6  38  38  38   6   6   6
- 14  14  14 210 210 210 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 246 246 246 242 242 242
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 144 144 144   2   2   6
-  2   2   6   2   2   6   2   2   6  46  46  46
-  2   2   6   2   2   6   2   2   6   2   2   6
- 42  42  42  74  74  74  30  30  30  10  10  10
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6  14  14  14  42  42  42  90  90  90
- 26  26  26   6   6   6  42  42  42   2   2   6
- 74  74  74 250 250 250 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 242 242 242 242 242 242
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 182 182 182   2   2   6
-  2   2   6   2   2   6   2   2   6  46  46  46
-  2   2   6   2   2   6   2   2   6   2   2   6
- 10  10  10  86  86  86  38  38  38  10  10  10
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 10  10  10  26  26  26  66  66  66  82  82  82
-  2   2   6  22  22  22  18  18  18   2   2   6
-149 149 149 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 234 234 234 242 242 242
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 206 206 206   2   2   6
-  2   2   6   2   2   6   2   2   6  38  38  38
-  2   2   6   2   2   6   2   2   6   2   2   6
-  6   6   6  86  86  86  46  46  46  14  14  14
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 18  18  18  46  46  46  86  86  86  18  18  18
-  2   2   6  34  34  34  10  10  10   6   6   6
-210 210 210 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 234 234 234 242 242 242
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 221 221 221   6   6   6
-  2   2   6   2   2   6   6   6   6  30  30  30
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6  82  82  82  54  54  54  18  18  18
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 26  26  26  66  66  66  62  62  62   2   2   6
-  2   2   6  38  38  38  10  10  10  26  26  26
-238 238 238 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 231 231 231 238 238 238
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 231 231 231   6   6   6
-  2   2   6   2   2   6  10  10  10  30  30  30
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6  66  66  66  58  58  58  22  22  22
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 38  38  38  78  78  78   6   6   6   2   2   6
-  2   2   6  46  46  46  14  14  14  42  42  42
-246 246 246 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 231 231 231 242 242 242
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 234 234 234  10  10  10
-  2   2   6   2   2   6  22  22  22  14  14  14
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6  66  66  66  62  62  62  22  22  22
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  18  18  18
- 50  50  50  74  74  74   2   2   6   2   2   6
- 14  14  14  70  70  70  34  34  34  62  62  62
-250 250 250 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 231 231 231 246 246 246
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 234 234 234  14  14  14
-  2   2   6   2   2   6  30  30  30   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6  66  66  66  62  62  62  22  22  22
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  18  18  18
- 54  54  54  62  62  62   2   2   6   2   2   6
-  2   2   6  30  30  30  46  46  46  70  70  70
-250 250 250 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 231 231 231 246 246 246
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 226 226 226  10  10  10
-  2   2   6   6   6   6  30  30  30   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6  66  66  66  58  58  58  22  22  22
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  22  22  22
- 58  58  58  62  62  62   2   2   6   2   2   6
-  2   2   6   2   2   6  30  30  30  78  78  78
-250 250 250 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 231 231 231 246 246 246
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 206 206 206   2   2   6
- 22  22  22  34  34  34  18  14   6  22  22  22
- 26  26  26  18  18  18   6   6   6   2   2   6
-  2   2   6  82  82  82  54  54  54  18  18  18
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  26  26  26
- 62  62  62 106 106 106  74  54  14 185 133  11
-210 162  10 121  92   8   6   6   6  62  62  62
-238 238 238 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 231 231 231 246 246 246
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 158 158 158  18  18  18
- 14  14  14   2   2   6   2   2   6   2   2   6
-  6   6   6  18  18  18  66  66  66  38  38  38
-  6   6   6  94  94  94  50  50  50  18  18  18
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 10  10  10  10  10  10  18  18  18  38  38  38
- 78  78  78 142 134 106 216 158  10 242 186  14
-246 190  14 246 190  14 156 118  10  10  10  10
- 90  90  90 238 238 238 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 231 231 231 250 250 250
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 246 230 190
-238 204  91 238 204  91 181 142  44  37  26   9
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6  38  38  38  46  46  46
- 26  26  26 106 106 106  54  54  54  18  18  18
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   6   6   6  14  14  14  22  22  22
- 30  30  30  38  38  38  50  50  50  70  70  70
-106 106 106 190 142  34 226 170  11 242 186  14
-246 190  14 246 190  14 246 190  14 154 114  10
-  6   6   6  74  74  74 226 226 226 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 231 231 231 250 250 250
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 228 184  62
-241 196  14 241 208  19 232 195  16  38  30  10
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   6   6   6  30  30  30  26  26  26
-203 166  17 154 142  90  66  66  66  26  26  26
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6  18  18  18  38  38  38  58  58  58
- 78  78  78  86  86  86 101 101 101 123 123 123
-175 146  61 210 150  10 234 174  13 246 186  14
-246 190  14 246 190  14 246 190  14 238 190  10
-102  78  10   2   2   6  46  46  46 198 198 198
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 234 234 234 242 242 242
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 224 178  62
-242 186  14 241 196  14 210 166  10  22  18   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   6   6   6 121  92   8
-238 202  15 232 195  16  82  82  82  34  34  34
- 10  10  10   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 14  14  14  38  38  38  70  70  70 154 122  46
-190 142  34 200 144  11 197 138  11 197 138  11
-213 154  11 226 170  11 242 186  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-225 175  15  46  32   6   2   2   6  22  22  22
-158 158 158 250 250 250 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 250 250 250 242 242 242 224 178  62
-239 182  13 236 186  11 213 154  11  46  32   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6  61  42   6 225 175  15
-238 190  10 236 186  11 112 100  78  42  42  42
- 14  14  14   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 22  22  22  54  54  54 154 122  46 213 154  11
-226 170  11 230 174  11 226 170  11 226 170  11
-236 178  12 242 186  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-241 196  14 184 144  12  10  10  10   2   2   6
-  6   6   6 116 116 116 242 242 242 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 231 231 231 198 198 198 214 170  54
-236 178  12 236 178  12 210 150  10 137  92   6
- 18  14   6   2   2   6   2   2   6   2   2   6
-  6   6   6  70  47   6 200 144  11 236 178  12
-239 182  13 239 182  13 124 112  88  58  58  58
- 22  22  22   6   6   6   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 30  30  30  70  70  70 180 133  36 226 170  11
-239 182  13 242 186  14 242 186  14 246 186  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 232 195  16  98  70   6   2   2   6
-  2   2   6   2   2   6  66  66  66 221 221 221
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 206 206 206 198 198 198 214 166  58
-230 174  11 230 174  11 216 158  10 192 133   9
-163 110   8 116  81   8 102  78  10 116  81   8
-167 114   7 197 138  11 226 170  11 239 182  13
-242 186  14 242 186  14 162 146  94  78  78  78
- 34  34  34  14  14  14   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 30  30  30  78  78  78 190 142  34 226 170  11
-239 182  13 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 241 196  14 203 166  17  22  18   6
-  2   2   6   2   2   6   2   2   6  38  38  38
-218 218 218 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-250 250 250 206 206 206 198 198 198 202 162  69
-226 170  11 236 178  12 224 166  10 210 150  10
-200 144  11 197 138  11 192 133   9 197 138  11
-210 150  10 226 170  11 242 186  14 246 190  14
-246 190  14 246 186  14 225 175  15 124 112  88
- 62  62  62  30  30  30  14  14  14   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 30  30  30  78  78  78 174 135  50 224 166  10
-239 182  13 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 241 196  14 139 102  15
-  2   2   6   2   2   6   2   2   6   2   2   6
- 78  78  78 250 250 250 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-250 250 250 214 214 214 198 198 198 190 150  46
-219 162  10 236 178  12 234 174  13 224 166  10
-216 158  10 213 154  11 213 154  11 216 158  10
-226 170  11 239 182  13 246 190  14 246 190  14
-246 190  14 246 190  14 242 186  14 206 162  42
-101 101 101  58  58  58  30  30  30  14  14  14
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 30  30  30  74  74  74 174 135  50 216 158  10
-236 178  12 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 241 196  14 226 184  13
- 61  42   6   2   2   6   2   2   6   2   2   6
- 22  22  22 238 238 238 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 226 226 226 187 187 187 180 133  36
-216 158  10 236 178  12 239 182  13 236 178  12
-230 174  11 226 170  11 226 170  11 230 174  11
-236 178  12 242 186  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 186  14 239 182  13
-206 162  42 106 106 106  66  66  66  34  34  34
- 14  14  14   6   6   6   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 26  26  26  70  70  70 163 133  67 213 154  11
-236 178  12 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 241 196  14
-190 146  13  18  14   6   2   2   6   2   2   6
- 46  46  46 246 246 246 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 221 221 221  86  86  86 156 107  11
-216 158  10 236 178  12 242 186  14 246 186  14
-242 186  14 239 182  13 239 182  13 242 186  14
-242 186  14 246 186  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-242 186  14 225 175  15 142 122  72  66  66  66
- 30  30  30  10  10  10   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 26  26  26  70  70  70 163 133  67 210 150  10
-236 178  12 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-232 195  16 121  92   8  34  34  34 106 106 106
-221 221 221 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-242 242 242  82  82  82  18  14   6 163 110   8
-216 158  10 236 178  12 242 186  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 242 186  14 163 133  67
- 46  46  46  18  18  18   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  10  10  10
- 30  30  30  78  78  78 163 133  67 210 150  10
-236 178  12 246 186  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-241 196  14 215 174  15 190 178 144 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 218 218 218
- 58  58  58   2   2   6  22  18   6 167 114   7
-216 158  10 236 178  12 246 186  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 186  14 242 186  14 190 150  46
- 54  54  54  22  22  22   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 38  38  38  86  86  86 180 133  36 213 154  11
-236 178  12 246 186  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 232 195  16 190 146  13 214 214 214
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 250 250 250 170 170 170  26  26  26
-  2   2   6   2   2   6  37  26   9 163 110   8
-219 162  10 239 182  13 246 186  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 186  14 236 178  12 224 166  10 142 122  72
- 46  46  46  18  18  18   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  18  18  18
- 50  50  50 109 106  95 192 133   9 224 166  10
-242 186  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-242 186  14 226 184  13 210 162  10 142 110  46
-226 226 226 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-253 253 253 253 253 253 253 253 253 253 253 253
-198 198 198  66  66  66   2   2   6   2   2   6
-  2   2   6   2   2   6  50  34   6 156 107  11
-219 162  10 239 182  13 246 186  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 242 186  14
-234 174  13 213 154  11 154 122  46  66  66  66
- 30  30  30  10  10  10   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  22  22  22
- 58  58  58 154 121  60 206 145  10 234 174  13
-242 186  14 246 186  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 186  14 236 178  12 210 162  10 163 110   8
- 61  42   6 138 138 138 218 218 218 250 250 250
-253 253 253 253 253 253 253 253 253 250 250 250
-242 242 242 210 210 210 144 144 144  66  66  66
-  6   6   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6  61  42   6 163 110   8
-216 158  10 236 178  12 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 239 182  13 230 174  11 216 158  10
-190 142  34 124 112  88  70  70  70  38  38  38
- 18  18  18   6   6   6   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  22  22  22
- 62  62  62 168 124  44 206 145  10 224 166  10
-236 178  12 239 182  13 242 186  14 242 186  14
-246 186  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 236 178  12 216 158  10 175 118   6
- 80  54   7   2   2   6   6   6   6  30  30  30
- 54  54  54  62  62  62  50  50  50  38  38  38
- 14  14  14   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   6   6   6  80  54   7 167 114   7
-213 154  11 236 178  12 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 190  14 242 186  14 239 182  13 239 182  13
-230 174  11 210 150  10 174 135  50 124 112  88
- 82  82  82  54  54  54  34  34  34  18  18  18
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  18  18  18
- 50  50  50 158 118  36 192 133   9 200 144  11
-216 158  10 219 162  10 224 166  10 226 170  11
-230 174  11 236 178  12 239 182  13 239 182  13
-242 186  14 246 186  14 246 190  14 246 190  14
-246 190  14 246 190  14 246 190  14 246 190  14
-246 186  14 230 174  11 210 150  10 163 110   8
-104  69   6  10  10  10   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   6   6   6  91  60   6 167 114   7
-206 145  10 230 174  11 242 186  14 246 190  14
-246 190  14 246 190  14 246 186  14 242 186  14
-239 182  13 230 174  11 224 166  10 213 154  11
-180 133  36 124 112  88  86  86  86  58  58  58
- 38  38  38  22  22  22  10  10  10   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  14  14  14
- 34  34  34  70  70  70 138 110  50 158 118  36
-167 114   7 180 123   7 192 133   9 197 138  11
-200 144  11 206 145  10 213 154  11 219 162  10
-224 166  10 230 174  11 239 182  13 242 186  14
-246 186  14 246 186  14 246 186  14 246 186  14
-239 182  13 216 158  10 185 133  11 152  99   6
-104  69   6  18  14   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   2   2   6   2   2   6   2   2   6
-  2   2   6   6   6   6  80  54   7 152  99   6
-192 133   9 219 162  10 236 178  12 239 182  13
-246 186  14 242 186  14 239 182  13 236 178  12
-224 166  10 206 145  10 192 133   9 154 121  60
- 94  94  94  62  62  62  42  42  42  22  22  22
- 14  14  14   6   6   6   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 18  18  18  34  34  34  58  58  58  78  78  78
-101  98  89 124 112  88 142 110  46 156 107  11
-163 110   8 167 114   7 175 118   6 180 123   7
-185 133  11 197 138  11 210 150  10 219 162  10
-226 170  11 236 178  12 236 178  12 234 174  13
-219 162  10 197 138  11 163 110   8 130  83   6
- 91  60   6  10  10  10   2   2   6   2   2   6
- 18  18  18  38  38  38  38  38  38  38  38  38
- 38  38  38  38  38  38  38  38  38  38  38  38
- 38  38  38  38  38  38  26  26  26   2   2   6
-  2   2   6   6   6   6  70  47   6 137  92   6
-175 118   6 200 144  11 219 162  10 230 174  11
-234 174  13 230 174  11 219 162  10 210 150  10
-192 133   9 163 110   8 124 112  88  82  82  82
- 50  50  50  30  30  30  14  14  14   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6  14  14  14  22  22  22  34  34  34
- 42  42  42  58  58  58  74  74  74  86  86  86
-101  98  89 122 102  70 130  98  46 121  87  25
-137  92   6 152  99   6 163 110   8 180 123   7
-185 133  11 197 138  11 206 145  10 200 144  11
-180 123   7 156 107  11 130  83   6 104  69   6
- 50  34   6  54  54  54 110 110 110 101  98  89
- 86  86  86  82  82  82  78  78  78  78  78  78
- 78  78  78  78  78  78  78  78  78  78  78  78
- 78  78  78  82  82  82  86  86  86  94  94  94
-106 106 106 101 101 101  86  66  34 124  80   6
-156 107  11 180 123   7 192 133   9 200 144  11
-206 145  10 200 144  11 192 133   9 175 118   6
-139 102  15 109 106  95  70  70  70  42  42  42
- 22  22  22  10  10  10   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   6   6   6  10  10  10
- 14  14  14  22  22  22  30  30  30  38  38  38
- 50  50  50  62  62  62  74  74  74  90  90  90
-101  98  89 112 100  78 121  87  25 124  80   6
-137  92   6 152  99   6 152  99   6 152  99   6
-138  86   6 124  80   6  98  70   6  86  66  30
-101  98  89  82  82  82  58  58  58  46  46  46
- 38  38  38  34  34  34  34  34  34  34  34  34
- 34  34  34  34  34  34  34  34  34  34  34  34
- 34  34  34  34  34  34  38  38  38  42  42  42
- 54  54  54  82  82  82  94  86  76  91  60   6
-134  86   6 156 107  11 167 114   7 175 118   6
-175 118   6 167 114   7 152  99   6 121  87  25
-101  98  89  62  62  62  34  34  34  18  18  18
-  6   6   6   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   6   6   6   6   6   6  10  10  10
- 18  18  18  22  22  22  30  30  30  42  42  42
- 50  50  50  66  66  66  86  86  86 101  98  89
-106  86  58  98  70   6 104  69   6 104  69   6
-104  69   6  91  60   6  82  62  34  90  90  90
- 62  62  62  38  38  38  22  22  22  14  14  14
- 10  10  10  10  10  10  10  10  10  10  10  10
- 10  10  10  10  10  10   6   6   6  10  10  10
- 10  10  10  10  10  10  10  10  10  14  14  14
- 22  22  22  42  42  42  70  70  70  89  81  66
- 80  54   7 104  69   6 124  80   6 137  92   6
-134  86   6 116  81   8 100  82  52  86  86  86
- 58  58  58  30  30  30  14  14  14   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   6   6   6  10  10  10  14  14  14
- 18  18  18  26  26  26  38  38  38  54  54  54
- 70  70  70  86  86  86  94  86  76  89  81  66
- 89  81  66  86  86  86  74  74  74  50  50  50
- 30  30  30  14  14  14   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6  18  18  18  34  34  34  58  58  58
- 82  82  82  89  81  66  89  81  66  89  81  66
- 94  86  66  94  86  76  74  74  74  50  50  50
- 26  26  26  14  14  14   6   6   6   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  6   6   6   6   6   6  14  14  14  18  18  18
- 30  30  30  38  38  38  46  46  46  54  54  54
- 50  50  50  42  42  42  30  30  30  18  18  18
- 10  10  10   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   6   6   6  14  14  14  26  26  26
- 38  38  38  50  50  50  58  58  58  58  58  58
- 54  54  54  42  42  42  30  30  30  18  18  18
- 10  10  10   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
-  6   6   6  10  10  10  14  14  14  18  18  18
- 18  18  18  14  14  14  10  10  10   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   6   6   6
- 14  14  14  18  18  18  22  22  22  22  22  22
- 18  18  18  14  14  14  10  10  10   6   6   6
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  3 4 4  6 7 7
+8 10 10  8 10 10  6 8 8  6 7 7  3 4 4  2 2 2
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  4 5 5  17 18 17
+27 29 28  35 37 36  40 43 41  43 45 43  40 43 41  37 39 37
+32 34 33  27 30 29  23 25 24  17 21 21  15 18 18  12 15 15
+11 13 13  8 10 10  6 7 7  3 4 4  1 1 1  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  13 13 13  32 34 33  49 51 48  60 60 56  58 59 55
+55 57 54  55 56 53  49 51 48  43 45 43  39 40 39  33 37 35
+28 31 30  23 27 26  20 23 23  17 20 20  14 17 17  13 16 16
+11 14 14  10 13 13  10 12 12  9 11 11  8 10 10  6 7 7
+2 3 3  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  6 7 7  12 15 15
+12 15 15  8 9 9  2 3 3  0 0 0  1 1 1  25 27 26
+55 56 53  68 70 65  65 66 61  65 66 61  63 64 60  63 64 60
+58 59 55  51 52 50  47 48 46  41 42 42  35 37 36  30 32 31
+26 28 27  20 24 24  18 22 22  16 19 19  14 17 17  13 16 16
+12 15 15  11 14 14  10 13 13  10 12 12  9 11 11  8 10 10
+8 9 9  6 8 8  3 3 3  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 7 7  20 24 24  23 27 26
+23 27 26  18 22 22  11 13 13  23 24 24  61 63 57  72 73 67
+72 73 67  68 70 65  68 70 65  68 70 65  63 64 60  58 59 55
+55 56 53  47 48 46  41 42 42  35 37 36  30 32 31  26 28 27
+20 24 24  18 22 22  16 20 20  15 19 19  14 17 17  13 16 16
+12 15 15  12 15 15  11 14 14  10 13 13  10 12 12  9 11 11
+8 10 10  8 9 9  7 9 9  6 7 7  1 2 2  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  1 1 1  4 5 5  5 6 5  4 5 5
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  15 19 19  40 41 39  53 55 47
+33 36 34  27 30 29  51 52 50  72 73 67  72 73 67  72 73 67
+72 73 67  68 70 65  68 70 65  63 64 60  58 59 55  51 52 50
+47 48 46  40 43 41  33 37 35  30 32 31  26 28 27  20 24 24
+18 22 22  17 21 21  16 19 19  14 18 18  14 17 17  13 17 17
+13 16 16  12 15 15  12 15 15  11 14 14  10 13 13  10 12 12
+9 11 11  8 10 10  8 9 9  7 9 9  6 8 8  3 4 4
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+2 2 2  6 8 8  10 12 12  10 12 12  10 12 12  10 12 12
+6 8 8  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  20 23 23  71 71 57  131 127 93
+115 113 82  63 64 60  72 73 67  72 73 67  72 73 67  72 73 67
+68 70 65  65 66 61  61 63 57  55 57 54  49 51 48  43 45 43
+39 40 39  33 36 34  28 31 30  23 27 26  20 24 24  20 23 23
+17 21 21  16 20 20  15 19 19  15 18 18  14 18 18  14 17 17
+13 17 17  13 16 16  12 15 15  12 15 15  11 14 14  10 13 13
+10 12 12  9 11 11  8 10 10  7 9 9  7 9 9  6 8 8
+4 5 5  0 0 0  0 0 0  0 0 0  1 1 1  6 7 7
+10 12 12  10 12 12  10 12 12  10 12 12  10 12 12  10 12 12
+10 12 12  3 4 4  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  18 22 22  71 71 57  144 139 99
+84 83 72  68 70 65  72 73 67  72 73 67  68 70 65  65 66 61
+63 64 60  55 57 54  51 52 50  47 48 46  40 43 41  35 37 36
+30 32 31  27 29 28  23 27 26  20 24 24  18 22 22  17 21 21
+16 20 20  15 19 19  15 19 19  15 19 19  15 18 18  14 18 18
+14 17 17  13 17 17  13 16 16  12 15 15  12 15 15  11 14 14
+10 13 13  9 12 12  9 11 11  8 10 10  7 9 9  6 8 8
+6 8 8  3 4 4  0 0 0  2 2 2  8 10 10  10 12 12
+10 12 12  10 12 12  11 13 13  36 38 35  61 61 53  48 49 45
+10 12 12  7 9 9  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  15 19 19  61 61 53  84 83 72
+68 70 65  72 73 67  68 70 65  68 70 65  63 64 60  58 59 55
+51 52 50  47 48 46  41 42 42  37 39 37  32 35 33  28 31 30
+23 27 26  20 24 24  20 23 23  18 22 22  17 21 21  17 21 21
+17 21 21  17 21 21  17 20 20  16 20 20  16 20 20  16 19 19
+15 18 18  14 18 18  13 17 17  13 16 16  12 15 15  12 15 15
+11 14 14  10 13 13  9 12 12  9 11 11  8 10 10  7 9 9
+6 8 8  6 8 8  5 6 5  9 11 11  10 12 12  10 12 12
+19 20 18  82 81 62  149 145 103  160 154 106  142 137 94  96 95 69
+10 12 12  10 12 12  1 1 1  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 12 12  44 46 43  68 70 65
+72 73 67  68 70 65  68 70 65  63 64 60  55 57 54  49 51 48
+43 45 43  39 40 39  33 37 35  30 32 31  26 28 27  23 27 26
+20 24 24  18 22 22  18 22 22  18 22 22  18 22 22  20 23 23
+20 24 24  23 25 24  23 25 24  22 24 23  20 23 23  18 22 22
+17 20 20  15 19 19  15 18 18  14 17 17  13 16 16  12 15 15
+11 14 14  11 13 13  10 12 12  9 11 11  8 10 10  8 9 9
+7 9 9  7 9 9  10 12 12  10 12 12  10 12 12  71 71 57
+164 159 111  186 182 128  186 182 128  171 165 117  151 147 98  96 95 69
+10 12 12  10 12 12  3 3 3  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  8 10 10  63 64 60  68 70 65
+72 73 67  68 70 65  63 64 60  55 57 54  47 48 46  40 43 41
+33 37 35  30 32 31  27 29 28  23 27 26  20 24 24  20 23 23
+18 22 22  18 22 22  20 23 22  21 25 23  23 27 26  27 29 28
+28 31 30  31 33 31  31 33 31  31 33 31  28 31 30  26 28 27
+23 25 24  20 23 22  16 20 20  15 18 18  14 17 17  13 16 16
+12 15 15  11 14 14  10 13 13  10 12 12  9 11 11  8 10 10
+10 12 12  10 13 13  10 12 12  12 14 14  96 95 69  165 161 109
+186 182 128  192 187 134  192 187 134  176 171 126  160 154 106  103 101 77
+10 12 12  10 12 12  5 6 5  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  35 37 36  68 70 65  72 73 67
+68 70 65  65 66 61  58 59 55  49 51 48  40 43 41  33 37 35
+28 31 30  23 27 26  20 24 24  20 23 23  18 22 22  18 22 22
+18 22 22  20 23 23  23 27 26  27 30 29  32 35 33  37 39 37
+40 43 41  44 46 43  46 47 43  44 46 43  40 43 41  36 38 35
+31 33 31  27 29 28  22 24 23  17 21 21  15 18 18  14 17 17
+13 16 16  12 15 15  11 14 14  11 14 14  11 13 13  13 16 16
+13 16 16  11 14 14  10 12 12  79 78 62  142 137 94  164 159 111
+178 174 128  192 187 134  192 187 134  176 171 126  160 154 106  96 95 69
+10 12 12  10 12 12  6 7 7  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  55 57 54  68 70 65  72 73 67
+68 70 65  63 64 60  55 56 53  43 45 43  35 37 36  28 31 30
+23 27 26  20 24 24  18 22 22  17 21 21  17 21 21  17 21 21
+20 24 24  25 27 26  31 33 31  38 39 37  46 47 43  53 55 47
+61 61 53  66 65 55  66 65 55  66 65 55  61 61 53  53 55 47
+46 47 43  37 39 37  30 33 30  24 26 24  17 21 21  15 18 18
+13 17 17  12 15 15  12 15 15  13 16 16  14 18 18  14 18 18
+14 17 17  12 15 15  30 31 28  118 116 76  134 131 96  160 154 106
+174 170 121  178 174 128  178 174 128  171 165 117  151 147 98  96 95 69
+10 12 12  10 12 12  6 8 8  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  63 64 60  68 70 65  68 70 65
+65 66 61  58 59 55  49 51 48  39 40 39  30 32 31  23 27 26
+20 24 24  18 22 22  17 21 21  16 20 20  17 21 21  20 23 23
+25 27 26  32 35 33  43 44 41  53 55 47  66 65 55  75 75 61
+82 81 62  84 83 72  87 86 72  87 86 72  82 81 62  75 75 61
+66 65 55  53 55 47  40 41 39  31 33 31  23 25 24  17 20 20
+14 18 18  13 16 16  12 15 15  12 15 15  13 17 17  14 18 18
+14 18 18  13 16 16  46 47 43  96 95 69  125 122 87  142 137 94
+160 154 106  165 161 109  164 159 111  155 149 109  142 137 94  75 75 61
+10 12 12  10 12 12  6 8 8  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  60 60 56  68 70 65  68 70 65
+63 64 60  55 57 54  46 47 45  35 37 36  27 30 29  23 25 24
+18 22 22  17 21 21  16 20 20  17 21 21  18 22 22  23 27 26
+31 33 31  43 44 41  55 56 53  71 71 57  84 83 72  92 91 72
+103 101 77  92 91 72  82 81 62  82 81 62  87 86 72  92 91 72
+84 83 72  71 71 57  55 56 53  43 44 41  30 33 30  22 24 23
+16 19 19  14 17 17  12 15 15  12 15 15  13 16 16  14 18 18
+14 18 18  14 17 17  43 44 41  82 81 62  118 116 76  125 122 87
+142 137 94  144 139 99  144 139 99  134 131 96  118 116 76  53 55 47
+10 12 12  10 12 12  6 8 8  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  47 48 46  63 64 60  63 64 60
+55 57 54  49 51 48  40 43 41  32 34 33  26 28 27  20 24 24
+18 22 22  16 20 20  16 20 20  17 21 21  20 24 24  28 31 30
+40 41 39  53 55 47  75 75 61  90 89 73  87 86 72  48 49 45
+14 14 13  2 2 2  1 2 2  1 1 1  1 1 1  2 2 2
+19 20 18  43 44 41  66 65 55  53 55 47  38 39 37  26 28 27
+18 22 22  14 18 18  13 16 16  12 15 15  12 15 15  13 17 17
+14 18 18  14 18 18  30 31 28  66 65 55  96 95 69  103 101 77
+118 116 76  118 116 76  118 116 76  118 116 76  103 101 77  36 38 35
+10 12 12  10 12 12  6 7 7  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  28 31 30  55 57 54  51 52 50
+49 51 48  41 42 42  35 37 36  28 31 30  23 27 26  20 23 23
+17 21 21  16 20 20  16 20 20  18 22 22  23 27 26  33 36 34
+48 49 45  71 71 57  82 81 62  43 44 41  8 9 9  6 7 7
+6 7 7  6 7 7  6 7 7  5 6 5  4 5 5  3 4 4
+2 3 3  1 2 2  4 5 4  36 38 35  48 49 45  32 35 33
+21 25 23  16 19 19  13 17 17  12 15 15  12 15 15  13 16 16
+14 18 18  14 18 18  16 18 16  36 38 35  61 61 53  82 81 62
+96 95 69  96 95 69  96 95 69  96 95 69  79 78 62  19 20 18
+10 12 12  10 12 12  4 5 5  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  13 13 13  46 47 45  43 45 43
+40 43 41  35 37 36  30 32 31  23 27 26  20 24 24  18 22 22
+17 21 21  16 20 20  17 21 21  20 23 23  27 30 29  40 41 39
+61 61 53  53 55 47  16 17 16  9 11 11  10 12 12  10 12 12
+10 12 12  10 12 12  10 12 12  9 11 11  8 10 10  8 9 9
+6 8 8  5 6 5  4 5 5  2 3 3  19 20 18  38 39 37
+26 28 27  17 21 21  14 17 17  13 16 16  12 15 15  12 15 15
+13 17 17  14 18 18  12 15 15  13 12 7  30 31 28  46 47 43
+53 55 47  66 65 55  66 65 55  53 55 47  36 38 35  10 12 12
+10 12 12  10 12 12  2 3 3  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  1 1 1  33 37 35  35 37 36
+32 35 33  28 31 30  23 27 26  20 24 24  18 22 22  17 21 21
+16 20 20  16 20 20  17 21 21  21 25 23  31 33 31  44 46 43
+31 33 31  11 13 13  12 14 14  12 15 15  13 16 16  14 17 17
+14 17 17  14 17 17  14 17 17  13 16 16  12 15 15  12 14 14
+11 13 13  9 11 11  8 10 10  6 8 8  4 5 5  17 18 17
+30 33 30  20 23 22  15 18 18  13 16 16  12 15 15  12 14 14
+13 16 16  14 17 17  14 18 18  11 12 11  7 7 5  16 17 12
+21 22 20  30 31 28  25 27 25  21 22 20  14 14 13  10 12 12
+10 12 12  9 11 11  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  18 22 22  27 30 29
+27 29 28  40 41 39  53 55 47  53 55 47  53 55 47  46 47 43
+25 27 25  16 20 20  17 21 21  23 25 24  31 33 31  20 20 20
+12 15 15  14 17 17  15 19 19  16 20 20  17 21 21  18 22 22
+18 22 22  18 22 22  18 22 22  17 21 21  17 21 21  16 19 19
+15 18 18  13 16 16  12 15 15  10 12 12  8 10 10  6 8 8
+21 22 21  22 24 23  15 19 19  13 17 17  13 16 16  12 15 15
+12 15 15  13 17 17  14 18 18  14 18 18  13 15 14  10 9 6
+7 7 5  7 7 5  7 7 5  9 11 11  10 12 12  10 12 12
+10 12 12  6 7 7  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  16 17 12  82 81 62
+118 116 76  118 116 76  161 156 96  161 156 96  161 156 96  118 116 76
+118 116 76  96 95 69  53 55 47  22 24 23  14 17 17  13 16 16
+15 19 19  17 21 21  18 22 22  20 24 24  20 24 24  23 27 26
+23 27 26  23 27 26  23 27 26  23 27 26  23 27 26  20 24 24
+20 23 23  17 21 21  16 19 19  14 17 17  12 15 15  10 12 12
+9 11 11  20 23 22  16 19 19  14 17 17  13 16 16  12 15 15
+11 14 14  13 16 16  14 17 17  14 18 18  14 17 17  12 15 15
+10 12 12  10 12 12  10 12 12  10 12 12  10 12 12  10 12 12
+9 11 11  1 1 1  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  53 55 47  161 156 96
+161 156 96  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  161 156 96  118 116 76  96 95 69  21 22 20  16 19 19
+18 22 22  20 24 24  23 27 26  23 27 26  26 28 27  27 30 29
+27 30 29  18 22 22  12 14 14  8 10 10  9 11 11  17 21 21
+23 27 26  23 27 26  20 24 24  18 22 22  16 20 20  14 17 17
+12 14 14  14 17 17  16 20 20  14 17 17  13 17 17  13 16 16
+12 15 15  12 15 15  13 17 17  14 18 18  14 17 17  13 16 16
+11 13 13  10 12 12  10 12 12  10 12 12  10 12 12  10 12 12
+4 5 5  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  13 12 7  118 116 76  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  161 156 96  118 116 76  30 31 28
+20 24 24  23 27 26  27 30 29  28 31 30  30 32 31  23 27 26
+16 19 19  17 21 21  12 15 15  9 11 11  10 12 12  9 11 11
+20 24 24  28 31 30  26 28 27  23 27 26  20 24 24  17 21 21
+15 19 19  13 16 16  16 19 19  14 18 18  14 17 17  13 16 16
+12 15 15  11 14 14  13 16 16  14 17 17  14 18 18  14 17 17
+12 15 15  10 12 12  10 12 12  10 12 12  10 12 12  8 9 9
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  82 81 62  161 156 96  230 229 82
+230 229 82  233 233 100  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  161 156 96  118 116 76
+27 29 28  27 30 29  30 32 31  30 32 31  23 27 26  20 24 24
+26 28 27  17 21 21  6 7 7  72 73 67  145 141 105  15 15 15
+14 17 17  33 37 35  30 32 31  28 31 30  26 28 27  23 27 26
+20 23 23  16 20 20  15 19 19  14 18 18  14 17 17  13 16 16
+12 15 15  11 14 14  12 15 15  13 17 17  14 18 18  14 17 17
+13 16 16  11 13 13  10 12 12  10 12 12  9 11 11  1 1 1
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  16 17 12  161 156 96  230 229 82  230 229 82
+243 242 120  235 234 117  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  161 156 96
+82 81 62  28 31 30  28 31 30  27 30 29  28 31 30  30 32 31
+33 37 35  13 16 16  3 3 3  105 104 92  210 208 158  12 14 14
+17 21 21  33 37 35  33 37 35  32 35 33  30 32 31  27 30 29
+23 27 26  20 23 23  17 20 20  15 18 18  14 18 18  13 17 17
+13 16 16  12 15 15  11 14 14  13 16 16  14 17 17  14 18 18
+13 17 17  12 15 15  10 12 12  10 12 12  3 4 4  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  96 95 69  230 229 82  230 229 82  244 244 132
+241 241 143  243 242 120  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+161 156 96  46 47 43  32 35 33  33 37 35  33 37 35  33 37 35
+40 43 41  23 27 26  1 1 1  2 2 2  24 26 24  14 17 17
+23 27 26  33 37 35  33 37 35  33 37 35  33 37 35  30 32 31
+27 30 29  23 27 26  20 23 23  15 18 18  14 18 18  14 17 17
+13 16 16  12 15 15  11 14 14  12 15 15  13 17 17  14 17 17
+14 17 17  13 16 16  11 13 13  6 8 8  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  16 17 12  161 156 96  230 229 82  235 234 117  239 239 170
+239 239 170  236 236 101  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  118 116 76  33 37 35  33 37 35  37 39 37  37 39 37
+43 45 43  49 51 48  20 24 24  8 10 10  17 20 20  35 37 36
+33 37 35  40 43 41  37 39 37  35 37 36  33 37 35  33 37 35
+30 32 31  27 30 29  23 27 26  15 19 19  14 18 18  14 17 17
+13 17 17  13 16 16  12 15 15  11 14 14  13 16 16  14 17 17
+14 17 17  13 17 17  11 14 14  4 5 5  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  96 95 69  230 229 82  230 229 82  239 239 170  251 251 187
+241 241 143  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  161 156 96  36 38 35  33 37 35  33 37 35  33 37 35
+37 39 37  47 48 46  55 57 54  55 57 54  49 51 48  43 45 43
+43 45 43  43 45 43  40 43 41  40 43 41  37 39 37  33 37 35
+33 37 35  28 31 30  26 28 27  16 20 20  15 18 18  14 18 18
+14 17 17  13 16 16  12 15 15  11 14 14  12 15 15  13 17 17
+14 17 17  14 17 17  8 10 10  5 7 7  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+16 17 12  230 229 82  230 229 82  243 242 120  251 251 187  251 251 187
+246 246 123  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  66 65 55  30 32 31  32 35 33  33 37 35
+33 37 35  37 39 37  40 43 41  47 48 46  49 51 48  51 52 50
+55 57 54  55 57 54  51 52 50  47 48 46  43 45 43  39 40 39
+33 37 35  30 32 31  26 28 27  17 21 21  15 19 19  14 18 18
+14 17 17  13 16 16  12 15 15  12 14 14  11 14 14  13 16 16
+14 17 17  12 15 15  7 9 9  6 8 8  1 1 1  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+96 95 69  230 229 82  230 229 82  239 239 170  251 251 187  239 239 170
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  96 95 69  27 30 29  28 31 30  30 32 31
+33 37 35  40 43 41  46 47 45  55 57 54  63 64 60  72 73 67
+72 73 67  72 73 67  72 73 67  65 66 61  55 57 54  47 48 46
+39 40 39  32 35 33  27 30 29  17 21 21  15 19 19  15 18 18
+14 18 18  13 17 17  13 16 16  12 15 15  11 14 14  12 14 14
+13 16 16  9 11 11  7 9 9  9 11 11  66 65 55  115 113 82
+21 22 20  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  13 12 7
+230 229 82  230 229 82  236 236 101  251 251 187  251 251 187  246 246 123
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  118 116 76  23 27 26  26 28 27  32 35 33
+51 52 50  90 89 73  110 109 94  145 141 105  168 163 120  177 172 135
+177 172 135  188 184 146  188 184 146  181 176 137  194 191 148  188 184 146
+184 179 149  188 184 146  188 184 146  156 151 111  177 172 135  181 176 137
+177 172 135  168 163 120  168 163 120  158 153 112  156 151 111  158 153 112
+156 151 111  158 153 112  177 172 135  188 184 146  188 184 146  194 189 146
+36 38 35  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  82 81 62
+230 229 82  230 229 82  244 244 132  251 251 187  244 244 132  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  161 156 96  82 81 62
+96 95 69  230 229 82  181 178 103  110 109 94  156 151 111  188 184 146
+188 184 146  197 193 154  188 184 146  184 181 136  188 184 146  168 163 120
+168 163 120  178 174 128  156 151 111  158 153 112  174 170 121  156 151 111
+156 151 111  158 153 112  156 151 111  168 163 120  178 174 128  181 176 137
+176 171 126  178 174 128  184 181 136  176 171 126  178 174 128  184 181 136
+176 171 126  178 174 128  184 181 136  164 159 111  155 149 109  96 95 69
+1 1 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  2 2 1  161 156 96
+230 229 82  230 229 82  244 244 132  244 244 132  236 236 101  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  46 47 43  82 81 62
+158 153 112  197 193 154  194 189 146  184 181 136  188 184 146  168 163 120
+156 151 111  137 133 100  131 127 93  137 133 100  137 133 100  158 153 112
+121 119 87  137 133 100  156 151 111  145 141 105  99 98 80  84 83 72
+63 64 60  52 53 49  40 43 41  33 36 34  36 38 35  36 38 35
+38 39 37  43 44 41  43 44 41  46 47 43  48 49 45  48 49 45
+46 47 43  36 38 35  30 31 28  19 20 18  6 7 7  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  36 38 35  230 229 82
+230 229 82  230 229 82  246 246 123  236 236 101  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  53 55 47  121 119 87
+176 171 126  171 165 117  161 156 96  82 81 62  53 55 47  33 37 35
+39 40 39  63 64 60  99 98 80  121 119 87  137 133 100  177 172 135
+176 171 126  184 181 136  131 127 93  131 127 93  110 109 94  84 83 72
+51 52 50  39 40 39  27 29 28  18 22 22  16 19 19  15 19 19
+15 19 19  14 18 18  14 17 17  13 16 16  12 15 15  11 14 14
+10 13 13  9 12 12  9 11 11  8 9 9  7 9 9  1 1 1
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  118 116 76  230 229 82
+230 229 82  230 229 82  236 236 101  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  96 95 69  71 71 57
+36 38 35  118 116 76  118 116 76  12 15 15  15 18 18  20 24 24
+33 37 35  55 56 53  84 83 72  110 109 94  145 141 105  110 109 94
+168 163 120  121 119 87  156 151 111  131 127 93  87 86 72  61 63 57
+47 48 46  28 31 30  18 22 22  15 19 19  15 18 18  15 19 19
+15 19 19  14 18 18  14 17 17  13 17 17  13 16 16  12 15 15
+11 13 13  10 12 12  9 11 11  8 10 10  7 9 9  3 3 3
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  1 1 0  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  161 156 96
+161 156 96  230 229 82  118 116 76  11 14 14  14 17 17  18 22 22
+27 30 29  40 43 41  60 60 56  84 83 72  105 104 92  110 109 94
+110 109 94  110 109 94  99 98 80  90 89 73  68 70 65  47 48 46
+32 34 33  23 25 24  20 23 23  17 21 21  15 19 19  14 17 17
+15 19 19  15 18 18  14 18 18  13 17 17  13 16 16  12 15 15
+11 14 14  10 12 12  9 11 11  8 10 10  7 9 9  4 5 5
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  16 17 12  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  161 156 96  118 116 76  11 13 13  13 16 16  15 19 19
+20 24 24  30 32 31  40 43 41  51 52 50  63 64 60  72 73 67
+65 66 61  65 66 61  65 66 61  55 57 54  46 47 45  33 37 35
+27 29 28  20 24 24  17 21 21  16 20 20  16 20 20  15 19 19
+15 19 19  15 19 19  14 18 18  14 17 17  13 16 16  12 15 15
+11 14 14  10 13 13  9 12 12  8 10 10  7 9 9  6 7 7
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  53 55 47  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+161 156 96  118 116 76  53 55 47  10 13 13  12 15 15  14 17 17
+17 20 20  20 24 24  27 29 28  32 34 33  37 39 37  40 43 41
+43 45 43  41 42 42  35 37 36  30 32 31  28 31 30  23 27 26
+20 23 23  17 21 21  16 20 20  16 20 20  16 20 20  16 19 19
+15 19 19  15 19 19  14 18 18  14 17 17  13 16 16  12 15 15
+11 14 14  10 13 13  9 12 12  9 11 11  8 10 10  10 12 12
+1 1 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  82 81 62  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  161 156 96  161 156 96
+118 116 76  82 81 62  13 14 12  10 13 13  12 15 15  13 17 17
+15 19 19  16 20 20  20 23 23  20 24 24  23 27 26  26 28 27
+26 28 27  26 28 27  23 27 26  18 22 22  20 23 23  17 21 21
+17 21 21  16 20 20  16 20 20  16 20 20  16 20 20  16 19 19
+15 19 19  15 19 19  15 18 18  14 17 17  13 17 17  13 16 16
+12 15 15  12 14 14  12 14 14  12 14 14  12 14 14  23 24 24
+6 8 8  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  118 116 76  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  161 156 96  161 156 96  118 116 76
+71 71 57  13 14 12  9 12 12  10 13 13  12 15 15  13 17 17
+15 18 18  15 19 19  16 20 20  17 21 21  17 21 21  18 22 22
+18 22 22  18 22 22  17 21 21  16 19 19  15 18 18  14 18 18
+16 19 19  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+15 19 19  15 19 19  15 18 18  14 18 18  16 20 20  23 25 24
+17 21 21  25 27 26  47 48 46  47 48 46  51 52 50  72 73 67
+33 36 34  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  118 116 76  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  161 156 96  118 116 76  118 116 76  46 47 43
+9 11 11  9 11 11  10 12 12  11 13 13  12 15 15  14 17 17
+15 18 18  15 19 19  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+15 19 19  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+15 19 19  16 20 20  20 24 24  55 56 53  32 34 33  84 83 72
+90 89 73  110 109 94  110 109 94  105 104 92  110 109 94  110 109 94
+72 73 67  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  96 95 69  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  161 156 96  118 116 76  82 81 62  16 17 12  9 11 11
+9 11 11  9 12 12  10 13 13  12 14 14  13 16 16  14 18 18
+15 19 19  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 19 19  33 36 34  99 98 80  156 151 111  145 141 105  184 179 149
+168 163 120  184 179 149  177 172 135  156 151 111  145 141 105  110 109 94
+90 89 73  2 2 2  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  71 71 57  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  230 229 82
+230 229 82  161 156 96  230 229 82  230 229 82  230 229 82  161 156 96
+118 116 76  82 81 62  30 31 28  9 11 11  9 11 11  9 11 11
+10 12 12  10 13 13  11 14 14  13 16 16  14 17 17  15 18 18
+15 19 19  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+18 22 22  58 59 55  137 133 100  197 193 154  214 212 158  210 208 158
+197 193 154  184 179 149  184 179 149  137 133 100  110 109 94  99 98 80
+84 83 72  10 10 9  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  16 17 12  230 229 82  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  230 229 82  161 156 96
+161 156 96  161 156 96  161 156 96  161 156 96  118 116 76  71 71 57
+21 22 20  12 14 14  11 13 13  10 12 12  10 12 12  10 13 13
+11 13 13  12 15 15  13 16 16  14 17 17  14 18 18  15 19 19
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  17 21 21
+23 27 26  84 83 72  184 179 149  251 251 187  210 208 158  184 179 149
+184 179 149  156 151 111  110 109 94  84 83 72  63 64 60  51 52 50
+18 22 22  6 8 8  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  118 116 76  230 229 82
+230 229 82  230 229 82  230 229 82  230 229 82  161 156 96  161 156 96
+161 156 96  161 156 96  118 116 76  53 55 47  20 23 22  16 19 19
+13 16 16  12 15 15  12 14 14  11 14 14  11 14 14  11 14 14
+12 15 15  13 16 16  14 17 17  15 19 19  16 20 20  17 21 21
+23 27 26  18 22 22  20 24 24  23 27 26  30 32 31  17 21 21
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+23 27 26  33 37 35  137 133 100  156 151 111  158 153 112  105 104 92
+105 104 92  68 70 65  39 40 39  18 22 22  12 14 14  12 15 15
+9 11 11  4 5 5  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  16 17 12  230 229 82
+230 229 82  230 229 82  230 229 82  161 156 96  118 116 76  118 116 76
+118 116 76  66 65 55  43 45 43  32 34 33  25 27 26  20 23 22
+17 20 20  15 18 18  14 17 17  15 18 18  13 16 16  14 17 17
+14 18 18  16 20 20  32 34 33  55 57 54  58 59 55  72 73 67
+105 104 92  55 57 54  65 66 61  63 64 60  40 43 41  33 37 35
+41 42 42  20 24 24  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+17 21 21  26 28 27  30 32 31  35 37 36  68 70 65  39 40 39
+23 27 26  15 18 18  13 16 16  11 14 14  9 12 12  8 10 10
+7 9 9  6 7 7  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  36 38 35
+230 229 82  230 229 82  230 229 82  96 95 69  30 31 28  49 51 48
+90 89 73  68 70 65  55 57 54  47 48 46  47 48 46  43 45 43
+32 34 33  43 45 43  43 45 43  23 27 26  25 27 26  40 43 41
+40 43 41  90 89 73  110 109 94  145 141 105  156 151 111  156 151 111
+184 179 149  184 179 149  177 172 135  184 179 149  137 133 100  84 83 72
+105 104 92  63 64 60  49 51 48  47 48 46  28 31 30  18 22 22
+16 20 20  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  15 19 19  15 19 19  15 19 19  18 22 22  15 19 19
+13 16 16  12 15 15  11 14 14  10 13 13  9 12 12  9 11 11
+8 10 10  6 8 8  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+30 31 28  230 229 82  71 71 57  2 2 1  0 0 0  58 59 55
+105 104 92  84 83 72  65 66 61  84 83 72  110 109 94  110 109 94
+145 141 105  105 104 92  110 109 94  110 109 94  84 83 72  110 109 94
+158 153 112  197 193 154  197 193 154  239 239 170  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  210 208 158  197 193 154
+197 193 154  184 179 149  145 141 105  137 133 100  105 104 92  47 48 46
+20 23 23  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 19 19  15 19 19  15 19 19  14 18 18  14 17 17
+13 17 17  13 16 16  12 14 14  12 14 14  13 13 13  13 13 13
+13 13 13  12 12 12  10 10 9  6 7 7  2 2 2  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  1 1 0  0 0 0  0 0 0  65 66 61
+105 104 92  84 83 72  84 83 72  110 109 94  184 179 149  210 208 158
+210 208 158  210 208 158  214 212 158  197 193 154  214 212 158  210 208 158
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  251 251 187  239 239 170  251 251 187  184 179 149  84 83 72
+26 28 27  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  15 19 19  15 19 19  15 18 18  14 18 18
+13 17 17  13 16 16  15 15 15  14 14 13  14 14 13  14 14 13
+13 13 13  13 13 13  12 12 12  12 12 12  12 12 12  3 4 4
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  72 73 67
+105 104 92  99 98 80  84 83 72  99 98 80  177 172 135  197 193 154
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  214 212 158  197 193 154  99 98 80
+23 27 26  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  15 19 19  15 19 19  15 18 18  14 18 18
+14 17 17  16 16 16  16 16 16  16 16 16  15 15 15  14 14 13
+14 14 13  13 13 13  13 13 13  12 12 12  12 12 12  12 12 12
+3 3 3  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  84 83 72
+110 109 94  99 98 80  72 73 67  63 64 60  99 98 80  177 172 135
+184 179 149  210 208 158  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  210 208 158  184 179 149  177 172 135  110 109 94  33 37 35
+17 21 21  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+16 20 20  16 20 20  15 19 19  15 19 19  15 19 19  14 18 18
+15 18 18  18 19 18  18 19 18  17 17 17  16 16 16  15 15 15
+14 14 13  13 13 13  13 13 13  12 12 12  12 12 12  12 12 12
+10 10 9  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  2 2 2  105 104 92
+108 107 93  99 98 80  72 73 67  63 64 60  51 52 50  87 86 72
+105 104 92  110 109 94  108 107 93  156 151 111  184 179 149  184 179 149
+197 193 154  197 193 154  197 193 154  184 179 149  184 179 149  177 172 135
+197 193 154  156 151 111  177 172 135  184 179 149  168 163 120  137 133 100
+145 141 105  110 109 94  99 98 80  47 48 46  55 57 54  15 19 19
+16 19 19  16 20 20  16 20 20  16 20 20  16 20 20  16 20 20
+17 20 20  17 21 21  16 20 20  16 19 19  15 19 19  16 19 19
+20 20 20  21 22 21  20 20 20  19 20 19  18 19 18  16 16 16
+15 15 15  14 14 13  13 13 13  13 13 13  12 12 12  12 12 12
+12 12 12  4 5 5  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  58 59 55  110 109 94
+105 104 92  90 89 73  72 73 67  55 57 54  43 45 43  39 40 39
+43 45 43  46 47 45  43 45 43  68 70 65  65 66 61  63 64 60
+108 107 93  72 73 67  105 104 92  90 89 73  72 73 67  40 43 41
+72 73 67  68 70 65  68 70 65  58 59 55  63 64 60  49 51 48
+43 45 43  33 36 34  27 30 29  20 24 24  16 20 20  15 19 19
+15 19 19  15 19 19  15 19 19  16 19 19  16 20 20  16 20 20
+17 21 21  20 24 24  20 23 22  17 21 21  17 20 20  20 20 20
+21 22 21  21 22 21  21 22 21  21 22 21  20 20 20  18 19 18
+16 16 16  15 15 15  13 13 13  13 13 13  12 12 12  12 12 12
+12 12 12  10 10 9  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  21 22 21  110 109 94  110 109 94
+105 104 92  84 83 72  68 70 65  51 52 50  41 42 42  33 37 35
+28 31 30  23 27 26  20 23 23  18 22 22  17 20 20  25 27 26
+26 28 27  27 30 29  25 27 26  20 23 23  23 27 26  30 32 31
+20 24 24  17 21 21  18 22 22  15 19 19  26 28 27  20 23 23
+14 18 18  15 19 19  15 18 18  15 19 19  15 19 19  15 19 19
+15 19 19  15 19 19  15 19 19  15 19 19  15 19 19  16 19 19
+16 20 20  22 24 23  24 26 24  22 24 23  20 23 22  22 24 23
+24 26 24  24 26 24  23 24 24  22 24 23  21 22 21  19 20 19
+17 17 17  15 15 15  14 14 13  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  2 2 2  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  2 2 2  99 98 80  110 109 94  108 107 93
+105 104 92  84 83 72  63 64 60  49 51 48  39 40 39  32 34 33
+27 30 29  23 25 24  20 23 23  17 20 20  15 19 19  14 18 18
+14 17 17  13 17 17  13 17 17  13 17 17  13 17 17  13 17 17
+14 17 17  14 17 17  14 17 17  14 17 17  14 17 17  14 17 17
+14 18 18  14 18 18  14 18 18  14 18 18  15 18 18  15 19 19
+15 19 19  15 19 19  15 19 19  15 19 19  15 19 19  15 19 19
+15 19 19  17 21 21  27 29 28  26 28 27  25 27 26  25 27 26
+27 29 28  27 29 28  26 28 27  24 26 24  21 22 21  20 20 20
+18 19 18  16 16 16  14 14 13  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  4 5 5  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  51 52 50  110 109 94  110 109 94  105 104 92
+90 89 73  72 73 67  55 57 54  43 45 43  35 37 36  30 32 31
+26 28 27  20 24 24  17 21 21  16 19 19  15 18 18  14 17 17
+13 16 16  13 16 16  13 16 16  13 16 16  13 16 16  13 16 16
+13 16 16  13 16 16  13 16 16  13 17 17  13 17 17  14 17 17
+14 17 17  14 17 17  14 17 17  14 18 18  14 18 18  14 18 18
+15 18 18  15 18 18  15 19 19  15 19 19  15 19 19  15 19 19
+15 19 19  15 19 19  27 29 28  32 34 33  28 31 30  27 29 28
+30 32 31  30 32 31  30 31 28  26 28 27  23 24 24  21 22 21
+19 20 19  16 16 16  14 14 13  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  6 7 7  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  3 3 3  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  10 10 9  108 107 93  110 109 94  108 107 93  99 98 80
+84 83 72  63 64 60  49 51 48  40 43 41  33 36 34  27 30 29
+23 27 26  18 22 22  17 20 20  15 18 18  14 17 17  13 16 16
+13 16 16  13 16 16  12 15 15  12 15 15  12 15 15  12 15 15
+13 16 16  13 16 16  13 16 16  13 16 16  13 16 16  13 16 16
+13 17 17  13 17 17  14 17 17  14 17 17  14 17 17  14 18 18
+14 18 18  14 18 18  15 18 18  15 18 18  15 19 19  15 19 19
+15 19 19  15 19 19  17 21 21  33 36 34  32 34 33  31 33 31
+33 36 34  33 36 34  31 33 31  27 29 28  25 27 26  21 22 21
+19 20 19  17 17 17  15 15 15  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  8 8 7  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  63 64 60  137 133 100  43 45 43  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  68 70 65  110 109 94  110 109 94  105 104 92  84 83 72
+68 70 65  55 57 54  43 45 43  35 37 36  30 32 31  26 28 27
+20 24 24  17 21 21  16 19 19  14 17 17  13 16 16  12 15 15
+12 15 15  12 15 15  12 15 15  12 15 15  12 15 15  12 15 15
+12 15 15  12 15 15  12 15 15  12 15 15  12 15 15  13 16 16
+13 16 16  13 16 16  13 16 16  13 17 17  13 17 17  14 17 17
+14 17 17  14 17 17  14 18 18  14 18 18  14 18 18  15 18 18
+15 19 19  15 19 19  15 19 19  20 24 24  32 34 33  35 37 36
+37 39 37  35 37 36  33 36 34  30 32 31  26 28 27  22 24 23
+20 20 20  17 17 17  15 15 15  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  8 8 7  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+1 1 1  99 98 80  184 179 149  184 179 149  68 70 65  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+15 15 15  110 109 94  110 109 94  108 107 93  99 98 80  72 73 67
+61 63 57  49 51 48  39 40 39  33 36 34  27 30 29  23 25 24
+18 22 22  16 19 19  14 17 17  13 16 16  12 15 15  12 15 15
+11 14 14  11 14 14  11 14 14  11 14 14  11 14 14  11 14 14
+11 14 14  11 14 14  12 14 14  12 15 15  12 15 15  12 15 15
+12 15 15  13 16 16  13 16 16  13 16 16  13 16 16  13 16 16
+13 17 17  14 17 17  14 17 17  14 17 17  14 18 18  14 18 18
+14 18 18  15 18 18  15 19 19  15 19 19  30 32 31  38 39 37
+39 40 39  39 40 39  35 37 36  31 33 31  27 29 28  22 24 23
+20 20 20  17 17 17  15 15 15  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  8 8 7  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  3 3 3
+110 109 94  197 193 154  210 208 158  184 179 149  68 70 65  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+68 70 65  110 109 94  110 109 94  105 104 92  84 83 72  65 66 61
+51 52 50  43 45 43  35 37 36  30 32 31  25 27 26  20 23 23
+17 20 20  15 18 18  13 16 16  12 15 15  12 15 15  11 14 14
+11 14 14  11 14 14  11 13 13  11 13 13  11 13 13  11 13 13
+11 14 14  11 14 14  11 14 14  11 14 14  11 14 14  11 14 14
+12 15 15  12 15 15  12 15 15  12 15 15  13 16 16  13 16 16
+13 16 16  13 16 16  13 17 17  13 17 17  14 17 17  14 17 17
+14 18 18  14 18 18  14 18 18  16 19 19  37 39 37  41 42 42
+41 42 42  41 42 42  38 39 37  32 34 33  27 29 28  23 24 24
+21 22 21  17 17 17  15 15 15  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  8 8 7  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  11 11 11  137 133 100
+197 193 154  251 251 187  239 239 170  184 179 149  31 33 31  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  12 12 12
+110 109 94  110 109 94  105 104 92  90 89 73  72 73 67  58 59 55
+46 47 45  37 39 37  31 33 31  26 28 27  20 24 24  17 21 21
+15 18 18  13 16 16  12 15 15  12 14 14  11 13 13  11 13 13
+10 13 13  10 13 13  10 13 13  10 13 13  10 13 13  10 13 13
+10 13 13  10 13 13  11 13 13  11 13 13  11 14 14  11 14 14
+11 14 14  11 14 14  12 14 14  12 15 15  12 15 15  12 15 15
+13 16 16  13 16 16  13 16 16  13 16 16  13 17 17  13 17 17
+14 17 17  14 17 17  14 18 18  23 27 26  41 42 42  41 42 42
+43 45 43  41 42 42  39 40 39  33 36 34  27 29 28  23 24 24
+21 22 21  17 17 17  15 15 15  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  6 7 7  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  27 29 28  168 163 120  210 208 158
+251 251 187  251 251 187  210 208 158  137 133 100  1 1 1  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  60 60 56
+110 109 94  105 104 92  105 104 92  84 83 72  65 66 61  51 52 50
+40 43 41  33 36 34  27 30 29  23 25 24  18 22 22  16 19 19
+14 17 17  12 15 15  11 14 14  11 14 14  10 13 13  10 13 13
+10 13 13  10 12 12  10 12 12  10 12 12  10 12 12  10 12 12
+10 12 12  10 12 12  10 13 13  10 13 13  10 13 13  11 13 13
+11 13 13  11 14 14  11 14 14  11 14 14  11 14 14  12 15 15
+12 15 15  12 15 15  12 15 15  13 16 16  13 16 16  13 16 16
+13 17 17  13 17 17  14 17 17  32 34 33  43 45 43  43 45 43
+43 45 43  43 45 43  39 40 39  33 36 34  27 29 28  23 24 24
+21 22 21  17 17 17  15 15 15  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  6 7 7  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  1 1 1  68 70 65  184 179 149  210 208 158  251 251 187
+251 251 187  214 212 158  184 179 149  37 39 37  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  6 7 7  105 104 92
+105 104 92  105 104 92  99 98 80  72 73 67  58 59 55  46 47 45
+35 37 36  30 32 31  25 27 26  20 23 23  16 19 19  14 17 17
+12 15 15  12 14 14  11 13 13  10 13 13  10 12 12  10 12 12
+10 12 12  10 12 12  9 12 12  9 12 12  9 12 12  9 12 12
+10 12 12  10 12 12  10 12 12  10 12 12  10 12 12  10 13 13
+10 13 13  10 13 13  11 13 13  11 13 13  11 14 14  11 14 14
+11 14 14  12 15 15  12 15 15  12 15 15  12 15 15  13 16 16
+13 16 16  13 16 16  17 20 20  41 42 42  46 47 45  46 47 45
+46 47 45  43 45 43  40 41 39  33 36 34  27 29 28  23 24 24
+20 20 20  17 17 17  15 15 15  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  4 5 5  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+15 15 15  110 109 94  197 193 154  214 212 158  251 251 187  251 251 187
+239 239 170  184 179 149  84 83 72  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  47 48 46  105 104 92
+105 104 92  99 98 80  84 83 72  68 70 65  51 52 50  40 43 41
+32 34 33  27 29 28  22 24 23  17 21 21  15 18 18  13 16 16
+12 15 15  11 13 13  10 13 13  10 12 12  9 12 12  9 12 12
+9 12 12  9 12 12  9 11 11  9 11 11  9 11 11  9 11 11
+9 12 12  9 12 12  9 12 12  9 12 12  10 12 12  10 12 12
+10 12 12  10 12 12  10 13 13  10 13 13  10 13 13  11 13 13
+11 14 14  11 14 14  11 14 14  12 14 14  12 15 15  12 15 15
+12 15 15  13 16 16  28 31 30  43 45 43  47 48 46  47 48 46
+47 48 46  43 45 43  40 41 39  33 36 34  27 29 28  22 24 23
+20 20 20  17 17 17  15 15 15  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  3 4 4  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  1 1 1  60 60 56
+177 172 135  197 193 154  251 251 187  251 251 187  251 251 187  251 251 187
+184 179 149  110 109 94  3 4 4  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  1 1 1  99 98 80  105 104 92
+99 98 80  87 86 72  84 83 72  63 64 60  46 47 45  35 37 36
+30 32 31  25 27 26  18 22 22  16 19 19  14 17 17  12 15 15
+11 14 14  10 13 13  9 12 12  9 12 12  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 11 11  9 12 12  9 12 12
+9 12 12  10 12 12  10 12 12  10 12 12  10 13 13  10 13 13
+10 13 13  11 13 13  11 14 14  11 14 14  11 14 14  12 15 15
+12 15 15  14 17 17  41 42 42  47 48 46  49 51 48  51 52 50
+47 48 46  43 45 43  40 41 39  33 36 34  27 29 28  22 24 23
+19 20 19  16 16 16  14 14 13  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  2 2 2  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  23 24 24  137 133 100  184 179 149
+210 208 158  251 251 187  251 251 187  251 251 187  251 251 187  184 179 149
+110 109 94  13 13 13  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  30 32 31  105 104 92  99 98 80
+84 83 72  84 83 72  72 73 67  55 57 54  41 42 42  32 34 33
+27 29 28  20 24 24  17 20 20  14 17 17  13 16 16  12 14 14
+10 13 13  10 12 12  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 12 12  9 12 12  10 12 12  10 12 12  10 12 12
+10 13 13  10 13 13  10 13 13  11 13 13  11 14 14  11 14 14
+11 14 14  27 29 28  55 56 53  72 73 67  51 52 50  51 52 50
+49 51 48  43 45 43  39 40 39  32 34 33  26 28 27  21 22 21
+19 20 19  16 16 16  18 19 17  13 13 13  12 12 12  12 12 12
+12 12 12  12 12 12  1 1 1  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  8 8 7  84 83 72  184 179 149  197 193 154  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  184 179 149  145 141 105
+19 20 19  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  14 14 13  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  72 73 67  105 104 92  84 83 72
+72 73 67  84 83 72  68 70 65  49 51 48  39 40 39  30 32 31
+25 27 26  18 22 22  15 18 18  13 16 16  12 15 15  11 13 13
+10 12 12  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 12 12  9 12 12  9 12 12
+10 12 12  10 12 12  10 12 12  10 13 13  10 13 13  11 13 13
+13 16 16  41 42 42  99 98 80  158 153 112  65 66 61  51 52 50
+49 51 48  43 45 43  39 40 39  31 33 31  25 27 26  21 22 21
+21 22 21  68 70 65  55 56 53  13 13 13  12 12 12  12 12 12
+12 12 12  11 11 11  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  3 3 3
+63 64 60  158 153 112  184 179 149  210 208 158  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  184 179 149  137 133 100  27 29 28
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+21 22 21  110 109 94  5 6 5  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  13 13 13  105 104 92  90 89 73  72 73 67
+68 70 65  84 83 72  63 64 60  46 47 45  35 37 36  27 29 28
+22 24 23  17 20 20  14 17 17  12 15 15  11 14 14  10 12 12
+10 12 12  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 12 12  9 12 12  10 12 12  10 12 12  10 13 13  10 13 13
+30 32 31  47 48 46  177 172 135  210 208 158  137 133 100  55 56 53
+49 51 48  43 45 43  38 39 37  31 33 31  25 27 26  22 24 23
+110 109 94  184 179 149  63 64 60  13 13 13  12 12 12  12 12 12
+12 12 12  8 9 9  0 0 0  1 1 1  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  21 22 21  105 104 92
+184 179 149  210 208 158  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  251 251 187  184 179 149  145 141 105  23 24 24  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+68 70 65  184 179 149  105 104 92  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  51 52 50  99 98 80  84 83 72  63 64 60
+68 70 65  72 73 67  55 57 54  41 42 42  32 34 33  25 27 26
+20 23 23  16 19 19  13 16 16  12 14 14  10 13 13  10 12 12
+9 11 11  9 11 11  9 11 11  9 11 11  9 11 11  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 11 11  9 12 12  9 12 12  10 12 12  17 20 20
+46 47 45  72 73 67  210 208 158  251 251 187  210 208 158  63 64 60
+49 51 48  43 45 43  37 39 37  30 32 31  24 26 24  105 104 92
+210 208 158  197 193 154  47 48 46  13 13 13  12 12 12  12 12 12
+12 12 12  6 7 7  33 36 34  48 49 45  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  8 8 7  23 24 24  55 56 53  110 109 94
+210 208 158  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  184 179 149  110 109 94  20 20 20  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+110 109 94  251 251 187  210 208 158  47 48 46  0 0 0  0 0 0
+0 0 0  1 1 1  90 89 73  90 89 73  72 73 67  55 56 53
+72 73 67  68 70 65  51 52 50  37 39 37  28 31 30  23 25 24
+17 21 21  15 18 18  12 15 15  11 14 14  10 13 13  9 12 12
+9 11 11  9 11 11  9 11 11  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  9 11 11  9 11 11  9 11 11  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  9 12 12  13 16 16  41 42 42
+49 51 48  110 109 94  251 251 187  251 251 187  251 251 187  105 104 92
+49 51 48  43 45 43  35 37 36  30 31 28  47 48 46  197 193 154
+251 251 187  197 193 154  31 33 31  12 12 12  12 12 12  12 12 12
+12 12 12  51 52 50  184 179 149  72 73 67  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  2 2 2
+11 11 11  21 22 21  30 32 31  40 41 39  60 60 56  145 141 105
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  214 212 158
+184 179 149  110 109 94  13 13 13  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  4 5 4  61 61 53  48 49 45  3 4 3
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+156 151 111  251 251 187  251 251 187  184 179 149  11 11 11  0 0 0
+0 0 0  26 28 27  99 98 80  84 83 72  60 60 56  43 45 43
+72 73 67  65 66 61  49 51 48  35 37 36  27 29 28  20 24 24
+17 20 20  14 17 17  12 15 15  11 13 13  10 12 12  9 11 11
+9 11 11  9 11 11  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  9 11 11  9 11 11
+9 11 11  9 11 11  9 11 11  11 13 13  37 39 37  47 48 46
+51 52 50  184 179 149  251 251 187  251 251 187  251 251 187  145 141 105
+47 48 46  41 42 42  35 37 36  27 29 28  137 133 100  251 251 187
+251 251 187  197 193 154  19 20 19  12 12 12  12 12 12  12 12 12
+27 29 28  184 179 149  214 212 158  63 64 60  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  1 1 1  6 7 7  16 16 16  24 26 24
+30 32 31  38 39 37  47 48 46  55 57 54  68 70 65  110 109 94
+197 193 154  251 251 187  251 251 187  251 251 187  210 208 158  184 179 149
+105 104 92  8 8 7  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  65 66 61  184 179 149  156 151 111
+30 32 31  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+168 163 120  251 251 187  251 251 187  251 251 187  110 109 94  0 0 0
+0 0 0  60 60 56  84 83 72  68 70 65  51 52 50  38 39 37
+84 83 72  63 64 60  43 45 43  33 36 34  25 27 26  20 23 22
+15 18 18  13 16 16  12 14 14  10 13 13  9 12 12  9 11 11
+9 11 11  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+9 11 11  9 11 11  10 12 12  33 36 34  46 47 45  51 52 50
+72 73 67  210 208 158  251 251 187  251 251 187  251 251 187  177 172 135
+47 48 46  41 42 42  35 37 36  37 39 37  184 179 149  251 251 187
+251 251 187  197 193 154  13 13 13  12 12 12  12 12 12  12 12 12
+110 109 94  251 251 187  251 251 187  37 39 37  0 0 0  0 0 0
+0 0 0  21 22 20  2 2 1  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+4 5 5  12 12 12  21 22 21  25 27 26  30 32 31  38 39 37
+46 47 45  55 56 53  60 60 56  65 66 61  68 70 65  105 104 92
+110 109 94  197 193 154  210 208 158  197 193 154  184 179 149  84 83 72
+2 2 2  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  13 13 13  184 179 149  251 251 187
+197 193 154  43 44 41  0 0 0  0 0 0  0 0 0  0 0 0
+145 141 105  251 251 187  251 251 187  251 251 187  214 212 158  43 45 43
+2 2 2  84 83 72  72 73 67  58 59 55  41 42 42  38 39 37
+72 73 67  58 59 55  41 42 42  31 33 31  25 27 26  18 22 22
+14 17 17  12 15 15  12 14 14  10 12 12  9 12 12  9 11 11
+9 11 11  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  9 12 12  31 33 31  43 45 43  49 51 48  55 56 53
+110 109 94  251 251 187  251 251 187  251 251 187  251 251 187  168 163 120
+47 48 46  41 42 42  33 36 34  63 64 60  197 193 154  251 251 187
+251 251 187  184 179 149  13 13 13  12 12 12  12 12 12  16 16 16
+197 193 154  251 251 187  239 239 170  20 20 20  0 0 0  2 2 1
+108 107 93  110 109 94  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  1 1 1  4 5 5  11 11 11  18 19 18
+22 24 23  26 28 27  32 34 33  39 40 39  46 47 45  51 52 50
+55 57 54  60 60 56  63 64 60  63 64 60  63 64 60  58 59 55
+63 64 60  99 98 80  145 141 105  137 133 100  43 45 43  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  3 4 3  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  110 109 94  251 251 187
+251 251 187  184 179 149  25 27 26  0 0 0  0 0 0  0 0 0
+99 98 80  251 251 187  251 251 187  251 251 187  251 251 187  156 151 111
+25 27 26  84 83 72  65 66 61  47 48 46  32 34 33  39 40 39
+72 73 67  55 57 54  40 41 39  30 32 31  23 25 24  18 22 22
+14 17 17  12 15 15  11 13 13  10 12 12  9 11 11  9 11 11
+9 11 11  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+9 11 11  28 31 30  41 42 42  47 48 46  55 56 53  58 59 55
+137 133 100  251 251 187  251 251 187  251 251 187  210 208 158  137 133 100
+47 48 46  40 41 39  32 34 33  75 75 61  184 179 149  239 239 170
+251 251 187  177 172 135  13 13 13  12 12 12  12 12 12  43 44 41
+197 193 154  251 251 187  210 208 158  10 10 9  0 0 0  84 83 72
+251 251 187  84 83 72  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  1 1 1
+6 7 7  11 11 11  17 17 17  20 20 20  23 24 24  27 29 28
+32 34 33  38 39 37  43 45 43  47 48 46  51 52 50  55 56 53
+58 59 55  58 59 55  55 57 54  55 56 53  47 48 46  41 42 42
+35 37 36  31 33 31  47 48 46  14 14 13  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  66 65 55  99 98 80  20 20 20
+0 0 0  0 0 0  0 0 0  0 0 0  43 45 43  214 212 158
+251 251 187  251 251 187  145 141 105  3 3 3  0 0 0  0 0 0
+48 49 45  184 179 149  239 239 170  251 251 187  239 239 170  177 172 135
+84 83 72  72 73 67  55 56 53  39 40 39  26 28 27  39 40 39
+68 70 65  51 52 50  39 40 39  28 31 30  22 24 23  17 20 20
+14 17 17  12 14 14  10 13 13  9 11 11  9 11 11  9 11 11
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+27 29 28  40 41 39  46 47 45  51 52 50  55 57 54  63 64 60
+131 127 93  197 193 154  210 208 158  197 193 154  168 163 120  96 95 69
+47 48 46  40 41 39  32 34 33  71 71 57  145 141 105  184 179 149
+184 179 149  131 127 93  13 13 13  12 12 12  12 12 12  48 49 45
+168 163 120  184 179 149  156 151 111  6 7 7  14 14 13  177 172 135
+239 239 170  40 41 39  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  3 3 3  6 7 7  11 11 11  16 16 16
+18 19 18  21 22 21  23 24 24  27 29 28  32 34 33  37 39 37
+41 42 42  43 45 43  47 48 46  51 52 50  51 52 50  51 52 50
+51 52 50  49 51 48  46 47 45  40 41 39  32 34 33  25 27 26
+20 20 20  14 14 13  2 2 2  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  33 36 34  197 193 154  184 179 149
+41 42 42  0 0 0  0 0 0  0 0 0  3 3 3  184 179 149
+251 251 187  251 251 187  184 179 149  48 49 45  0 0 0  0 0 0
+16 17 12  121 119 87  177 172 135  194 189 146  188 184 146  145 141 105
+82 81 62  63 64 60  46 47 45  31 33 31  21 22 21  35 37 36
+68 70 65  51 52 50  37 39 37  27 30 29  22 24 23  17 20 20
+13 16 16  12 14 14  10 13 13  9 11 11  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  25 27 26
+38 39 37  43 45 43  51 52 50  55 56 53  60 60 56  63 64 60
+92 91 72  158 153 112  176 171 126  171 165 117  149 143 98  82 81 62
+44 46 43  38 39 37  30 32 31  71 71 57  131 127 93  160 154 106
+149 143 98  82 81 62  13 13 13  12 12 12  12 12 12  46 47 43
+121 119 87  134 131 96  96 95 69  7 7 6  38 39 37  131 127 93
+145 141 105  12 13 12  0 0 0  1 1 1  3 3 3  6 7 7
+10 10 9  12 12 12  14 14 13  16 16 16  18 19 18  21 22 21
+22 24 23  26 28 27  30 31 28  33 36 34  37 39 37  40 41 39
+41 42 42  43 45 43  46 47 45  46 47 45  46 47 45  43 45 43
+41 42 42  37 39 37  31 33 31  26 28 27  21 22 21  16 16 16
+6 7 7  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  177 172 135  251 251 187
+197 193 154  27 29 28  0 0 0  0 0 0  0 0 0  110 109 94
+239 239 170  239 239 170  184 179 149  87 86 72  2 2 1  0 0 0
+1 1 1  82 81 62  142 137 94  165 161 109  165 161 109  131 127 93
+75 75 61  55 56 53  37 39 37  25 27 26  19 20 19  32 34 33
+65 66 61  49 51 48  35 37 36  27 29 28  20 23 23  16 19 19
+13 16 16  13 13 13  10 12 12  9 11 11  8 10 10  8 10 10
+8 9 9  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  22 24 23  35 37 36
+41 42 42  47 48 46  55 56 53  58 59 55  63 64 60  65 66 61
+71 71 57  131 127 93  160 154 106  160 154 106  142 137 94  82 81 62
+46 47 43  40 41 39  33 36 34  66 65 55  125 122 87  149 143 98
+142 137 94  82 81 62  17 17 17  18 19 17  14 14 13  46 47 43
+118 116 76  125 122 87  96 95 69  16 17 12  71 71 57  103 101 77
+82 81 62  11 11 11  11 11 11  13 13 13  14 14 13  14 14 13
+15 15 15  16 16 16  17 17 17  19 20 19  21 22 21  23 24 24
+26 28 27  27 29 28  31 33 31  33 36 34  35 37 36  38 39 37
+39 40 39  39 40 39  38 39 37  37 39 37  35 37 36  31 33 31
+27 29 28  24 26 24  21 22 21  17 17 17  12 12 12  2 2 2
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  68 70 65  251 251 187
+251 251 187  156 151 111  2 2 1  0 0 0  0 0 0  43 44 41
+177 172 135  184 179 149  158 153 112  103 101 77  19 20 18  0 0 0
+0 0 0  46 47 43  131 127 93  160 154 106  160 154 106  131 127 93
+71 71 57  43 45 43  30 32 31  21 22 21  16 16 16  26 28 27
+63 64 60  47 48 46  35 37 36  26 28 27  20 23 23  16 19 19
+13 16 16  13 13 13  10 12 12  9 11 11  8 10 10  8 10 10
+7 9 9  7 9 9  8 9 9  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  20 20 20  33 36 34  40 41 39
+46 47 45  51 52 50  55 57 54  60 60 56  63 64 60  65 66 61
+66 65 55  118 116 76  151 147 98  165 161 109  151 147 98  121 119 87
+96 95 69  96 95 69  96 95 69  103 101 77  142 137 94  151 147 98
+142 137 94  103 101 77  82 81 62  82 81 62  82 81 62  96 95 69
+131 127 93  142 137 94  103 101 77  46 47 43  96 95 69  118 116 76
+71 71 57  14 14 13  14 14 13  15 15 15  15 15 15  16 16 16
+16 16 16  17 17 17  18 19 18  20 20 20  21 22 21  23 24 24
+25 27 26  27 29 28  30 31 28  30 32 31  31 33 31  31 33 31
+31 33 31  31 33 31  30 31 28  27 29 28  25 27 26  22 24 23
+20 20 20  16 16 16  13 13 13  6 7 7  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+58 59 55  68 70 65  8 8 7  0 0 0  10 10 9  210 208 158
+251 251 187  184 179 149  38 39 37  0 0 0  0 0 0  8 8 7
+103 101 77  149 143 98  149 143 98  118 116 76  40 41 39  25 27 25
+53 55 47  82 81 62  144 139 99  165 161 109  165 161 109  142 137 94
+71 71 57  35 37 36  24 26 24  18 19 18  15 15 15  22 24 23
+63 64 60  46 47 45  33 36 34  26 28 27  20 23 22  17 18 17
+12 15 15  11 13 13  10 12 12  9 11 11  8 10 10  8 10 10
+7 9 9  7 9 9  7 9 9  7 9 9  8 9 9  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  16 16 16  30 31 28  35 37 36  41 42 42
+47 48 46  55 56 53  58 59 55  63 64 60  65 66 61  65 66 61
+61 61 53  103 101 77  151 147 98  171 165 117  171 165 117  168 163 120
+158 153 112  158 153 112  155 149 109  151 147 98  151 147 98  160 154 106
+151 147 98  149 143 98  142 137 94  149 143 98  149 143 98  149 143 98
+155 149 109  151 147 98  131 127 93  103 101 77  125 122 87  118 116 76
+71 71 57  16 16 16  16 16 16  16 16 16  17 17 17  17 17 17
+17 17 17  17 17 17  18 19 18  19 20 19  20 20 20  21 22 21
+23 24 24  24 26 24  25 27 26  26 28 27  26 28 27  26 28 27
+25 27 26  24 26 24  22 24 23  21 22 21  19 20 19  16 16 16
+14 14 13  8 8 7  1 1 1  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+20 20 20  184 179 149  168 163 120  21 22 21  0 0 0  105 104 92
+177 172 135  145 141 105  71 71 57  0 0 0  0 0 0  0 0 0
+66 65 55  131 127 93  151 147 98  142 137 94  118 116 76  121 119 87
+145 141 105  158 153 112  176 171 126  178 174 128  176 171 126  149 145 103
+96 95 69  31 33 31  21 22 21  16 16 16  14 14 13  18 19 18
+60 60 56  46 47 45  33 36 34  25 27 26  21 22 21  15 18 18
+12 15 15  11 13 13  9 11 11  8 10 10  8 10 10  8 9 9
+7 9 9  7 9 9  7 9 9  7 9 9  7 9 9  8 9 9
+8 9 9  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  10 12 12  26 28 27  31 33 31  38 39 37  43 45 43
+51 52 50  55 56 53  60 60 56  63 64 60  65 66 61  68 70 65
+63 64 60  96 95 69  158 153 112  178 174 128  188 184 146  194 189 146
+194 189 146  188 184 146  184 181 136  176 171 126  171 165 117  173 167 111
+173 167 111  165 161 109  171 165 117  174 170 121  176 171 126  178 174 128
+178 174 128  174 170 121  160 154 106  149 143 98  149 143 98  125 122 87
+71 71 57  16 16 16  16 16 16  17 17 17  17 17 17  17 17 17
+17 17 17  17 17 17  17 17 17  18 19 18  19 20 19  20 20 20
+21 22 21  21 22 21  21 22 21  22 24 23  21 22 21  21 22 21
+21 22 21  19 20 19  18 19 18  16 16 16  14 14 13  11 11 11
+3 3 3  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  105 104 92  197 193 154  110 109 94  9 9 8  36 38 35
+121 119 87  131 127 93  96 95 69  18 19 17  30 31 28  66 65 55
+96 95 69  142 137 94  160 154 106  160 154 106  160 154 106  168 163 120
+184 181 136  194 191 148  197 193 154  197 193 154  194 189 146  168 163 120
+125 122 87  46 47 43  18 19 18  15 15 15  13 13 13  14 14 13
+55 57 54  43 45 43  32 34 33  25 27 26  18 22 22  17 17 17
+12 14 14  10 12 12  9 11 11  8 10 10  8 9 9  7 9 9
+6 8 8  7 9 9  7 9 9  7 9 9  7 9 9  7 9 9
+7 9 9  8 9 9  8 9 9  8 10 10  8 10 10  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  32 34 33  41 42 42  35 37 36  39 40 39  37 39 37
+35 37 36  55 57 54  60 60 56  63 64 60  65 66 61  65 66 61
+61 63 57  115 113 82  168 163 120  194 191 148  204 201 155  210 208 158
+210 208 158  210 208 158  197 193 154  194 189 146  186 182 128  176 171 126
+174 170 121  176 171 126  186 182 128  190 186 136  194 191 148  197 193 154
+197 193 154  188 184 146  181 176 137  174 170 121  165 161 109  142 137 94
+82 81 62  24 26 24  16 16 16  16 16 16  16 16 16  16 16 16
+17 17 17  17 17 17  17 17 17  17 17 17  18 19 18  19 20 19
+19 20 19  19 20 19  20 20 20  19 20 19  19 20 19  18 19 18
+17 17 17  15 15 15  13 13 13  12 12 12  6 7 7  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  17 18 17  137 133 100  115 113 82  53 55 47  19 20 18
+103 101 77  144 139 99  137 133 100  115 113 82  137 133 100  156 151 111
+158 153 112  164 159 111  171 165 117  174 170 121  178 174 128  194 189 146
+204 201 155  214 212 158  214 212 158  214 212 158  210 208 158  188 184 146
+158 153 112  87 86 72  17 17 17  13 13 13  13 13 13  15 15 15
+55 56 53  43 45 43  32 34 33  24 26 24  17 20 20  16 16 16
+12 14 14  10 12 12  8 10 10  8 10 10  7 9 9  6 8 8
+6 8 8  6 8 8  6 8 8  7 9 9  7 9 9  7 9 9
+7 9 9  7 9 9  7 9 9  7 9 9  8 9 9  8 10 10
+8 10 10  8 10 10  8 10 10  8 10 10  8 10 10  8 10 10
+8 10 10  110 109 94  84 83 72  49 51 48  26 28 27  8 10 10
+8 9 9  51 52 50  58 59 55  63 64 60  63 64 60  63 64 60
+66 65 55  134 131 96  181 176 137  210 208 158  214 212 158  239 239 170
+239 239 170  224 223 159  210 208 158  204 201 155  194 189 146  186 182 128
+186 182 128  184 181 136  194 189 146  204 201 155  210 208 158  210 208 158
+210 208 158  210 208 158  197 193 154  190 186 136  176 171 126  155 149 109
+118 116 76  36 38 35  15 15 15  16 16 16  16 16 16  16 16 16
+16 16 16  16 16 16  16 16 16  16 16 16  16 16 16  17 17 17
+17 17 17  17 17 17  17 17 17  16 16 16  16 16 16  15 15 15
+13 13 13  12 12 12  8 8 7  2 2 2  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  53 55 47  103 101 77  96 95 69  53 55 47
+103 101 77  158 153 112  177 172 135  184 179 149  188 184 146  197 193 154
+194 189 146  190 186 136  184 181 136  184 181 136  194 189 146  210 208 158
+214 212 158  239 239 170  251 251 187  251 251 187  224 223 159  204 201 155
+177 172 135  121 119 87  30 31 28  13 13 13  12 12 12  39 40 39
+60 60 56  43 45 43  32 34 33  23 25 24  18 19 18  13 16 16
+13 13 13  9 11 11  8 10 10  8 9 9  6 8 8  6 8 8
+6 8 8  6 8 8  6 8 8  6 8 8  6 8 8  7 9 9
+7 9 9  7 9 9  7 9 9  7 9 9  7 9 9  7 9 9
+7 9 9  8 9 9  8 9 9  8 10 10  8 10 10  8 10 10
+14 17 17  197 193 154  158 153 112  55 57 54  7 9 9  7 9 9
+8 10 10  51 52 50  58 59 55  60 60 56  63 64 60  63 64 60
+71 71 57  155 149 109  194 191 148  214 212 158  251 251 187  251 251 187
+251 251 187  251 251 187  239 239 170  210 208 158  197 193 154  190 186 136
+190 186 136  194 189 146  204 201 155  210 208 158  224 223 159  239 239 170
+239 239 170  224 223 159  210 208 158  204 201 155  190 186 136  164 159 111
+125 122 87  40 41 39  15 15 15  15 15 15  15 15 15  15 15 15
+16 16 16  16 16 16  16 16 16  16 16 16  16 16 16  16 16 16
+16 16 16  16 16 16  15 15 15  14 14 13  13 13 13  12 12 12
+8 9 9  3 3 3  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  21 22 20  96 95 69  125 122 87  121 119 87
+144 139 99  177 172 135  197 193 154  210 208 158  214 212 158  214 212 158
+210 208 158  204 201 155  194 191 148  194 189 146  204 201 155  214 212 158
+239 239 170  251 251 187  251 251 187  251 251 187  251 251 187  214 212 158
+188 184 146  145 141 105  53 55 47  12 12 12  15 15 15  63 64 60
+63 64 60  41 42 42  31 33 31  23 24 24  17 18 17  12 15 15
+11 13 13  9 11 11  8 9 9  7 9 9  6 8 8  6 8 8
+6 7 7  6 7 7  6 8 8  6 8 8  6 8 8  6 8 8
+6 8 8  7 9 9  7 9 9  7 9 9  7 9 9  7 9 9
+7 9 9  7 9 9  7 9 9  7 9 9  7 9 9  8 8 7
+43 45 43  251 251 187  156 151 111  8 10 10  7 9 9  7 9 9
+21 22 21  51 52 50  55 56 53  55 57 54  58 59 55  58 59 55
+75 75 61  158 153 112  197 193 154  224 223 159  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  214 212 158  204 201 155  194 189 146
+190 186 136  197 193 154  210 208 158  224 223 159  251 251 187  251 251 187
+251 251 187  251 251 187  239 239 170  210 208 158  197 193 154  176 171 126
+125 122 87  36 38 35  14 14 13  14 14 13  15 15 15  15 15 15
+15 15 15  15 15 15  15 15 15  15 15 15  15 15 15  15 15 15
+15 15 15  14 14 13  13 13 13  12 12 12  10 10 9  3 4 4
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  7 7 5  71 71 57  131 127 93  158 153 112
+177 172 135  197 193 154  214 212 158  239 239 170  251 251 187  251 251 187
+238 237 168  210 208 158  204 201 155  197 193 154  204 201 155  214 212 158
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  214 212 158
+197 193 154  156 151 111  66 65 55  12 12 12  37 39 37  58 59 55
+58 59 55  41 42 42  31 33 31  22 24 23  17 17 17  12 14 14
+10 12 12  8 10 10  6 8 8  6 8 8  6 7 7  6 7 7
+6 7 7  5 7 7  6 7 7  6 7 7  6 8 8  6 8 8
+6 8 8  6 8 8  6 8 8  7 9 9  7 9 9  7 9 9
+7 9 9  6 8 8  6 8 8  6 8 8  6 8 8  6 8 8
+61 63 57  197 193 154  16 19 19  6 8 8  6 8 8  8 9 9
+41 42 42  47 48 46  51 52 50  51 52 50  55 56 53  55 56 53
+71 71 57  158 153 112  197 193 154  224 223 159  251 251 187  251 251 187
+251 251 187  251 251 187  239 239 170  214 212 158  204 201 155  194 189 146
+190 186 136  197 193 154  210 208 158  239 239 170  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  224 223 159  204 201 155  177 172 135
+121 119 87  30 31 28  13 13 13  14 14 13  14 14 13  14 14 13
+14 14 13  14 14 13  15 15 15  15 15 15  14 14 13  13 13 13
+12 12 12  12 12 12  10 10 9  4 5 5  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  48 49 45  131 127 93  174 170 121
+194 189 146  210 208 158  239 239 170  251 251 187  251 251 187  251 251 187
+251 251 187  214 212 158  204 201 155  197 193 154  204 201 155  210 208 158
+239 239 170  251 251 187  251 251 187  251 251 187  239 239 170  214 212 158
+194 191 148  156 151 111  71 71 57  19 20 19  51 52 50  51 52 50
+51 52 50  41 42 42  30 32 31  21 22 21  17 17 17  13 13 13
+9 11 11  8 9 9  6 8 8  6 7 7  6 7 7  5 7 7
+5 6 5  5 6 5  5 7 7  5 7 7  6 7 7  6 7 7
+6 8 8  6 8 8  6 8 8  6 7 7  6 7 7  6 7 7
+6 7 7  6 8 8  6 8 8  6 8 8  6 8 8  6 8 8
+55 56 53  43 45 43  6 8 8  6 8 8  6 8 8  47 48 46
+60 60 56  47 48 46  46 47 45  47 48 46  38 39 37  10 12 12
+66 65 55  145 141 105  197 193 154  214 212 158  251 251 187  251 251 187
+251 251 187  251 251 187  224 223 159  210 208 158  194 191 148  184 181 136
+184 181 136  194 189 146  204 201 155  224 223 159  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  239 239 170  210 208 158  181 176 137
+115 113 82  21 22 20  13 13 13  13 13 13  13 13 13  13 13 13
+14 14 13  13 13 13  13 13 13  13 13 13  12 12 12  11 11 11
+10 10 9  6 7 7  1 1 1  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  2 2 1  66 65 55  144 139 99  178 174 128
+204 201 155  214 212 158  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  214 212 158  204 201 155  194 191 148  197 193 154  204 201 155
+214 212 158  239 239 170  239 239 170  239 239 170  214 212 158  210 208 158
+184 181 136  149 145 103  66 65 55  41 42 42  47 48 46  46 47 45
+43 45 43  39 40 39  28 31 30  21 22 21  16 16 16  10 12 12
+8 10 10  6 8 8  6 7 7  6 7 7  5 6 5  5 6 5
+5 6 5  5 6 5  5 6 5  5 6 5  5 7 7  5 7 7
+6 7 7  6 7 7  6 7 7  5 7 7  5 7 7  5 7 7
+5 7 7  6 7 7  6 7 7  6 7 7  6 7 7  6 8 8
+6 8 8  6 8 8  6 7 7  6 7 7  46 47 45  156 151 111
+105 104 92  58 59 55  43 45 43  32 34 33  6 8 8  6 8 8
+49 51 48  125 122 87  181 176 137  204 201 155  214 212 158  239 239 170
+239 239 170  214 212 158  210 208 158  197 193 154  181 176 137  176 171 126
+176 171 126  184 181 136  197 193 154  210 208 158  239 239 170  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  210 208 158  177 172 135
+99 98 80  13 13 13  12 12 12  12 12 12  13 13 13  12 12 12
+12 12 12  12 12 12  11 11 11  11 11 11  8 9 9  4 5 5
+1 1 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  1 1 0  61 61 53  142 137 94  181 176 137
+204 201 155  224 223 159  251 251 187  251 251 187  251 251 187  251 251 187
+251 251 187  214 212 158  197 193 154  190 186 136  184 181 136  188 184 146
+197 193 154  204 201 155  210 208 158  210 208 158  204 201 155  194 189 146
+176 171 126  134 131 96  66 65 55  43 45 43  41 42 42  39 40 39
+35 37 36  33 36 34  27 29 28  20 20 20  15 15 15  9 11 11
+8 9 9  6 7 7  5 6 5  5 6 5  4 5 5  4 5 5
+4 5 5  4 5 5  4 5 5  4 5 5  5 6 5  4 5 5
+4 5 5  5 6 5  4 5 5  5 6 5  5 6 5  5 6 5
+5 7 7  5 7 7  5 7 7  5 7 7  5 7 7  5 7 7
+6 7 7  6 7 7  6 7 7  28 31 30  184 179 149  184 179 149
+145 141 105  84 83 72  27 29 28  5 7 7  5 6 5  16 16 16
+43 44 41  96 95 69  158 153 112  188 184 146  204 201 155  210 208 158
+204 201 155  197 193 154  184 179 149  177 172 135  168 163 120  164 159 111
+164 159 111  174 170 121  184 181 136  197 193 154  214 212 158  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  210 208 158  177 172 135
+71 71 57  11 11 11  12 12 12  11 11 11  11 11 11  11 11 11
+10 10 9  10 10 9  8 8 7  3 4 4  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  31 33 31  121 119 87  176 171 126
+197 193 154  214 212 158  251 251 187  251 251 187  251 251 187  251 251 187
+239 239 170  210 208 158  194 189 146  178 174 128  174 170 121  176 171 126
+177 172 135  181 176 137  184 179 149  184 179 149  181 176 137  178 174 128
+158 153 112  121 119 87  53 55 47  37 39 37  33 36 34  30 32 31
+27 29 28  25 27 26  24 26 24  19 20 19  13 13 13  8 10 10
+6 8 8  6 7 7  5 6 5  4 5 5  4 5 5  4 5 5
+4 5 5  4 5 5  4 5 5  3 4 4  3 4 4  4 5 5
+4 5 5  4 5 5  4 5 5  4 5 5  4 5 5  4 5 5
+5 6 5  5 6 5  5 6 5  5 6 5  5 6 5  5 6 5
+5 6 5  5 6 5  12 14 14  145 141 105  184 179 149  177 172 135
+90 89 73  21 22 21  5 6 5  5 6 5  4 5 5  37 39 37
+38 39 37  61 61 53  134 131 96  168 163 120  184 181 136  188 184 146
+184 179 149  177 172 135  168 163 120  164 159 111  155 149 109  151 147 98
+151 147 98  164 159 111  176 171 126  184 179 149  210 208 158  239 239 170
+251 251 187  251 251 187  251 251 187  239 239 170  210 208 158  158 153 112
+46 47 43  10 10 9  10 10 9  10 10 9  8 9 9  8 9 9
+6 7 7  3 3 3  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  13 12 7  82 81 62  158 153 112
+188 184 146  210 208 158  239 239 170  251 251 187  251 251 187  251 251 187
+224 223 159  204 201 155  184 181 136  171 165 117  164 159 111  160 154 106
+158 153 112  164 159 111  168 163 120  168 163 120  168 163 120  164 159 111
+142 137 94  96 95 69  43 44 41  27 29 28  26 28 27  23 24 24
+21 22 21  18 19 18  17 17 17  18 19 18  13 13 13  8 8 7
+6 7 7  5 6 5  4 5 5  3 4 4  3 4 4  3 4 4
+3 4 4  3 4 4  3 3 3  3 3 3  3 4 4  3 4 4
+3 4 4  3 4 4  4 5 5  4 5 5  4 5 5  4 5 5
+4 5 5  4 5 5  4 5 5  4 5 5  4 5 5  4 5 5
+4 5 5  4 5 5  4 5 5  4 5 5  4 5 5  4 5 5
+4 5 5  4 5 5  4 5 5  4 5 5  31 33 31  65 66 61
+37 39 37  38 39 37  96 95 69  144 139 99  168 163 120  174 170 121
+168 163 120  164 159 111  155 149 109  149 145 103  149 143 98  142 137 94
+149 143 98  151 147 98  164 159 111  177 172 135  197 193 154  210 208 158
+251 251 187  251 251 187  251 251 187  239 239 170  197 193 154  137 133 100
+24 26 24  8 9 9  8 9 9  8 8 7  6 7 7  2 2 2
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  46 47 43  125 122 87
+176 171 126  197 193 154  210 208 158  239 239 170  251 251 187  239 239 170
+214 212 158  197 193 154  181 176 137  164 159 111  151 147 98  149 143 98
+149 143 98  149 143 98  149 145 103  155 149 109  160 154 106  149 143 98
+118 116 76  82 81 62  30 31 28  21 22 21  19 20 19  17 17 17
+14 14 13  12 12 12  10 10 9  12 12 12  10 12 12  6 8 8
+4 5 5  3 4 4  3 4 4  3 4 4  3 3 3  3 3 3
+3 3 3  3 3 3  3 3 3  3 3 3  2 3 3  2 3 3
+3 4 4  3 4 4  3 4 4  3 4 4  3 4 4  4 5 5
+4 5 5  3 4 4  3 4 4  3 4 4  3 4 4  3 4 4
+4 5 5  4 5 5  4 5 5  4 5 5  4 5 5  4 5 5
+4 5 5  3 4 4  3 4 4  23 24 24  110 109 94  72 73 67
+39 40 39  22 24 23  46 47 43  103 101 77  142 137 94  155 149 109
+160 154 106  155 149 109  149 143 98  142 137 94  142 137 94  142 137 94
+142 137 94  149 143 98  155 149 109  176 171 126  184 179 149  210 208 158
+239 239 170  251 251 187  251 251 187  214 212 158  184 179 149  105 104 92
+10 10 9  6 7 7  3 4 4  1 1 1  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  12 12 9  82 81 62
+149 145 103  181 176 137  197 193 154  210 208 158  214 212 158  214 212 158
+210 208 158  197 193 154  177 172 135  158 153 112  149 143 98  142 137 94
+142 137 94  142 137 94  149 143 98  151 147 98  151 147 98  131 127 93
+103 101 77  71 71 57  22 24 23  15 15 15  13 13 13  11 11 11
+8 9 9  6 7 7  6 7 7  4 5 5  8 9 9  6 7 7
+4 5 5  3 3 3  3 3 3  3 3 3  3 3 3  2 2 2
+2 2 2  2 2 2  2 2 2  2 2 2  2 2 2  2 3 3
+2 3 3  2 3 3  2 3 3  3 4 4  3 4 4  3 4 4
+3 4 4  3 4 4  3 3 3  3 4 4  3 4 4  3 4 4
+3 4 4  3 4 4  3 4 4  3 4 4  3 4 4  3 4 4
+3 4 4  3 4 4  21 22 21  145 141 105  145 141 105  72 73 67
+17 18 17  3 4 4  21 22 20  66 65 55  118 116 76  142 137 94
+149 143 98  151 147 98  149 143 98  142 137 94  142 137 94  142 137 94
+142 137 94  149 143 98  155 149 109  168 163 120  184 179 149  210 208 158
+239 239 170  251 251 187  251 251 187  210 208 158  177 172 135  71 71 57
+3 3 3  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  36 38 35
+115 113 82  158 153 112  181 176 137  197 193 154  204 201 155  210 208 158
+204 201 155  188 184 146  177 172 135  164 159 111  149 145 103  142 137 94
+142 137 94  142 137 94  149 143 98  151 147 98  149 143 98  125 122 87
+96 95 69  61 61 53  16 17 12  8 9 9  8 8 7  6 7 7
+4 5 5  3 4 4  3 3 3  3 3 3  3 3 3  5 6 5
+3 4 4  2 3 3  2 2 2  2 2 2  2 2 2  2 2 2
+2 2 2  2 2 2  2 2 2  2 2 2  2 2 2  1 2 2
+2 2 2  2 2 2  2 3 3  2 3 3  2 3 3  2 3 3
+3 3 3  3 3 3  3 3 3  3 3 3  3 3 3  3 3 3
+3 3 3  2 3 3  2 3 3  3 4 4  3 4 4  3 4 4
+3 4 4  3 4 4  3 4 4  8 9 9  8 8 7  3 3 3
+3 3 3  3 3 3  9 9 8  36 38 35  82 81 62  118 116 76
+142 137 94  151 147 98  151 147 98  151 147 98  149 143 98  149 143 98
+149 143 98  151 147 98  160 154 106  176 171 126  188 184 146  210 208 158
+239 239 170  251 251 187  239 239 170  210 208 158  156 151 111  31 33 31
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  7 7 5
+66 65 55  125 122 87  158 153 112  181 176 137  194 189 146  197 193 154
+197 193 154  184 179 149  177 172 135  168 163 120  156 151 111  151 147 98
+151 147 98  151 147 98  151 147 98  161 156 96  149 143 98  118 116 76
+82 81 62  53 55 47  12 12 9  4 5 5  3 4 4  3 3 3
+3 3 3  3 3 3  2 2 2  2 2 2  1 1 1  1 2 2
+3 3 3  2 2 2  2 2 2  2 2 2  2 2 2  2 2 2
+1 1 1  1 1 1  1 1 1  1 1 1  1 2 2  1 2 2
+1 2 2  1 2 2  1 2 2  2 2 2  2 2 2  2 3 3
+2 3 3  2 3 3  2 3 3  2 3 3  2 2 2  2 2 2
+2 3 3  2 3 3  2 3 3  2 3 3  2 3 3  2 3 3
+2 3 3  2 3 3  2 3 3  2 3 3  2 3 3  3 3 3
+3 3 3  3 3 3  72 73 67  61 61 53  53 55 47  96 95 69
+131 127 93  151 147 98  161 156 96  161 156 96  151 147 98  151 147 98
+161 156 96  160 154 106  164 159 111  177 172 135  197 193 154  210 208 158
+239 239 170  251 251 187  224 223 159  197 193 154  131 127 93  9 9 8
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+24 26 24  82 81 62  131 127 93  164 159 111  178 174 128  188 184 146
+188 184 146  188 184 146  181 176 137  176 171 126  168 163 120  164 159 111
+160 154 106  160 154 106  160 154 106  160 154 106  151 147 98  125 122 87
+82 81 62  61 61 53  12 12 9  3 3 3  3 3 3  2 2 2
+2 2 2  1 1 1  1 1 1  1 1 1  0 0 0  0 0 0
+0 0 0  2 2 2  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 2 2  1 2 2  1 2 2  1 2 2
+1 2 2  2 2 2  2 2 2  2 2 2  2 2 2  2 2 2
+2 2 2  2 2 2  2 2 2  2 2 2  2 2 2  2 2 2
+2 3 3  2 3 3  2 3 3  2 3 3  2 3 3  2 3 3
+2 3 3  30 32 31  72 73 67  31 33 31  36 38 35  82 81 62
+118 116 76  149 143 98  161 156 96  161 156 96  161 156 96  160 154 106
+165 161 109  165 161 109  176 171 126  188 184 146  204 201 155  214 212 158
+239 239 170  239 239 170  214 212 158  184 179 149  82 81 62  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+2 2 2  43 44 41  96 95 69  131 127 93  160 154 106  176 171 126
+184 181 136  184 181 136  184 181 136  181 176 137  178 174 128  174 170 121
+171 165 117  173 167 111  173 167 111  173 167 111  160 154 106  131 127 93
+96 95 69  66 65 55  16 17 12  2 2 2  1 1 1  1 1 1
+1 1 1  1 1 1  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 2 2  1 2 2  1 2 2  1 2 2  1 2 2  2 2 2
+2 2 2  2 2 2  2 2 2  2 2 2  2 2 2  2 2 2
+2 2 2  2 2 2  2 2 2  2 2 2  2 2 2  2 2 2
+2 2 2  2 2 2  2 2 2  10 9 6  30 31 28  71 71 57
+118 116 76  149 143 98  165 161 109  165 161 109  165 161 109  173 167 111
+173 167 111  176 171 126  184 181 136  197 193 154  210 208 158  224 223 159
+251 251 187  239 239 170  210 208 158  168 163 120  40 41 39  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  13 12 7  61 61 53  96 95 69  131 127 93  160 154 106
+176 171 126  184 181 136  184 181 136  188 184 146  184 181 136  184 181 136
+184 181 136  186 182 128  186 182 128  178 174 128  174 170 121  149 145 103
+118 116 76  82 81 62  21 22 20  1 1 1  1 1 1  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 2 2
+1 2 2  1 2 2  1 2 2  1 2 2  1 2 2  2 2 2
+2 2 2  2 2 2  2 2 2  2 2 2  2 2 2  2 2 2
+2 2 2  2 2 2  2 2 2  3 3 3  30 31 28  66 65 55
+118 116 76  149 143 98  165 161 109  173 167 111  173 167 111  174 170 121
+186 182 128  190 186 136  197 193 154  210 208 158  224 223 159  251 251 187
+251 251 187  239 239 170  197 193 154  137 133 100  12 12 9  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  30 31 28  71 71 57  103 101 77  134 131 96
+164 159 111  176 171 126  184 181 136  188 184 146  194 189 146  197 193 154
+197 193 154  197 193 154  194 191 148  194 189 146  190 186 136  176 171 126
+145 141 105  103 101 77  40 41 39  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 2 2  1 2 2
+1 2 2  1 2 2  1 2 2  1 2 2  1 2 2  1 2 2
+1 2 2  1 2 2  1 2 2  1 2 2  30 31 28  71 71 57
+118 116 76  160 154 106  173 167 111  178 174 128  186 182 128  190 186 136
+194 191 148  204 201 155  210 208 158  224 223 159  251 251 187  251 251 187
+251 251 187  214 212 158  184 179 149  84 83 72  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  5 5 3  43 44 41  82 81 62  103 101 77
+142 137 94  165 161 109  178 174 128  190 186 136  197 193 154  204 201 155
+210 208 158  210 208 158  210 208 158  210 208 158  210 208 158  197 193 154
+177 172 135  145 141 105  79 78 62  5 4 3  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 2 2  1 2 2  30 31 28  82 81 62
+142 137 94  165 161 109  178 174 128  190 186 136  194 191 148  204 201 155
+210 208 158  214 212 158  239 239 170  251 251 187  251 251 187  251 251 187
+251 251 187  210 208 158  168 163 120  36 38 35  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  16 17 12  53 55 47  82 81 62
+118 116 76  151 147 98  171 165 117  184 181 136  194 191 148  210 208 158
+214 212 158  224 223 159  239 239 170  239 239 170  224 223 159  214 212 158
+197 193 154  176 171 126  115 113 82  24 26 24  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  40 41 39  103 101 77
+151 147 98  176 171 126  190 186 136  197 193 154  210 208 158  214 212 158
+239 239 170  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+239 239 170  197 193 154  110 109 94  3 4 3  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  30 31 28  66 65 55
+96 95 69  125 122 87  160 154 106  178 174 128  194 189 146  204 201 155
+214 212 158  239 239 170  251 251 187  251 251 187  251 251 187  239 239 170
+210 208 158  188 184 146  149 145 103  61 61 53  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  61 61 53  131 127 93
+164 159 111  184 181 136  197 193 154  210 208 158  224 223 159  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  251 251 187
+210 208 158  168 163 120  43 44 41  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  4 3 2  36 38 35
+71 71 57  96 95 69  142 137 94  165 161 109  184 181 136  197 193 154
+210 208 158  239 239 170  251 251 187  251 251 187  251 251 187  251 251 187
+214 212 158  197 193 154  168 163 120  103 101 77  7 7 5  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+1 1 1  0 0 0  0 0 0  0 0 0  82 81 62  142 137 94
+174 170 121  194 189 146  210 208 158  224 223 159  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  251 251 187  224 223 159
+184 179 149  99 98 80  3 3 3  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  7 7 5
+43 44 41  82 81 62  118 116 76  142 137 94  171 165 117  190 186 136
+204 201 155  224 223 159  251 251 187  251 251 187  251 251 187  251 251 187
+214 212 158  197 193 154  174 170 121  125 122 87  30 31 28  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  1 1 1
+1 1 1  1 1 1  1 1 1  1 1 1  1 1 1  1 1 1
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  3 4 3  82 81 62  149 143 98
+176 171 126  194 191 148  210 208 158  239 239 170  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  251 251 187  239 239 170  204 201 155
+145 141 105  30 31 28  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+10 9 6  46 47 43  82 81 62  118 116 76  149 143 98  174 170 121
+194 189 146  210 208 158  224 223 159  251 251 187  251 251 187  224 223 159
+210 208 158  194 191 148  174 170 121  134 131 96  53 55 47  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  7 7 5  96 95 69  149 143 98
+176 171 126  194 191 148  210 208 158  239 239 170  251 251 187  251 251 187
+251 251 187  251 251 187  251 251 187  239 239 170  210 208 158  177 172 135
+75 75 61  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  10 9 6  46 47 43  82 81 62  118 116 76  149 143 98
+176 171 126  194 191 148  210 208 158  214 212 158  214 212 158  210 208 158
+197 193 154  184 181 136  164 159 111  131 127 93  53 55 47  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  7 7 5  96 95 69  149 143 98
+174 170 121  194 189 146  204 201 155  214 212 158  239 239 170  251 251 187
+251 251 187  251 251 187  239 239 170  210 208 158  184 179 149  110 109 94
+12 12 9  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  10 9 6  43 44 41  82 81 62  115 113 82
+144 139 99  168 163 120  188 184 146  197 193 154  197 193 154  194 189 146
+184 181 136  174 170 121  151 147 98  118 116 76  36 38 35  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  4 3 2  82 81 62  142 137 94
+171 165 117  186 182 128  194 191 148  210 208 158  214 212 158  224 223 159
+239 239 170  224 223 159  210 208 158  184 179 149  137 133 100  36 38 35
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  7 7 5  36 38 35  71 71 57
+103 101 77  131 127 93  155 149 109  168 163 120  168 163 120  168 163 120
+164 159 111  149 143 98  125 122 87  82 81 62  13 12 7  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  61 61 53  125 122 87
+160 154 106  174 170 121  184 181 136  194 189 146  204 201 155  210 208 158
+210 208 158  204 201 155  184 179 149  145 141 105  61 61 53  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  3 3 2  30 31 28
+61 61 53  82 81 62  103 101 77  121 119 87  125 122 87  125 122 87
+118 116 76  103 101 77  79 78 62  24 26 24  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  25 27 25  96 95 69
+142 137 94  160 154 106  171 165 117  178 174 128  184 181 136  184 181 136
+181 176 137  177 172 135  145 141 105  75 75 61  5 5 3  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+16 17 12  40 41 39  61 61 53  71 71 57  71 71 57  71 71 57
+66 65 55  43 44 41  12 12 9  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  1 1 1  46 47 43
+96 95 69  125 122 87  142 137 94  149 145 103  155 149 109  155 149 109
+145 141 105  121 119 87  66 65 55  7 7 5  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  1 1 1  16 17 12  24 26 24  25 27 25  19 20 18
+7 7 5  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  2 2 1
+25 27 25  61 61 53  82 81 62  96 95 69  96 95 69  82 81 62
+61 61 53  25 27 25  2 2 1  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  5 6 5  13 12 7  10 9 6  3 4 3
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0
diff --git a/drivers/video/logo/logo_linux_vga16.ppm b/drivers/video/logo/logo_linux_vga16.ppm
index 1850c15..12ac3a54 100644
--- a/drivers/video/logo/logo_linux_vga16.ppm
+++ b/drivers/video/logo/logo_linux_vga16.ppm
@@ -1,1604 +1,2739 @@
 P3
-# Standard 16-color Linux logo
-80 80
+142 114
 255
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85  85  85  85  85  85  85  85  85  85
- 85  85  85  85  85  85  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85  85  85  85
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
- 85  85  85  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85 170 170 170   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-170 170 170 170 170 170  85  85  85   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0  85  85  85 170 170 170   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 170 170 170 170 170 170
-170 170 170   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
- 85  85  85 170 170 170 170 170 170 170 170 170
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0 170 170 170 255 255 255 255 255 255
-255 255 255 170 170 170   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0  85  85  85
-170 170 170 170 170 170 255 255 255 255 255 255
-  0   0   0   0   0   0   0   0   0   0   0   0
-170 170 170 255 255 255 170 170 170 170 170 170
-255 255 255 170 170 170   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0  85  85  85
-170 170 170   0   0   0   0   0   0 255 255 255
- 85  85  85   0   0   0   0   0   0   0   0   0
-255 255 255 170 170 170   0   0   0  85  85  85
-170 170 170 255 255 255 170 170 170   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0  85  85  85
- 85  85  85   0   0   0   0   0   0 170 170 170
- 85  85  85   0   0   0   0   0   0   0   0   0
-255 255 255  85  85  85   0   0   0   0   0   0
- 85  85  85 255 255 255 170 170 170   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0  85  85  85
-170 170 170   0   0   0   0   0   0 170 170 170
- 85  85  85  85  85  85  85  85  85  85  85  85
-255 255 255  85  85  85   0   0   0   0   0   0
- 85  85  85 255 255 255 170 170 170   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-255 255 255   0   0   0   0   0   0 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0   0   0   0   0   0   0
- 85  85  85 255 255 255   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-170 170 170 170 170 170 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170 170 170 170 170 170   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85  85  85  85   0   0   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 170  85   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85  85  85  85   0   0   0
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 170  85   0
-170  85   0 170  85   0  85  85  85   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85  85  85  85   0   0   0
- 85  85  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170  85   0 170  85   0  85  85  85   0   0   0
-  0   0   0  85  85  85 170 170 170  85  85  85
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85  85  85  85   0   0   0
- 85  85  85 170  85   0 170  85   0 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170 170 170 170 170 170 170 170 170   0   0   0
-  0   0   0   0   0   0 170 170 170 170 170 170
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
- 85  85  85 170 170 170 170  85   0 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170  85   0 170  85   0 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170  85  85  85
-  0   0   0   0   0   0  85  85  85  85  85  85
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
- 85  85  85 170 170 170 170 170 170 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170 170 170 170 170 170 170 170 170 170 170 170
-255 255 255 255 255 255 255 255 255 170 170 170
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0  85  85  85
-255 255 255 255 255 255 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0 170 170 170
-255 255 255 255 255 255 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-170 170 170   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0  85  85  85 255 255 255
-255 255 255 255 255 255 255 255 255 170 170 170
-170 170 170 170 170 170 170 170 170 170 170 170
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0  85  85  85 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0  85  85  85 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 170 170 170   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0  85  85  85 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
- 85  85  85 170 170 170 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85 170 170 170 170 170 170 170 170 170
-255 255 255 255 255 255 255 255 255 170 170 170
-170 170 170 170 170 170 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-170 170 170 170 170 170 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-170 170 170 170 170 170 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-170 170 170 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 170 170 170
-170 170 170 170 170 170 170 170 170  85  85  85
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-170 170 170 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 170 170 170 170 170 170 170 170 170
-  0   0   0   0   0   0   0   0   0  85  85  85
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
- 85  85  85   0   0   0   0   0   0  85  85  85
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 170 170 170
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0 170 170 170
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-170 170 170  85  85  85   0   0   0   0   0   0
-  0   0   0  85  85  85  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0  85  85  85
-  0   0   0   0   0   0  85  85  85 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 170 170 170   0   0   0  85  85  85
- 85  85  85   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0  85  85  85
-  0   0   0  85  85  85 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 170 170 170   0   0   0  85  85  85
- 85  85  85   0   0   0  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0  85  85  85
-  0   0   0 170 170 170 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0  85  85  85   0   0   0
-  0   0   0 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0  85  85  85   0   0   0
- 85  85  85 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0  85  85  85   0   0   0   0   0   0
-170 170 170 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0  85  85  85
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0  85  85  85
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85  85  85  85
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255   0   0   0
- 85  85  85  85  85  85  85  85  85  85  85  85
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85   0   0   0 170  85   0
-255 255  85 170  85   0   0   0   0   0   0   0
- 85  85  85 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0  85  85  85  85  85  85   0   0   0
-  0   0   0  85  85  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0   0   0   0
-  0   0   0  85  85  85 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255  85 170  85   0 255 255  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85  85  85  85
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-  0   0   0   0   0   0  85  85  85 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255  85
-170  85   0 255 255  85 170  85   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-170  85   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0   0   0   0   0   0   0  85  85  85
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 170  85   0
-255 255  85 170  85   0 255 255  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0 170  85   0
-255 255  85 170  85   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85   0   0   0   0   0   0   0   0   0
- 85  85  85 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255  85
-170  85   0 255 255  85 170  85   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0 255 255  85
-170  85   0 255 255  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85   0   0   0   0   0   0
-  0   0   0  85  85  85 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 255 255  85 170  85   0
-255 255  85 170  85   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85   0   0   0
-  0   0   0   0   0   0  85  85  85 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 170 170 170 170 170 170 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 170 170 170 170 170 170 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 170 170 170 170 170 170 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0   0   0   0   0   0   0   0   0   0
-  0   0   0 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 170 170 170 170 170 170 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85   0   0   0   0   0   0   0   0   0
- 85  85  85 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 170 170 170  85  85  85 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85  85  85  85  85  85  85
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-170 170 170  85  85  85  85  85  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 170 170 170
- 85  85  85   0   0   0   0   0   0 170  85   0
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170  85  85  85
-  0   0   0   0   0   0   0   0   0 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-170 170 170 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-170 170 170  85  85  85  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0 170  85   0
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 170  85   0
-170  85   0 170 170 170 255 255 255 255 255 255
-255 255 255 255 255 255 255 255 255 255 255 255
-255 255 255 255 255 255 170 170 170  85  85  85
- 85  85  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-170  85   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85 170  85   0
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 170  85   0 170  85   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 170  85   0
-170  85   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-170  85   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-170  85   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0  85  85  85 170  85   0
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 170  85   0 170  85   0 170  85   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 170  85   0 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 170  85   0
-170  85   0   0   0   0   0   0   0   0   0   0
- 85  85  85  85  85  85  85  85  85  85  85  85
- 85  85  85  85  85  85  85  85  85  85  85  85
- 85  85  85  85  85  85  85  85  85   0   0   0
-  0   0   0   0   0   0   0   0   0 170  85   0
-170  85   0 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 255 255  85 170  85   0
-170  85   0 170  85   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0 170  85   0 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170  85   0 170  85   0 255 255  85 170  85   0
-255 255  85 170  85   0 170  85   0 170  85   0
- 85  85  85  85  85  85  85  85  85  85  85  85
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0  85  85  85
- 85  85  85  85  85  85  85  85  85 170  85   0
-170  85   0 170  85   0 170  85   0 255 255  85
-170  85   0 255 255  85 170  85   0 170  85   0
-170  85   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170  85   0 170  85   0 170  85   0 170  85   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0 170  85   0 170  85   0 170  85   0
-170  85   0 170  85   0 170  85   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-170  85   0 170  85   0 170  85   0 170  85   0
-170  85   0 170  85   0 170  85   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
-  0   0   0   0   0   0   0   0   0   0   0   0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  85 85 85  0 0 0  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  85 85 85  85 85 85  85 85 85
+0 0 0  85 85 85  85 85 85  0 0 0  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  170 170 170
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+85 85 85  0 0 0  85 85 85  85 85 85  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  170 170 170  170 85 0  170 170 170  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+170 170 170  255 255 85  170 170 170  170 170 170  170 170 170  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  170 170 170
+255 255 85  170 170 170  170 170 170  170 85 0  85 255 85  170 85 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  170 170 170  170 85 0
+170 170 170  170 170 170  255 255 85  170 170 170  170 170 170  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  170 85 0  170 170 170
+170 170 170  170 85 0  170 170 170  170 170 170  170 85 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  85 85 85  85 85 85  85 255 85
+255 85 85  85 255 85  170 170 170  170 85 0  170 170 170  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  170 85 0  85 85 85  85 85 85
+170 170 170  170 85 0  170 170 170  85 85 85  170 85 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  85 85 85  170 85 0
+85 85 85  85 85 85  170 85 0  85 255 85  85 85 85  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  85 85 85  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  170 85 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 170 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+170 85 0  85 255 85  170 85 0  170 85 0  170 85 0  85 255 85
+170 85 0  170 85 0  0 170 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 170 0  170 85 0
+255 255 85  170 85 0  255 255 85  255 255 85  255 255 85  170 85 0
+255 255 85  85 255 85  170 85 0  170 85 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 85 0  255 255 85
+85 255 85  255 255 85  255 255 85  170 85 0  255 255 85  255 255 85
+255 255 85  170 85 0  255 255 85  85 255 85  170 85 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  255 255 85  170 85 0
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  170 85 0
+255 255 85  255 255 85  255 255 85  255 255 85  170 85 0  85 255 85
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  170 170 170  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  170 85 0  255 255 85  255 255 85
+255 255 85  255 255 85  170 85 0  255 255 85  85 255 85  255 255 85
+255 255 85  170 85 0  255 255 85  170 85 0  255 255 85  170 85 0
+170 85 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  170 170 170  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  170 85 0  255 255 85  85 255 85  255 255 85
+170 170 170  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  85 255 85  255 255 85  255 255 85  255 255 85
+85 255 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  170 85 0  255 255 85  255 255 85  255 255 85
+255 255 255  255 255 85  255 255 85  170 85 0  255 255 85  170 85 0
+255 255 85  255 255 85  255 255 85  255 255 85  170 85 0  255 255 85
+170 85 0  170 85 0  0 170 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  170 85 0  85 255 85  255 255 85  170 170 170  255 255 255
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  170 85 0  255 255 85  85 255 85  255 255 85
+255 255 85  85 255 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  255 255 85  255 255 85  255 255 85  255 255 255  255 255 85
+255 255 85  255 255 85  85 255 85  255 255 85  255 255 85  85 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  170 85 0
+255 255 85  170 85 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+85 85 85  0 0 0  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+170 85 0  170 85 0  255 255 85  255 255 85  255 255 255  170 170 170
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+170 85 0  255 255 85  255 255 85  170 85 0  255 255 85  255 255 85
+255 255 85  85 255 85  170 85 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+255 255 85  85 255 85  255 255 85  170 170 170  255 255 255  255 255 85
+255 255 85  255 255 85  170 85 0  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  85 255 85  170 85 0
+255 255 85  170 85 0  170 85 0  0 0 0  85 85 85  0 0 0
+85 85 85  85 85 85  85 85 85  170 170 170  170 170 170  170 170 170
+85 255 85  170 170 170  170 170 170  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  170 170 170  255 255 85  170 170 170
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 170 0
+170 85 0  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  85 255 85  255 255 85  170 85 0  170 85 0
+170 85 0  85 255 85  255 255 85  85 85 85  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  85 255 85  170 170 170  170 170 170
+85 85 85  170 170 170  170 170 170  170 85 0  170 170 170  170 170 170
+85 255 85  170 170 170  170 85 0  170 170 170  85 255 85  255 85 85
+85 255 85  170 170 170  255 255 85  85 85 85  255 255 85  170 170 170
+85 255 85  170 170 170  255 255 85  170 170 170  170 170 170  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 255  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  170 85 0
+255 255 85  255 255 85  255 255 85  170 85 0  0 170 0  85 85 85
+170 170 170  170 170 170  255 255 85  170 170 170  170 170 170  85 255 85
+255 85 85  85 255 85  85 85 85  255 85 85  85 85 85  170 170 170
+170 85 0  170 170 170  85 85 85  85 255 85  85 85 85  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+170 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  255 255 85
+170 85 0  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  170 85 0  255 255 85  85 85 85  85 85 85
+255 255 85  170 170 170  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  85 85 85  170 170 170  170 85 0  170 170 170
+170 170 170  255 255 85  170 170 170  85 85 85  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 85 0  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  170 85 0  170 85 0  0 170 0
+0 0 0  170 85 0  170 85 0  0 170 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  85 85 85  170 170 170  85 85 85
+170 170 170  85 85 85  85 85 85  170 170 170  170 85 0  85 85 85
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  255 255 85  170 85 0
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  170 85 0
+255 255 85  255 255 85  255 255 85  170 85 0  255 255 85  255 255 85
+170 85 0  255 255 85  85 255 85  255 255 85  255 255 85  170 85 0
+170 85 0  255 255 85  170 85 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  255 255 85  255 255 85
+255 255 85  255 255 85  170 85 0  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  170 85 0  255 255 85  255 255 85
+85 255 85  170 85 0  0 170 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 170 0  170 85 0  255 255 85
+85 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+170 85 0  255 255 85  85 255 85  255 255 85  255 255 85  170 85 0
+85 255 85  170 85 0  170 85 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  170 85 0  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  170 85 0  255 255 85  85 255 85  255 255 85  170 85 0
+255 255 85  255 255 85  170 85 0  255 255 85  170 85 0  85 255 85
+170 85 0  170 85 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  255 255 85  170 85 0
+255 255 85  170 85 0  255 255 85  170 85 0  255 255 85  85 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  170 85 0  255 255 85  85 255 85  170 85 0  170 85 0
+0 170 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  170 85 0  255 255 85  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  255 255 85  170 85 0  255 255 85  170 85 0  85 255 85
+255 255 85  85 255 85  170 85 0  170 85 0  85 255 85  170 85 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  255 255 85  85 255 85
+255 255 85  255 255 85  85 255 85  255 255 85  255 255 85  255 255 85
+255 255 85  170 85 0  255 255 85  85 255 85  255 255 85  255 255 85
+170 85 0  170 85 0  85 255 85  170 85 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  85 85 85  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  170 170 170  170 170 170  85 85 85
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  255 255 85  255 255 85
+170 85 0  255 255 85  255 255 85  170 85 0  255 255 85  170 85 0
+255 255 85  85 255 85  170 85 0  255 255 85  170 85 0  85 255 85
+170 85 0  170 85 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  170 170 170  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  85 85 85  85 85 85  85 85 85
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 85 0  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  255 255 85  85 255 85
+170 85 0  255 255 85  170 85 0  85 255 85  170 85 0  170 85 0
+0 170 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  170 170 170  170 170 170  255 255 255  170 170 170
+170 170 170  170 170 170  85 85 85  85 85 85  85 85 85  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 255 85  255 255 85
+170 85 0  255 255 85  255 255 85  170 85 0  85 255 85  170 85 0
+255 255 85  170 85 0  0 170 0  170 85 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  170 170 170  170 170 170  170 170 170  85 85 85
+85 85 85  85 85 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  255 255 85
+255 255 85  255 255 85  255 255 85  255 255 85  170 85 0  170 85 0
+0 170 0  85 85 85  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+255 255 85  255 255 85  170 85 0  0 170 0  85 85 85  85 85 85
+85 85 85  85 85 85  0 0 0  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  85 85 85  85 85 85  170 170 170  170 170 170  85 85 85
+170 170 170  170 170 170  170 170 170  170 170 170  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  170 85 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  85 85 85  85 85 85  170 170 170  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+170 170 170  170 170 170  170 170 170  170 170 170  255 255 255  255 255 255
+255 255 255  255 255 255  255 255 255  170 170 170  255 255 255  170 170 170
+170 170 170  170 170 170  170 170 170  85 85 85  85 85 85  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  170 170 170  170 170 170
+255 255 255  255 255 255  255 255 255  170 170 170  255 255 255  170 170 170
+255 255 255  255 255 255  255 255 255  255 255 255  255 255 255  255 255 255
+255 255 255  255 255 255  255 255 255  255 255 255  255 255 255  255 255 255
+255 255 255  255 255 255  170 170 170  255 255 255  170 170 170  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  170 170 170  170 170 170
+255 255 255  170 170 170  255 255 255  255 255 255  255 255 255  255 255 255
+255 255 255  255 255 255  255 255 255  255 255 255  255 255 255  170 170 170
+255 255 255  255 255 255  170 170 170  255 255 255  255 255 255  255 255 255
+255 255 255  255 255 255  255 255 255  255 255 255  170 170 170  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  170 170 170
+170 170 170  170 170 170  255 255 255  170 170 170  255 255 255  170 170 170
+255 255 255  170 170 170  255 255 255  170 170 170  255 255 255  255 255 255
+255 255 255  170 170 170  255 255 255  170 170 170  255 255 255  170 170 170
+170 170 170  170 170 170  170 170 170  170 170 170  85 85 85  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  85 85 85  85 85 85  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  170 170 170  85 85 85  170 170 170
+170 170 170  170 170 170  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+170 170 170  85 85 85  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 170 170  85 85 85
+85 85 85  85 85 85  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  170 170 170  85 85 85
+85 85 85  85 85 85  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  85 85 85  170 170 170  85 85 85  85 85 85
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  170 170 170  170 170 170
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  170 170 170  85 85 85  85 85 85  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  255 255 255  170 170 170
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  170 170 170
+170 170 170  255 255 255  170 170 170  170 170 170
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 170 170  170 170 170
+255 255 255  255 255 255  170 170 170  170 170 170
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  170 170 170  170 170 170  255 255 255
+255 255 255  170 170 170  170 170 170  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+170 170 170  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  170 170 170  255 255 255  255 255 255  255 255 255
+170 170 170  170 170 170  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+170 170 170  170 170 170  255 255 255  255 255 255  255 255 255  170 170 170
+170 170 170  170 170 170  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 170 170  170 170 170
+170 170 170  255 255 255  255 255 255  255 255 255  170 170 170  170 170 170
+170 170 170  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  85 85 85  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  170 170 170  170 170 170  170 170 170
+255 255 255  255 255 255  255 255 255  255 255 255  170 170 170  170 170 170
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  85 85 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  170 170 170  255 255 255  255 255 255  255 255 255
+255 255 255  255 255 255  170 170 170  170 170 170  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  170 170 170  255 255 255  85 85 85  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+170 170 170  170 170 170  255 255 255  170 170 170  255 255 255  255 255 255
+255 255 255  255 255 255  170 170 170  170 170 170  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  170 170 170  255 255 255  170 170 170  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+255 255 255  170 170 170  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+255 255 255  255 255 255  255 255 255  255 255 255  255 255 255  255 255 255
+170 170 170  170 170 170  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  255 255 255  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  255 255 255  255 255 255  255 255 255  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  170 170 170
+255 255 255  170 170 170  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  170 170 170
+170 170 170  255 255 255  255 255 255  255 255 255  255 255 255  170 170 170
+170 170 170  170 170 170  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+170 170 170  255 255 255  255 255 255  170 170 170  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+85 85 85  170 170 170  255 255 255  255 255 255  255 255 255  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  255 255 255
+255 255 255  170 170 170  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  85 85 85  85 85 85  85 85 85
+170 170 170  255 255 255  255 255 255  255 255 255  170 170 170  170 170 170
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  170 170 170  170 170 170
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+170 170 170  255 255 255  255 255 255  255 255 255  85 85 85  0 0 0
+0 0 0  85 85 85  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  170 170 170  255 255 255  255 255 255  255 255 255  170 170 170
+0 0 0  85 85 85  0 0 0  85 85 85  170 170 170  255 255 255
+255 255 255  170 170 170  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  255 255 255  255 255 255  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  85 85 85  0 0 0  85 85 85  85 85 85
+170 170 170  170 170 170  170 170 170  170 170 170  170 170 170  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 170 170  255 255 255
+170 170 170  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  255 255 255  255 255 255  255 255 255  255 255 255  0 0 0
+0 0 0  85 85 85  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  255 255 255  255 255 255  255 255 255  170 170 170  170 170 170
+85 85 85  0 0 0  0 0 0  85 85 85  170 170 170  255 255 255
+255 255 255  170 170 170  0 0 0  0 0 0  0 0 0  0 0 0
+170 170 170  255 255 255  170 170 170  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  85 85 85  0 0 0  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  170 170 170  85 85 85  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  170 170 170
+255 255 255  170 170 170  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  255 255 255  255 255 255  255 255 255  170 170 170
+0 0 0  85 85 85  85 85 85  85 85 85  0 0 0  0 0 0
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+170 170 170  170 170 170  255 255 255  170 170 170  255 255 255  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  170 170 170  255 255 255
+170 170 170  170 170 170  0 0 0  0 0 0  0 0 0  85 85 85
+170 170 170  255 255 255  255 255 255  0 0 0  0 0 0  85 85 85
+255 255 255  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  85 85 85
+85 85 85  0 0 0  85 85 85  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  255 255 255
+255 255 255  255 255 255  170 170 170  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  255 255 255  170 170 170  170 170 170  170 170 170
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  85 85 85
+85 85 85  170 170 170  255 255 255  170 170 170  170 170 170  85 85 85
+85 85 85  0 0 0  85 85 85  85 85 85  85 85 85  170 170 170
+170 170 170  85 85 85  85 85 85  0 0 0  0 0 0  85 85 85
+170 170 170  170 170 170  85 85 85  0 0 0  0 0 0  170 170 170
+170 170 170  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 170 170  170 170 170
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  170 170 170
+255 255 255  170 170 170  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  170 170 170  170 170 170  255 255 85  85 85 85
+85 85 85  85 85 85  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  85 85 85  0 0 0  85 85 85
+85 85 85  170 170 170  170 170 170  170 170 170  170 85 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  170 170 170  170 85 0
+170 170 170  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+170 85 0  170 170 170  85 85 85  0 0 0  85 85 85  85 85 85
+170 170 170  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 170 170  255 255 255
+170 170 170  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+255 255 255  170 170 170  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  170 85 0  170 170 170  170 170 170  85 85 85
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  85 85 85
+85 85 85  170 85 0  85 255 85  170 85 0  170 170 170  85 85 85
+85 85 85  0 0 0  0 0 0  85 85 85  170 85 0  85 255 85
+170 85 0  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+85 85 85  85 85 85  170 85 0  0 0 0  85 85 85  85 85 85
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  255 255 255
+255 255 255  170 170 170  0 0 0  0 0 0  0 0 0  0 0 0
+170 170 170  170 170 170  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  170 170 170  170 85 0  170 170 170  170 85 0
+85 85 85  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  255 85 85  170 170 170  85 255 85  170 85 0
+85 85 85  85 85 85  170 85 0  85 85 85  170 170 170  85 85 85
+170 170 170  170 85 0  85 85 85  85 85 85  85 85 85  85 85 85
+170 85 0  85 255 85  85 85 85  85 85 85  85 85 85  170 85 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  0 0 0  0 0 0  0 0 0  170 170 170
+255 255 255  170 170 170  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 85 0  170 170 170  170 85 0  85 85 85  0 0 0
+85 85 85  85 85 85  85 255 85  170 170 170  170 170 170  170 85 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+0 0 0  85 85 85  85 85 85  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  85 255 85  255 85 85  170 170 170  170 170 170
+170 170 170  85 255 85  170 170 170  170 85 0  170 170 170  170 85 0
+170 170 170  85 85 85  85 255 85  170 85 0  170 170 170  170 85 0
+170 170 170  170 170 170  170 85 0  85 85 85  85 85 85  85 255 85
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  170 170 170  170 170 170  0 0 0  0 0 0  85 85 85
+170 170 170  170 170 170  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  255 255 85  85 85 85  85 85 85  85 85 85
+85 255 85  255 85 85  170 170 170  170 85 0  170 170 170  85 255 85
+85 85 85  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  170 85 0  170 170 170  170 170 170  255 255 85
+170 170 170  255 85 85  170 170 170  170 170 170  255 255 85  170 170 170
+85 255 85  170 170 170  255 85 85  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  170 85 0  170 170 170  170 85 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  170 170 170  85 85 85  0 0 0  85 85 85
+85 85 85  170 85 0  85 85 85  0 0 0  85 85 85  85 85 85
+85 85 85  170 85 0  170 170 170  170 170 170  255 255 85  170 170 170
+170 170 170  170 170 170  255 255 85  170 170 170  170 170 170  255 85 85
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  85 85 85  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  170 170 170  255 255 85  170 170 170  170 170 170
+170 170 170  255 255 85  170 170 170  170 170 170  170 170 170  170 85 0
+170 170 170  255 255 85  170 170 170  255 255 85  170 170 170  255 255 85
+170 170 170  255 255 85  170 170 170  170 170 170  85 255 85  170 85 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  170 170 170  85 85 85  85 85 85  0 0 0
+85 85 85  85 85 85  170 170 170  85 85 85  170 170 170  170 85 0
+170 170 170  85 255 85  170 170 170  170 85 0  170 170 170  170 170 170
+255 255 85  170 170 170  170 170 170  255 255 255  255 255 85  170 170 170
+255 255 85  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  85 85 85  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  170 85 0  170 170 170  170 170 170  170 170 170  255 255 255
+170 170 170  255 255 255  255 255 85  170 170 170  255 255 85  170 170 170
+255 255 85  170 170 170  170 170 170  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  255 85 85  170 170 170  170 170 170
+85 85 85  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  170 85 0  85 85 85
+85 85 85  255 255 85  170 170 170  170 170 170  170 170 170  170 170 170
+255 255 85  170 170 170  170 170 170  255 255 85  170 170 170  170 170 170
+170 170 170  255 255 255  255 255 255  170 170 170  255 255 255  170 170 170
+170 170 170  85 85 85  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  85 255 85  170 170 170  255 255 85  255 255 255  255 255 255
+255 255 255  170 170 170  255 255 255  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  255 255 85  170 170 170  255 255 85  255 255 255
+255 255 85  255 255 255  255 255 85  170 170 170  170 170 170  170 85 0
+170 170 170  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  170 170 170  255 255 85  170 170 170  255 255 85  170 170 170
+170 170 170  255 255 85  170 170 170  170 170 170  170 170 170  255 255 85
+255 255 255  255 255 255  255 255 85  255 255 255  255 255 255  170 170 170
+255 255 85  85 85 85  85 85 85  0 0 0  0 0 0  85 85 85
+85 85 85  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  170 170 170  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  170 170 170  170 170 170  170 170 170  255 255 255  170 170 170
+255 255 255  255 255 255  255 255 255  170 170 170  170 170 170  255 255 85
+170 170 170  255 255 85  170 170 170  255 255 255  170 170 170  255 255 255
+255 255 255  255 255 255  170 170 170  255 255 85  170 170 170  255 255 85
+85 85 85  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  170 85 0  170 170 170
+255 255 85  170 170 170  170 170 170  255 255 255  255 255 255  255 255 255
+170 170 170  170 170 170  170 170 170  255 255 85  170 170 170  170 170 170
+255 255 255  170 170 170  255 255 255  255 255 255  170 170 170  255 255 255
+170 170 170  170 170 170  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 170 170  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  85 85 85  85 85 85  0 0 0
+85 85 85  170 85 0  255 255 255  170 170 170  255 255 255  255 255 255
+255 255 85  255 255 255  170 170 170  255 255 85  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  255 255 85  255 255 255  255 255 255
+170 170 170  255 255 255  255 255 255  170 170 170  170 170 170  170 170 170
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 255 85  170 170 170
+170 170 170  255 255 85  170 170 170  255 255 255  170 170 170  255 255 255
+255 255 255  255 255 255  255 255 85  170 170 170  170 170 170  255 255 255
+170 170 170  255 255 255  255 255 255  170 170 170  255 255 255  255 255 85
+170 170 170  170 85 0  85 85 85  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  170 170 170  170 170 170  255 255 85  170 170 170  255 255 255
+255 255 255  170 170 170  255 255 255  170 170 170  170 170 170  255 255 85
+170 170 170  255 255 85  170 170 170  255 255 255  170 170 170  255 255 255
+255 255 255  255 255 255  255 255 255  255 255 255  170 170 170  255 255 85
+85 85 85  85 85 85  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  170 85 0  170 170 170
+170 170 170  255 255 255  255 255 255  255 255 255  255 255 255  255 255 255
+170 170 170  170 170 170  170 170 170  170 170 170  255 255 85  170 170 170
+255 255 85  255 255 255  170 170 170  255 255 255  170 170 170  170 170 170
+170 170 170  170 170 170  85 85 85  0 0 0  85 85 85  85 85 85
+0 0 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+85 85 85  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+85 85 85  85 85 85  170 170 170  170 170 170  255 255 255  170 170 170
+255 255 255  170 170 170  255 255 85  170 170 170  170 170 170  170 170 170
+255 85 85  170 170 170  170 170 170  170 170 170  255 255 255  255 255 255
+170 170 170  255 255 255  255 255 255  170 170 170  255 255 255  170 170 170
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  170 170 170
+255 255 85  170 170 170  255 255 255  170 170 170  255 255 255  255 255 255
+255 255 85  255 255 255  170 170 170  255 255 85  170 170 170  170 170 170
+170 170 170  170 170 170  255 255 85  170 170 170  170 170 170  255 255 85
+170 170 170  170 85 0  85 85 85  0 0 0  85 85 85  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  170 170 170  170 170 170
+170 170 170  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  170 170 170  255 255 85  170 170 170  170 170 170
+255 255 85  170 170 170  170 170 170  170 170 170  170 170 170  255 85 85
+85 255 85  170 170 170  170 170 170  170 170 170  255 255 85  170 170 170
+255 255 255  255 255 255  255 255 255  255 255 85  170 170 170  170 170 170
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  255 255 85
+170 170 170  170 170 170  255 255 255  255 255 255  255 255 255  170 170 170
+255 255 255  170 170 170  170 170 170  170 170 170  170 170 170  255 85 85
+170 170 170  170 170 170  170 170 170  170 170 170  170 170 170  170 170 170
+170 170 170  85 85 85  85 85 85  0 0 0  85 85 85  0 0 0
+85 85 85  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  170 170 170  170 170 170  170 170 170
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  170 85 0  170 170 170  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  170 85 0  170 170 170  85 255 85
+255 85 85  170 170 170  255 255 85  170 170 170  170 170 170  255 255 255
+255 255 255  170 170 170  255 255 255  255 255 255  170 170 170  170 170 170
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  170 170 170
+170 170 170  255 255 85  170 170 170  255 255 85  255 255 255  255 255 255
+170 170 170  170 170 170  255 255 85  170 170 170  255 85 85  85 255 85
+170 170 170  170 85 0  170 170 170  170 170 170  255 255 85  170 170 170
+170 85 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  85 85 85  85 85 85  85 85 85  170 170 170  255 255 85
+170 170 170  170 85 0  170 170 170  170 170 170  170 85 0  85 85 85
+170 170 170  170 85 0  85 85 85  170 170 170  170 170 170  170 170 170
+170 170 170  255 255 255  255 255 255  255 255 85  170 170 170  170 170 170
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  170 85 0
+170 170 170  170 170 170  255 255 255  170 170 170  255 255 255  170 170 170
+255 255 255  170 170 170  170 170 170  170 85 0  170 170 170  85 85 85
+170 170 170  170 170 170  170 85 0  170 170 170  170 85 0  85 85 85
+85 255 85  85 85 85  0 0 0  0 0 0  0 0 0  85 85 85
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+85 85 85  0 0 0  85 85 85  170 85 0  85 85 85  170 170 170
+170 85 0  170 170 170  85 255 85  170 85 0  170 170 170  85 85 85
+170 85 0  170 170 170  170 170 170  255 255 85  170 170 170  255 255 255
+255 255 85  255 255 255  170 170 170  170 170 170  170 170 170  170 85 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+170 170 170  170 170 170  170 170 170  170 170 170  170 170 170  255 255 85
+170 170 170  255 255 85  170 170 170  170 170 170  85 255 85  170 170 170
+170 85 0  170 85 0  170 170 170  85 255 85  85 85 85  170 170 170
+170 85 0  85 85 85  0 0 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  170 170 170  85 85 85
+0 0 0  0 0 0  0 0 0  85 85 85  170 85 0  85 85 85
+170 170 170  170 85 0  170 170 170  85 85 85  170 170 170  170 85 0
+170 170 170  85 255 85  170 85 0  170 170 170  170 170 170  170 170 170
+255 255 255  170 170 170  255 255 255  255 255 255  170 170 170  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+170 85 0  170 170 170  255 255 85  170 170 170  255 255 255  170 170 170
+170 170 170  170 170 170  170 170 170  170 85 0  170 170 170  170 85 0
+170 170 170  85 255 85  170 85 0  170 170 170  170 85 0  85 85 85
+85 85 85  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+85 255 85  170 170 170  170 85 0  170 170 170  170 85 0  85 255 85
+170 170 170  170 85 0  170 170 170  170 170 170  170 170 170  255 255 85
+170 170 170  255 255 255  170 170 170  170 170 170  170 170 170  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 85 0  85 85 85  170 170 170  255 255 85  170 170 170
+170 170 170  255 255 85  170 170 170  170 170 170  170 170 170  170 85 0
+170 170 170  85 85 85  170 170 170  170 85 0  170 170 170  85 85 85
+170 85 0  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  0 0 0  85 85 85  170 85 0
+85 85 85  255 85 85  85 255 85  170 85 0  170 170 170  170 170 170
+170 85 0  170 170 170  85 85 85  255 255 85  170 170 170  170 170 170
+255 255 255  170 170 170  255 255 255  255 255 85  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  170 170 170  170 85 0  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  255 255 85  85 85 85  170 170 170
+85 255 85  255 85 85  170 170 170  85 255 85  255 85 85  85 255 85
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  85 85 85  0 0 0  85 85 85
+85 85 85  85 255 85  255 85 85  170 170 170  85 255 85  170 85 0
+170 170 170  170 170 170  255 255 85  170 170 170  170 170 170  255 255 255
+170 170 170  255 255 255  170 170 170  170 170 170  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  170 170 170  85 85 85  255 255 85
+170 170 170  255 255 85  170 170 170  170 170 170  170 170 170  255 255 85
+85 85 85  255 255 85  170 170 170  170 85 0  170 170 170  85 85 85
+170 85 0  85 85 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+170 170 170  170 85 0  170 170 170  170 85 0  170 170 170  170 170 170
+170 85 0  170 170 170  170 170 170  170 170 170  255 255 85  170 170 170
+255 255 85  255 255 255  170 170 170  170 170 170  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  170 85 0  85 85 85  170 170 170
+170 85 0  170 170 170  170 170 170  255 255 85  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  255 255 85  170 170 170  170 85 0
+85 85 85  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+170 85 0  85 255 85  170 170 170  170 170 170  255 255 85  170 170 170
+255 255 85  170 170 170  170 170 170  170 170 170  255 255 255  255 255 255
+255 255 255  170 170 170  255 255 85  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  170 85 0
+170 170 170  170 170 170  170 170 170  170 170 170  170 170 170  255 255 85
+170 170 170  255 255 85  170 170 170  170 170 170  170 170 170  170 170 170
+170 170 170  85 85 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  170 85 0  170 170 170  170 85 0  170 170 170  170 170 170
+170 170 170  255 255 85  170 170 170  255 255 85  170 170 170  255 255 255
+170 170 170  255 255 255  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  85 85 85  85 85 85  85 85 85
+170 85 0  170 170 170  170 85 0  255 255 85  170 170 170  170 170 170
+170 170 170  170 170 170  255 255 85  170 170 170  255 255 85  170 170 170
+255 255 85  85 85 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+85 85 85  170 170 170  255 255 85  170 170 170  255 255 85  170 170 170
+170 170 170  255 255 255  255 255 255  255 255 255  255 255 255  255 255 255
+170 170 170  170 170 170  170 170 170  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 170 0  85 85 85
+170 85 0  85 255 85  170 170 170  170 170 170  170 170 170  255 255 85
+255 255 255  170 170 170  255 255 255  170 170 170  255 255 255  170 170 170
+170 170 170  255 255 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+170 85 0  170 170 170  170 170 170  170 170 170  170 170 170  255 255 85
+170 170 170  255 255 255  170 170 170  255 255 255  170 170 170  255 255 255
+255 255 255  255 255 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  170 85 0  170 170 170  170 170 170  255 255 85  170 170 170
+170 170 170  255 255 255  255 255 255  255 255 255  170 170 170  255 255 255
+170 170 170  170 170 170  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 255 85
+170 170 170  255 255 85  170 170 170  255 255 85  255 255 255  255 255 255
+255 255 255  255 255 255  255 255 255  255 255 255  255 255 255  170 170 170
+170 170 170  170 170 170  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  85 85 85  170 85 0  170 170 170  170 170 170
+255 255 85  170 170 170  255 255 255  255 255 85  255 255 255  255 255 255
+170 170 170  255 255 85  170 170 170  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  170 85 0
+170 170 170  170 170 170  170 170 170  255 255 255  170 170 170  255 255 255
+170 170 170  255 255 255  170 170 170  255 255 255  255 255 85  255 255 255
+170 170 170  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  170 85 0  85 85 85  170 170 170  170 170 170  170 170 170
+170 170 170  255 255 255  170 170 170  255 255 255  255 255 255  170 170 170
+255 255 85  170 170 170  170 170 170  170 85 0  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  170 170 170
+255 255 85  170 170 170  255 255 85  170 170 170  255 255 255  255 255 255
+255 255 255  255 255 255  255 255 255  255 255 255  170 170 170  170 170 170
+170 170 170  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  85 85 85  85 85 85  170 85 0  170 170 170
+255 255 85  170 170 170  255 255 85  255 255 255  170 170 170  255 255 255
+170 170 170  170 170 170  170 170 170  170 170 170  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  170 170 170
+170 85 0  170 170 170  255 255 255  170 170 170  255 255 255  170 170 170
+255 255 255  255 255 255  170 170 170  255 255 255  255 255 85  170 170 170
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  85 85 85  170 85 0  85 85 85  170 170 170
+170 170 170  170 170 170  170 170 170  170 170 170  255 255 85  170 170 170
+255 255 85  170 170 170  170 85 0  85 255 85  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  170 85 0
+170 170 170  170 170 170  255 255 85  170 170 170  255 255 255  255 255 255
+255 255 85  255 255 255  170 170 170  255 255 255  170 170 170  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+170 85 0  170 170 170  170 170 170  255 255 85  170 170 170  170 170 170
+170 170 170  170 170 170  170 170 170  170 85 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+255 255 85  170 170 170  170 170 170  170 170 170  255 255 85  170 170 170
+255 255 255  170 170 170  255 255 85  170 170 170  85 85 85  85 85 85
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+85 85 85  170 85 0  170 170 170  170 170 170  170 170 170  170 170 170
+170 85 0  170 170 170  170 85 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  85 85 85  85 85 85
+170 170 170  170 170 170  255 255 85  170 170 170  170 170 170  170 170 170
+170 170 170  255 255 255  170 170 170  170 170 170  85 85 85  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+85 85 85  85 85 85  85 85 85  170 85 0  85 85 85  170 85 0
+85 85 85  85 85 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  170 85 0
+85 85 85  170 85 0  170 170 170  170 170 170  170 170 170  255 255 85
+170 170 170  170 170 170  170 85 0  85 85 85  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  85 85 85  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  85 85 85
+85 85 85  85 255 85  170 85 0  170 170 170  170 85 0  170 170 170
+85 85 85  85 85 85  85 85 85  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  85 85 85  85 85 85  85 85 85  85 85 85  85 85 85
+85 85 85  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index 3a3f80f..0573ec6 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -151,7 +151,7 @@
 
 	info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev);
 	if (!info) {
-		printk(KERN_ERR "%s: Cannot allocate memory\n", dev->bus_id);
+		printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev));
 		return -ENOMEM;
 	}
 
@@ -160,7 +160,7 @@
 
 	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
 		printk(KERN_ERR "%s: Cannot allocate color map\n",
-		       dev->bus_id);
+		       dev_name(dev));
 		err = -ENOMEM;
 		goto err_alloc;
 	}
@@ -173,8 +173,9 @@
 	/* Request the I/O MEM resource.  */
 	start = tdev->resource.start;
 	len = tdev->resource.end - start + 1;
-	if (!request_mem_region(start, len, dev->bus_id)) {
-		printk(KERN_ERR "%s: Cannot reserve FB region\n", dev->bus_id);
+	if (!request_mem_region(start, len, dev_name(dev))) {
+		printk(KERN_ERR "%s: Cannot reserve FB region\n",
+		       dev_name(dev));
 		err = -EBUSY;
 		goto err_cmap;
 	}
@@ -183,7 +184,7 @@
 	info->fix.mmio_start = start;
 	par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
 	if (!par->mmio) {
-		printk(KERN_ERR "%s: Cannot map MMIO\n", dev->bus_id);
+		printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev));
 		err = -ENOMEM;
 		goto err_resource;
 	}
@@ -194,7 +195,7 @@
 	info->screen_base = ioremap_nocache(info->fix.smem_start,
 					    info->fix.smem_len);
 	if (!info->screen_base) {
-		printk(KERN_ERR "%s: Cannot map FB\n", dev->bus_id);
+		printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev));
 		err = -ENOMEM;
 		goto err_mmio_map;
 	}
@@ -205,14 +206,14 @@
 	err = register_framebuffer(info);
 	if (err < 0) {
 		printk(KERN_ERR "%s: Cannot register framebuffer\n",
-		       dev->bus_id);
+		       dev_name(dev));
 		goto err_smem_map;
 	}
 
 	get_device(dev);
 
 	pr_info("fb%d: %s frame buffer device at %s\n",
-		info->node, info->fix.id, dev->bus_id);
+		info->node, info->fix.id, dev_name(dev));
 
 	return 0;
 
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 9b80597..9874872 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -258,7 +258,7 @@
 
 	info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev);
 	if (!info) {
-		printk(KERN_ERR "%s: Cannot allocate memory\n", dev->bus_id);
+		printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev));
 		return -ENOMEM;
 	}
 
@@ -267,7 +267,7 @@
 
 	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
 		printk(KERN_ERR "%s: Cannot allocate color map\n",
-		       dev->bus_id);
+		       dev_name(dev));
 		err = -ENOMEM;
 		goto err_alloc;
 	}
@@ -280,8 +280,9 @@
 	/* Request the I/O MEM resource.  */
 	start = tdev->resource.start;
 	len = tdev->resource.end - start + 1;
-	if (!request_mem_region(start, len, dev->bus_id)) {
-		printk(KERN_ERR "%s: Cannot reserve FB region\n", dev->bus_id);
+	if (!request_mem_region(start, len, dev_name(dev))) {
+		printk(KERN_ERR "%s: Cannot reserve FB region\n",
+		       dev_name(dev));
 		err = -EBUSY;
 		goto err_cmap;
 	}
@@ -290,7 +291,7 @@
 	info->fix.mmio_start = start;
 	par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
 	if (!par->mmio) {
-		printk(KERN_ERR "%s: Cannot map MMIO\n", dev->bus_id);
+		printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev));
 		err = -ENOMEM;
 		goto err_resource;
 	}
@@ -301,7 +302,7 @@
 	info->fix.smem_start = start + PMAGB_B_FBMEM;
 	par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
 	if (!par->smem) {
-		printk(KERN_ERR "%s: Cannot map FB\n", dev->bus_id);
+		printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev));
 		err = -ENOMEM;
 		goto err_mmio_map;
 	}
@@ -316,7 +317,7 @@
 	err = register_framebuffer(info);
 	if (err < 0) {
 		printk(KERN_ERR "%s: Cannot register framebuffer\n",
-		       dev->bus_id);
+		       dev_name(dev));
 		goto err_smem_map;
 	}
 
@@ -328,7 +329,7 @@
 		 par->osc1 / 1000, par->osc1 % 1000);
 
 	pr_info("fb%d: %s frame buffer device at %s\n",
-		info->node, info->fix.id, dev->bus_id);
+		info->node, info->fix.id, dev_name(dev));
 	pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n",
 		info->node, freq0, par->osc1 ? freq1 : "disabled",
 		par->osc1 != 0);
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 87f826e..e00c1df 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -1213,7 +1213,7 @@
 	dev->core.driver_data = info;
 
 	dev_info(info->device, "%s %s, using %u KiB of video memory\n",
-		 dev_driver_string(info->dev), info->dev->bus_id,
+		 dev_driver_string(info->dev), dev_name(info->dev),
 		 info->fix.smem_len >> 10);
 
 	task = kthread_run(ps3fbd, info, DEVICE_NAME);
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 0a0fd48..53f8f11 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -61,7 +61,7 @@
 #include <mach-dreamcast/mach/sysasic.h>
 #endif
 
-#ifdef CONFIG_SH_DMA
+#ifdef CONFIG_PVR2_DMA
 #include <linux/pagemap.h>
 #include <mach/dma.h>
 #include <asm/dma.h>
@@ -188,7 +188,7 @@
 static unsigned long pvr2fb_map;
 #endif
 
-#ifdef CONFIG_SH_DMA
+#ifdef CONFIG_PVR2_DMA
 static unsigned int shdma = PVR2_CASCADE_CHAN;
 static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS;
 #endif
@@ -207,7 +207,7 @@
 static int pvr2_init_cable(void);
 static int pvr2_get_param(const struct pvr2_params *p, const char *s,
                             int val, int size);
-#ifdef CONFIG_SH_DMA
+#ifdef CONFIG_PVR2_DMA
 static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
 			    size_t count, loff_t *ppos);
 #endif
@@ -218,7 +218,7 @@
 	.fb_blank	= pvr2fb_blank,
 	.fb_check_var	= pvr2fb_check_var,
 	.fb_set_par	= pvr2fb_set_par,
-#ifdef CONFIG_SH_DMA
+#ifdef CONFIG_PVR2_DMA
 	.fb_write	= pvr2fb_write,
 #endif
 	.fb_fillrect	= cfb_fillrect,
@@ -671,7 +671,7 @@
 	return cable_type;
 }
 
-#ifdef CONFIG_SH_DMA
+#ifdef CONFIG_PVR2_DMA
 static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
 			    size_t count, loff_t *ppos)
 {
@@ -743,7 +743,7 @@
 
 	return ret;
 }
-#endif /* CONFIG_SH_DMA */
+#endif /* CONFIG_PVR2_DMA */
 
 /**
  * pvr2fb_common_init
@@ -893,7 +893,7 @@
 		return -EBUSY;
 	}
 
-#ifdef CONFIG_SH_DMA
+#ifdef CONFIG_PVR2_DMA
 	if (request_dma(pvr2dma, "pvr2") != 0) {
 		free_irq(HW_EVENT_VSYNC, 0);
 		return -EBUSY;
@@ -915,7 +915,7 @@
 	}
 
 	free_irq(HW_EVENT_VSYNC, 0);
-#ifdef CONFIG_SH_DMA
+#ifdef CONFIG_PVR2_DMA
 	free_dma(pvr2dma);
 #endif
 }
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 0e2b8fd..92ea0ab 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -33,6 +33,8 @@
 	struct fb_info info;
 	dma_addr_t dma_handle;
 	struct fb_deferred_io defio;
+	unsigned long frame_end;
+	wait_queue_head_t frame_end_wait;
 };
 
 struct sh_mobile_lcdc_priv {
@@ -226,7 +228,10 @@
 static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
 {
 	struct sh_mobile_lcdc_priv *priv = data;
+	struct sh_mobile_lcdc_chan *ch;
 	unsigned long tmp;
+	int is_sub;
+	int k;
 
 	/* acknowledge interrupt */
 	tmp = lcdc_read(priv, _LDINTR);
@@ -234,8 +239,24 @@
 	tmp |= 0x000000ff ^ LDINTR_FS; /* status in low 8 */
 	lcdc_write(priv, _LDINTR, tmp);
 
-	/* disable clocks */
-	sh_mobile_lcdc_clk_off(priv);
+	/* figure out if this interrupt is for main or sub lcd */
+	is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0;
+
+	/* wake up channel and disable clocks*/
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		ch = &priv->ch[k];
+
+		if (!ch->enabled)
+			continue;
+
+		if (is_sub == lcdc_chan_is_sublcd(ch)) {
+			ch->frame_end = 1;
+			wake_up(&ch->frame_end_wait);
+
+			sh_mobile_lcdc_clk_off(priv);
+		}
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -446,22 +467,29 @@
 {
 	struct sh_mobile_lcdc_chan *ch;
 	struct sh_mobile_lcdc_board_cfg	*board_cfg;
-	unsigned long tmp;
 	int k;
 
-	/* tell the board code to disable the panel */
+	/* clean up deferred io and ask board code to disable panel */
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 		ch = &priv->ch[k];
+
+		/* deferred io mode:
+		 * flush frame, and wait for frame end interrupt
+		 * clean up deferred io and enable clock
+		 */
+		if (ch->info.fbdefio) {
+			ch->frame_end = 0;
+			schedule_delayed_work(&ch->info.deferred_work, 0);
+			wait_event(ch->frame_end_wait, ch->frame_end);
+			fb_deferred_io_cleanup(&ch->info);
+			ch->info.fbdefio = NULL;
+			sh_mobile_lcdc_clk_on(priv);
+		}
+
 		board_cfg = &ch->cfg.board_cfg;
 		if (board_cfg->display_off)
 			board_cfg->display_off(board_cfg->board_data);
 
-		/* cleanup deferred io if SYS bus */
-		tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
-		if (ch->ldmt1r_value & (1 << 12) && tmp) {
-			fb_deferred_io_cleanup(&ch->info);
-			ch->info.fbdefio = NULL;
-		}
 	}
 
 	/* stop the lcdc */
@@ -654,6 +682,26 @@
 	return 0;
 }
 
+static int sh_mobile_lcdc_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	sh_mobile_lcdc_stop(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static int sh_mobile_lcdc_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
+}
+
+static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
+	.suspend = sh_mobile_lcdc_suspend,
+	.resume = sh_mobile_lcdc_resume,
+};
+
 static int sh_mobile_lcdc_remove(struct platform_device *pdev);
 
 static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
@@ -689,7 +737,7 @@
 	}
 
 	error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED,
-			    pdev->dev.bus_id, priv);
+			    dev_name(&pdev->dev), priv);
 	if (error) {
 		dev_err(&pdev->dev, "unable to request irq\n");
 		goto err1;
@@ -709,6 +757,7 @@
 			dev_err(&pdev->dev, "unsupported interface type\n");
 			goto err1;
 		}
+		init_waitqueue_head(&priv->ch[i].frame_end_wait);
 
 		switch (pdata->ch[i].chan) {
 		case LCDC_CHAN_MAINLCD:
@@ -862,6 +911,7 @@
 	.driver		= {
 		.name		= "sh_mobile_lcdc_fb",
 		.owner		= THIS_MODULE,
+		.pm		= &sh_mobile_lcdc_dev_pm_ops,
 	},
 	.probe		= sh_mobile_lcdc_probe,
 	.remove		= sh_mobile_lcdc_remove,
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
index 7baf2dd..a1eb086 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/tmiofb.c
@@ -751,7 +751,7 @@
 	}
 
 	retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED,
-					dev->dev.bus_id, info);
+					dev_name(&dev->dev), info);
 
 	if (retval)
 		goto err_request_irq;
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index 9e1138a..a411702 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -39,7 +39,7 @@
 {
 	struct w1_gpio_platform_data *pdata = data;
 
-	return gpio_get_value(pdata->pin);
+	return gpio_get_value(pdata->pin) ? 1 : 0;
 }
 
 static int __init w1_gpio_probe(struct platform_device *pdev)
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index f0c2b7a..734d980 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -269,7 +269,7 @@
 	bus_clk = 133; /* in MHz */
 
 	freq = fsl_get_sys_freq();
-	if (freq > 0)
+	if (freq != -1)
 		bus_clk = freq;
 
 	/* Map devices registers into memory */
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index 0b798fd..74c92d3 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -21,6 +21,7 @@
 #include <linux/watchdog.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
+#include <mach/timex.h>
 #include <mach/regs-timer.h>
 
 #define WDT_DEFAULT_TIME	5	/* seconds */
diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c
index 14a339f..b64ae1a 100644
--- a/drivers/watchdog/orion5x_wdt.c
+++ b/drivers/watchdog/orion5x_wdt.c
@@ -29,6 +29,7 @@
 #define  WDT_EN			0x0010
 #define WDT_VAL			(TIMER_VIRT_BASE + 0x0024)
 
+#define ORION5X_TCLK		166666667
 #define WDT_MAX_DURATION	(0xffffffff / ORION5X_TCLK)
 #define WDT_IN_USE		0
 #define WDT_OK_TO_CLOSE		1
diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
index 57027f4..f3553fa 100644
--- a/drivers/watchdog/rc32434_wdt.c
+++ b/drivers/watchdog/rc32434_wdt.c
@@ -34,104 +34,89 @@
 #include <asm/time.h>
 #include <asm/mach-rc32434/integ.h>
 
-#define MAX_TIMEOUT			20
-#define RC32434_WDT_INTERVAL		(15 * HZ)
-
-#define VERSION "0.2"
+#define VERSION "0.4"
 
 static struct {
-	struct completion stop;
-	int running;
-	struct timer_list timer;
-	int queue;
-	int default_ticks;
 	unsigned long inuse;
 } rc32434_wdt_device;
 
 static struct integ __iomem *wdt_reg;
-static int ticks = 100 * HZ;
 
 static int expect_close;
-static int timeout;
+
+/* Board internal clock speed in Hz,
+ * the watchdog timer ticks at. */
+extern unsigned int idt_cpu_freq;
+
+/* translate wtcompare value to seconds and vice versa */
+#define WTCOMP2SEC(x)	(x / idt_cpu_freq)
+#define SEC2WTCOMP(x)	(x * idt_cpu_freq)
+
+/* Use a default timeout of 20s. This should be
+ * safe for CPU clock speeds up to 400MHz, as
+ * ((2 ^ 32) - 1) / (400MHz / 2) = 21s.  */
+#define WATCHDOG_TIMEOUT 20
+
+static int timeout = WATCHDOG_TIMEOUT;
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
 	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
+/* apply or and nand masks to data read from addr and write back */
+#define SET_BITS(addr, or, nand) \
+	writel((readl(&addr) | or) & ~nand, &addr)
 
 static void rc32434_wdt_start(void)
 {
-	u32 val;
+	u32 or, nand;
 
-	if (!rc32434_wdt_device.inuse) {
-		writel(0, &wdt_reg->wtcount);
+	/* zero the counter before enabling */
+	writel(0, &wdt_reg->wtcount);
 
-		val = RC32434_ERR_WRE;
-		writel(readl(&wdt_reg->errcs) | val, &wdt_reg->errcs);
+	/* don't generate a non-maskable interrupt,
+	 * do a warm reset instead */
+	nand = 1 << RC32434_ERR_WNE;
+	or = 1 << RC32434_ERR_WRE;
 
-		val = RC32434_WTC_EN;
-		writel(readl(&wdt_reg->wtc) | val, &wdt_reg->wtc);
-	}
-	rc32434_wdt_device.running++;
+	/* reset the ERRCS timeout bit in case it's set */
+	nand |= 1 << RC32434_ERR_WTO;
+
+	SET_BITS(wdt_reg->errcs, or, nand);
+
+	/* reset WTC timeout bit and enable WDT */
+	nand = 1 << RC32434_WTC_TO;
+	or = 1 << RC32434_WTC_EN;
+
+	SET_BITS(wdt_reg->wtc, or, nand);
 }
 
 static void rc32434_wdt_stop(void)
 {
-	u32 val;
+	/* Disable WDT */
+	SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN);
+}
 
-	if (rc32434_wdt_device.running) {
+static int rc32434_wdt_set(int new_timeout)
+{
+	int max_to = WTCOMP2SEC((u32)-1);
 
-		val = ~RC32434_WTC_EN;
-		writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc);
-
-		val = ~RC32434_ERR_WRE;
-		writel(readl(&wdt_reg->errcs) & val, &wdt_reg->errcs);
-
-		rc32434_wdt_device.running = 0;
+	if (new_timeout < 0 || new_timeout > max_to) {
+		printk(KERN_ERR KBUILD_MODNAME
+			": timeout value must be between 0 and %d",
+			max_to);
+		return -EINVAL;
 	}
-}
-
-static void rc32434_wdt_set(int new_timeout)
-{
-	u32 cmp = new_timeout * HZ;
-	u32 state, val;
-
 	timeout = new_timeout;
-	/*
-	 * store and disable WTC
-	 */
-	state = (u32)(readl(&wdt_reg->wtc) & RC32434_WTC_EN);
-	val = ~RC32434_WTC_EN;
-	writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc);
+	writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare);
 
-	writel(0, &wdt_reg->wtcount);
-	writel(cmp, &wdt_reg->wtcompare);
-
-	/*
-	 * restore WTC
-	 */
-
-	writel(readl(&wdt_reg->wtc) | state, &wdt_reg);
+	return 0;
 }
 
-static void rc32434_wdt_reset(void)
+static void rc32434_wdt_ping(void)
 {
-	ticks = rc32434_wdt_device.default_ticks;
-}
-
-static void rc32434_wdt_update(unsigned long unused)
-{
-	if (rc32434_wdt_device.running)
-		ticks--;
-
 	writel(0, &wdt_reg->wtcount);
-
-	if (rc32434_wdt_device.queue && ticks)
-		mod_timer(&rc32434_wdt_device.timer,
-			jiffies + RC32434_WDT_INTERVAL);
-	else
-		complete(&rc32434_wdt_device.stop);
 }
 
 static int rc32434_wdt_open(struct inode *inode, struct file *file)
@@ -142,19 +127,23 @@
 	if (nowayout)
 		__module_get(THIS_MODULE);
 
+	rc32434_wdt_start();
+	rc32434_wdt_ping();
+
 	return nonseekable_open(inode, file);
 }
 
 static int rc32434_wdt_release(struct inode *inode, struct file *file)
 {
-	if (expect_close && nowayout == 0) {
+	if (expect_close == 42) {
 		rc32434_wdt_stop();
 		printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n");
 		module_put(THIS_MODULE);
-	} else
+	} else {
 		printk(KERN_CRIT KBUILD_MODNAME
 			": device closed unexpectedly. WDT will not stop !\n");
-
+		rc32434_wdt_ping();
+	}
 	clear_bit(0, &rc32434_wdt_device.inuse);
 	return 0;
 }
@@ -174,10 +163,10 @@
 				if (get_user(c, data + i))
 					return -EFAULT;
 				if (c == 'V')
-					expect_close = 1;
+					expect_close = 42;
 			}
 		}
-		rc32434_wdt_update(0);
+		rc32434_wdt_ping();
 		return len;
 	}
 	return 0;
@@ -197,11 +186,11 @@
 	};
 	switch (cmd) {
 	case WDIOC_KEEPALIVE:
-		rc32434_wdt_reset();
+		rc32434_wdt_ping();
 		break;
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETBOOTSTATUS:
-		value = readl(&wdt_reg->wtcount);
+		value = 0;
 		if (copy_to_user(argp, &value, sizeof(int)))
 			return -EFAULT;
 		break;
@@ -218,6 +207,7 @@
 			break;
 		case WDIOS_DISABLECARD:
 			rc32434_wdt_stop();
+			break;
 		default:
 			return -EINVAL;
 		}
@@ -225,11 +215,9 @@
 	case WDIOC_SETTIMEOUT:
 		if (copy_from_user(&new_timeout, argp, sizeof(int)))
 			return -EFAULT;
-		if (new_timeout < 1)
+		if (rc32434_wdt_set(new_timeout))
 			return -EINVAL;
-		if (new_timeout > MAX_TIMEOUT)
-			return -EINVAL;
-		rc32434_wdt_set(new_timeout);
+		/* Fall through */
 	case WDIOC_GETTIMEOUT:
 		return copy_to_user(argp, &timeout, sizeof(int));
 	default:
@@ -254,15 +242,15 @@
 	.fops	= &rc32434_wdt_fops,
 };
 
-static char banner[] = KERN_INFO KBUILD_MODNAME
+static char banner[] __devinitdata = KERN_INFO KBUILD_MODNAME
 		": Watchdog Timer version " VERSION ", timer margin: %d sec\n";
 
-static int rc32434_wdt_probe(struct platform_device *pdev)
+static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct resource *r;
 
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb500_wdt_res");
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res");
 	if (!r) {
 		printk(KERN_ERR KBUILD_MODNAME
 			"failed to retrieve resources\n");
@@ -277,24 +265,12 @@
 	}
 
 	ret = misc_register(&rc32434_wdt_miscdev);
-
 	if (ret < 0) {
 		printk(KERN_ERR KBUILD_MODNAME
 			"failed to register watchdog device\n");
 		goto unmap;
 	}
 
-	init_completion(&rc32434_wdt_device.stop);
-	rc32434_wdt_device.queue = 0;
-
-	clear_bit(0, &rc32434_wdt_device.inuse);
-
-	setup_timer(&rc32434_wdt_device.timer, rc32434_wdt_update, 0L);
-
-	rc32434_wdt_device.default_ticks = ticks;
-
-	rc32434_wdt_start();
-
 	printk(banner, timeout);
 
 	return 0;
@@ -304,23 +280,17 @@
 	return ret;
 }
 
-static int rc32434_wdt_remove(struct platform_device *pdev)
+static int __devexit rc32434_wdt_remove(struct platform_device *pdev)
 {
-	if (rc32434_wdt_device.queue) {
-		rc32434_wdt_device.queue = 0;
-		wait_for_completion(&rc32434_wdt_device.stop);
-	}
 	misc_deregister(&rc32434_wdt_miscdev);
-
 	iounmap(wdt_reg);
-
 	return 0;
 }
 
 static struct platform_driver rc32434_wdt = {
 	.probe	= rc32434_wdt_probe,
-	.remove = rc32434_wdt_remove,
-	.driver = {
+	.remove	= __devexit_p(rc32434_wdt_remove),
+	.driver	= {
 		.name = "rc32434_wdt",
 	}
 };
diff --git a/drivers/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c
index f1ae3729..cce1982 100644
--- a/drivers/watchdog/rm9k_wdt.c
+++ b/drivers/watchdog/rm9k_wdt.c
@@ -59,8 +59,8 @@
 static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *);
 static const struct resource *wdt_gpi_get_resource(struct platform_device *,
 						const char *, unsigned int);
-static int __init wdt_gpi_probe(struct device *);
-static int __exit wdt_gpi_remove(struct device *);
+static int __init wdt_gpi_probe(struct platform_device *);
+static int __exit wdt_gpi_remove(struct platform_device *);
 
 
 static const char wdt_gpi_name[] = "wdt_gpi";
@@ -346,10 +346,9 @@
 }
 
 /* No hotplugging on the platform bus - use __init */
-static int __init wdt_gpi_probe(struct device *dev)
+static int __init wdt_gpi_probe(struct platform_device *pdv)
 {
 	int res;
-	struct platform_device * const pdv = to_platform_device(dev);
 	const struct resource
 		* const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS,
 						  IORESOURCE_MEM),
@@ -374,7 +373,7 @@
 	return res;
 }
 
-static int __exit wdt_gpi_remove(struct device *dev)
+static int __exit wdt_gpi_remove(struct platform_device *dev)
 {
 	int res;
 
@@ -387,15 +386,13 @@
 
 
 /* Device driver init & exit */
-static struct device_driver wdt_gpi_driver = {
-	.name		= (char *) wdt_gpi_name,
-	.bus		= &platform_bus_type,
-	.owner		= THIS_MODULE,
+static struct platform_driver wgt_gpi_driver = {
+	.driver = {
+		.name		= wdt_gpi_name,
+		.owner		= THIS_MODULE,
+	},
 	.probe		= wdt_gpi_probe,
-	.remove		= __exit_p(wdt_gpi_remove),
-	.shutdown	= NULL,
-	.suspend	= NULL,
-	.resume		= NULL,
+	.remove		= __devexit_p(wdt_gpi_remove),
 };
 
 static int __init wdt_gpi_init_module(void)
@@ -403,12 +400,12 @@
 	atomic_set(&opencnt, 1);
 	if (timeout > MAX_TIMEOUT_SECONDS)
 		timeout = MAX_TIMEOUT_SECONDS;
-	return driver_register(&wdt_gpi_driver);
+	return platform_driver_register(&wdt_gpi_driver);
 }
 
 static void __exit wdt_gpi_cleanup_module(void)
 {
-	driver_unregister(&wdt_gpi_driver);
+	platform_driver_unregister(&wdt_gpi_driver);
 }
 
 module_init(wdt_gpi_init_module);
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index a1585d6..d45fb34 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -140,7 +140,7 @@
 
     /* Initialize the Zorro bus */
     INIT_LIST_HEAD(&zorro_bus.devices);
-    strcpy(zorro_bus.dev.bus_id, "zorro");
+    dev_set_name(&zorro_bus.dev, "zorro");
     error = device_register(&zorro_bus.dev);
     if (error) {
 	pr_err("Zorro: Error registering zorro_bus\n");
@@ -167,7 +167,7 @@
 	if (request_resource(zorro_find_parent_resource(z), &z->resource))
 	    pr_err("Zorro: Address space collision on device %s %pR\n",
 		   z->name, &z->resource);
-	sprintf(z->dev.bus_id, "%02x", i);
+	dev_set_name(&z->dev, "%02x", i);
 	z->dev.parent = &zorro_bus.dev;
 	z->dev.bus = &zorro_bus_type;
 	error = device_register(&z->dev);
diff --git a/fs/aio.c b/fs/aio.c
index 8fa77e2..76da125 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -443,7 +443,7 @@
 	req->private = NULL;
 	req->ki_iovec = NULL;
 	INIT_LIST_HEAD(&req->ki_run_list);
-	req->ki_eventfd = ERR_PTR(-EINVAL);
+	req->ki_eventfd = NULL;
 
 	/* Check if the completion queue has enough free space to
 	 * accept an event from this io.
@@ -485,8 +485,6 @@
 {
 	assert_spin_locked(&ctx->ctx_lock);
 
-	if (!IS_ERR(req->ki_eventfd))
-		fput(req->ki_eventfd);
 	if (req->ki_dtor)
 		req->ki_dtor(req);
 	if (req->ki_iovec != &req->ki_inline_vec)
@@ -508,8 +506,11 @@
 		list_del(&req->ki_list);
 		spin_unlock_irq(&fput_lock);
 
-		/* Complete the fput */
-		__fput(req->ki_filp);
+		/* Complete the fput(s) */
+		if (req->ki_filp != NULL)
+			__fput(req->ki_filp);
+		if (req->ki_eventfd != NULL)
+			__fput(req->ki_eventfd);
 
 		/* Link the iocb into the context's free list */
 		spin_lock_irq(&ctx->ctx_lock);
@@ -527,12 +528,14 @@
  */
 static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
 {
+	int schedule_putreq = 0;
+
 	dprintk(KERN_DEBUG "aio_put(%p): f_count=%ld\n",
 		req, atomic_long_read(&req->ki_filp->f_count));
 
 	assert_spin_locked(&ctx->ctx_lock);
 
-	req->ki_users --;
+	req->ki_users--;
 	BUG_ON(req->ki_users < 0);
 	if (likely(req->ki_users))
 		return 0;
@@ -540,10 +543,23 @@
 	req->ki_cancel = NULL;
 	req->ki_retry = NULL;
 
-	/* Must be done under the lock to serialise against cancellation.
-	 * Call this aio_fput as it duplicates fput via the fput_work.
+	/*
+	 * Try to optimize the aio and eventfd file* puts, by avoiding to
+	 * schedule work in case it is not __fput() time. In normal cases,
+	 * we would not be holding the last reference to the file*, so
+	 * this function will be executed w/out any aio kthread wakeup.
 	 */
-	if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) {
+	if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count)))
+		schedule_putreq++;
+	else
+		req->ki_filp = NULL;
+	if (req->ki_eventfd != NULL) {
+		if (unlikely(atomic_long_dec_and_test(&req->ki_eventfd->f_count)))
+			schedule_putreq++;
+		else
+			req->ki_eventfd = NULL;
+	}
+	if (unlikely(schedule_putreq)) {
 		get_ioctx(ctx);
 		spin_lock(&fput_lock);
 		list_add(&req->ki_list, &fput_head);
@@ -571,7 +587,7 @@
 static struct kioctx *lookup_ioctx(unsigned long ctx_id)
 {
 	struct mm_struct *mm = current->mm;
-	struct kioctx *ctx = NULL;
+	struct kioctx *ctx, *ret = NULL;
 	struct hlist_node *n;
 
 	rcu_read_lock();
@@ -579,12 +595,13 @@
 	hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) {
 		if (ctx->user_id == ctx_id && !ctx->dead) {
 			get_ioctx(ctx);
+			ret = ctx;
 			break;
 		}
 	}
 
 	rcu_read_unlock();
-	return ctx;
+	return ret;
 }
 
 /*
@@ -1009,7 +1026,7 @@
 	 * eventfd. The eventfd_signal() function is safe to be called
 	 * from IRQ context.
 	 */
-	if (!IS_ERR(iocb->ki_eventfd))
+	if (iocb->ki_eventfd != NULL)
 		eventfd_signal(iocb->ki_eventfd, 1);
 
 put_rq:
@@ -1608,6 +1625,7 @@
 		req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd);
 		if (IS_ERR(req->ki_eventfd)) {
 			ret = PTR_ERR(req->ki_eventfd);
+			req->ki_eventfd = NULL;
 			goto out_put_req;
 		}
 	}
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c
index 549b014..fe2b1aa 100644
--- a/fs/bio-integrity.c
+++ b/fs/bio-integrity.c
@@ -685,19 +685,20 @@
  * bio_integrity_clone - Callback for cloning bios with integrity metadata
  * @bio:	New bio
  * @bio_src:	Original bio
+ * @gfp_mask:	Memory allocation mask
  * @bs:		bio_set to allocate bip from
  *
  * Description:	Called to allocate a bip when cloning a bio
  */
 int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
-			struct bio_set *bs)
+			gfp_t gfp_mask, struct bio_set *bs)
 {
 	struct bio_integrity_payload *bip_src = bio_src->bi_integrity;
 	struct bio_integrity_payload *bip;
 
 	BUG_ON(bip_src == NULL);
 
-	bip = bio_integrity_alloc_bioset(bio, GFP_NOIO, bip_src->bip_vcnt, bs);
+	bip = bio_integrity_alloc_bioset(bio, gfp_mask, bip_src->bip_vcnt, bs);
 
 	if (bip == NULL)
 		return -EIO;
diff --git a/fs/bio.c b/fs/bio.c
index 124b95c..d4f0632 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -463,10 +463,12 @@
 	if (bio_integrity(bio)) {
 		int ret;
 
-		ret = bio_integrity_clone(b, bio, fs_bio_set);
+		ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set);
 
-		if (ret < 0)
+		if (ret < 0) {
+			bio_put(b);
 			return NULL;
+		}
 	}
 
 	return b;
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 42491d7..37f31b5 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -277,7 +277,7 @@
 	if (*cow_ret == buf)
 		unlock_orig = 1;
 
-	WARN_ON(!btrfs_tree_locked(buf));
+	btrfs_assert_tree_locked(buf);
 
 	if (parent)
 		parent_start = parent->start;
@@ -2365,7 +2365,7 @@
 	if (slot >= btrfs_header_nritems(upper) - 1)
 		return 1;
 
-	WARN_ON(!btrfs_tree_locked(path->nodes[1]));
+	btrfs_assert_tree_locked(path->nodes[1]);
 
 	right = read_node_slot(root, upper, slot + 1);
 	btrfs_tree_lock(right);
@@ -2562,7 +2562,7 @@
 	if (right_nritems == 0)
 		return 1;
 
-	WARN_ON(!btrfs_tree_locked(path->nodes[1]));
+	btrfs_assert_tree_locked(path->nodes[1]);
 
 	left = read_node_slot(root, path->nodes[1], slot - 1);
 	btrfs_tree_lock(left);
@@ -4101,7 +4101,7 @@
 
 		next = read_node_slot(root, c, slot);
 		if (!path->skip_locking) {
-			WARN_ON(!btrfs_tree_locked(c));
+			btrfs_assert_tree_locked(c);
 			btrfs_tree_lock(next);
 			btrfs_set_lock_blocking(next);
 		}
@@ -4126,7 +4126,7 @@
 			reada_for_search(root, path, level, slot, 0);
 		next = read_node_slot(root, next, 0);
 		if (!path->skip_locking) {
-			WARN_ON(!btrfs_tree_locked(path->nodes[level]));
+			btrfs_assert_tree_locked(path->nodes[level]);
 			btrfs_tree_lock(next);
 			btrfs_set_lock_blocking(next);
 		}
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 82491ba..5e1d4e3 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -784,7 +784,14 @@
 	struct list_head dirty_cowonly_roots;
 
 	struct btrfs_fs_devices *fs_devices;
+
+	/*
+	 * the space_info list is almost entirely read only.  It only changes
+	 * when we add a new raid type to the FS, and that happens
+	 * very rarely.  RCU is used to protect it.
+	 */
 	struct list_head space_info;
+
 	spinlock_t delalloc_lock;
 	spinlock_t new_trans_lock;
 	u64 delalloc_bytes;
@@ -1797,6 +1804,8 @@
 int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len);
 u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags);
 void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde);
+void btrfs_clear_space_info_full(struct btrfs_fs_info *info);
+
 int btrfs_check_metadata_free_space(struct btrfs_root *root);
 int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,
 				u64 bytes);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index adda739..3e18175 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -857,7 +857,7 @@
 	struct inode *btree_inode = root->fs_info->btree_inode;
 	if (btrfs_header_generation(buf) ==
 	    root->fs_info->running_transaction->transid) {
-		WARN_ON(!btrfs_tree_locked(buf));
+		btrfs_assert_tree_locked(buf);
 
 		/* ugh, clear_extent_buffer_dirty can be expensive */
 		btrfs_set_lock_blocking(buf);
@@ -2361,7 +2361,7 @@
 
 	btrfs_set_lock_blocking(buf);
 
-	WARN_ON(!btrfs_tree_locked(buf));
+	btrfs_assert_tree_locked(buf);
 	if (transid != root->fs_info->generation) {
 		printk(KERN_CRIT "btrfs transid mismatch buffer %llu, "
 		       "found %llu running %llu\n",
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 6b5966a..fefe83a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -20,6 +20,7 @@
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
 #include <linux/sort.h>
+#include <linux/rcupdate.h>
 #include "compat.h"
 #include "hash.h"
 #include "crc32c.h"
@@ -330,13 +331,33 @@
 {
 	struct list_head *head = &info->space_info;
 	struct btrfs_space_info *found;
-	list_for_each_entry(found, head, list) {
-		if (found->flags == flags)
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(found, head, list) {
+		if (found->flags == flags) {
+			rcu_read_unlock();
 			return found;
+		}
 	}
+	rcu_read_unlock();
 	return NULL;
 }
 
+/*
+ * after adding space to the filesystem, we need to clear the full flags
+ * on all the space infos.
+ */
+void btrfs_clear_space_info_full(struct btrfs_fs_info *info)
+{
+	struct list_head *head = &info->space_info;
+	struct btrfs_space_info *found;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(found, head, list)
+		found->full = 0;
+	rcu_read_unlock();
+}
+
 static u64 div_factor(u64 num, int factor)
 {
 	if (factor == 10)
@@ -1903,7 +1924,6 @@
 	if (!found)
 		return -ENOMEM;
 
-	list_add(&found->list, &info->space_info);
 	INIT_LIST_HEAD(&found->block_groups);
 	init_rwsem(&found->groups_sem);
 	spin_lock_init(&found->lock);
@@ -1917,6 +1937,7 @@
 	found->full = 0;
 	found->force_alloc = 0;
 	*space_info = found;
+	list_add_rcu(&found->list, &info->space_info);
 	return 0;
 }
 
@@ -4418,13 +4439,13 @@
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
 
-	BUG_ON(!btrfs_tree_locked(parent));
+	btrfs_assert_tree_locked(parent);
 	parent_level = btrfs_header_level(parent);
 	extent_buffer_get(parent);
 	path->nodes[parent_level] = parent;
 	path->slots[parent_level] = btrfs_header_nritems(parent);
 
-	BUG_ON(!btrfs_tree_locked(node));
+	btrfs_assert_tree_locked(node);
 	level = btrfs_header_level(node);
 	extent_buffer_get(node);
 	path->nodes[level] = node;
@@ -6320,6 +6341,7 @@
 int btrfs_free_block_groups(struct btrfs_fs_info *info)
 {
 	struct btrfs_block_group_cache *block_group;
+	struct btrfs_space_info *space_info;
 	struct rb_node *n;
 
 	spin_lock(&info->block_group_cache_lock);
@@ -6341,6 +6363,23 @@
 		spin_lock(&info->block_group_cache_lock);
 	}
 	spin_unlock(&info->block_group_cache_lock);
+
+	/* now that all the block groups are freed, go through and
+	 * free all the space_info structs.  This is only called during
+	 * the final stages of unmount, and so we know nobody is
+	 * using them.  We call synchronize_rcu() once before we start,
+	 * just to be on the safe side.
+	 */
+	synchronize_rcu();
+
+	while(!list_empty(&info->space_info)) {
+		space_info = list_entry(info->space_info.next,
+					struct btrfs_space_info,
+					list);
+
+		list_del(&space_info->list);
+		kfree(space_info);
+	}
 	return 0;
 }
 
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index 85506c4..47b0a88 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -220,8 +220,8 @@
 	return 0;
 }
 
-int btrfs_tree_locked(struct extent_buffer *eb)
+void btrfs_assert_tree_locked(struct extent_buffer *eb)
 {
-	return test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags) ||
-			spin_is_locked(&eb->lock);
+	if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
+		assert_spin_locked(&eb->lock);
 }
diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h
index 6bb0afb..6c4ce45 100644
--- a/fs/btrfs/locking.h
+++ b/fs/btrfs/locking.h
@@ -21,11 +21,11 @@
 
 int btrfs_tree_lock(struct extent_buffer *eb);
 int btrfs_tree_unlock(struct extent_buffer *eb);
-int btrfs_tree_locked(struct extent_buffer *eb);
 
 int btrfs_try_tree_lock(struct extent_buffer *eb);
 int btrfs_try_spin_lock(struct extent_buffer *eb);
 
 void btrfs_set_lock_blocking(struct extent_buffer *eb);
 void btrfs_clear_lock_blocking(struct extent_buffer *eb);
+void btrfs_assert_tree_locked(struct extent_buffer *eb);
 #endif
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 1316139..dd06e18 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1374,6 +1374,12 @@
 		ret = btrfs_add_device(trans, root, device);
 	}
 
+	/*
+	 * we've got more storage, clear any full flags on the space
+	 * infos
+	 */
+	btrfs_clear_space_info_full(root->fs_info);
+
 	unlock_chunks(root);
 	btrfs_commit_transaction(trans, root);
 
@@ -1459,6 +1465,8 @@
 	device->fs_devices->total_rw_bytes += diff;
 
 	device->total_bytes = new_size;
+	btrfs_clear_space_info_full(device->dev_root->fs_info);
+
 	return btrfs_update_device(trans, device);
 }
 
diff --git a/fs/buffer.c b/fs/buffer.c
index 9f69741..891e1c7 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -760,15 +760,9 @@
  * If warn is true, then emit a warning if the page is not uptodate and has
  * not been truncated.
  */
-static int __set_page_dirty(struct page *page,
+static void __set_page_dirty(struct page *page,
 		struct address_space *mapping, int warn)
 {
-	if (unlikely(!mapping))
-		return !TestSetPageDirty(page);
-
-	if (TestSetPageDirty(page))
-		return 0;
-
 	spin_lock_irq(&mapping->tree_lock);
 	if (page->mapping) {	/* Race with truncate? */
 		WARN_ON_ONCE(warn && !PageUptodate(page));
@@ -785,8 +779,6 @@
 	}
 	spin_unlock_irq(&mapping->tree_lock);
 	__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
-
-	return 1;
 }
 
 /*
@@ -816,6 +808,7 @@
  */
 int __set_page_dirty_buffers(struct page *page)
 {
+	int newly_dirty;
 	struct address_space *mapping = page_mapping(page);
 
 	if (unlikely(!mapping))
@@ -831,9 +824,12 @@
 			bh = bh->b_this_page;
 		} while (bh != head);
 	}
+	newly_dirty = !TestSetPageDirty(page);
 	spin_unlock(&mapping->private_lock);
 
-	return __set_page_dirty(page, mapping, 1);
+	if (newly_dirty)
+		__set_page_dirty(page, mapping, 1);
+	return newly_dirty;
 }
 EXPORT_SYMBOL(__set_page_dirty_buffers);
 
@@ -1262,8 +1258,11 @@
 			return;
 	}
 
-	if (!test_set_buffer_dirty(bh))
-		__set_page_dirty(bh->b_page, page_mapping(bh->b_page), 0);
+	if (!test_set_buffer_dirty(bh)) {
+		struct page *page = bh->b_page;
+		if (!TestSetPageDirty(page))
+			__set_page_dirty(page, page_mapping(page), 0);
+	}
 }
 
 /*
diff --git a/fs/compat.c b/fs/compat.c
index d0145ca..0949b43 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1402,6 +1402,7 @@
 	retval = mutex_lock_interruptible(&current->cred_exec_mutex);
 	if (retval < 0)
 		goto out_free;
+	current->in_execve = 1;
 
 	retval = -ENOMEM;
 	bprm->cred = prepare_exec_creds();
@@ -1454,6 +1455,7 @@
 		goto out;
 
 	/* execve succeeded */
+	current->in_execve = 0;
 	mutex_unlock(&current->cred_exec_mutex);
 	acct_update_integrals(current);
 	free_bprm(bprm);
@@ -1470,6 +1472,7 @@
 	}
 
 out_unlock:
+	current->in_execve = 0;
 	mutex_unlock(&current->cred_exec_mutex);
 
 out_free:
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 5f3231b..bff4052 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -198,9 +198,6 @@
 
 	fsi->ptmx_dentry = dentry;
 	rc = 0;
-
-	printk(KERN_DEBUG "Created ptmx node in devpts ino %lu\n",
-			inode->i_ino);
 out:
 	mutex_unlock(&root->d_inode->i_mutex);
 	return rc;
@@ -369,8 +366,6 @@
 	struct pts_fs_info *fsi;
 	struct pts_mount_opts *opts;
 
-	printk(KERN_NOTICE "devpts: newinstance mount\n");
-
 	err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt);
 	if (err)
 		return err;
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index f6caeb1..8b65f28 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -946,6 +946,8 @@
 	list_for_each_entry(global_auth_tok,
 			    &mount_crypt_stat->global_auth_tok_list,
 			    mount_crypt_stat_list) {
+		if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_FNEK)
+			continue;
 		rc = ecryptfs_add_keysig(crypt_stat, global_auth_tok->sig);
 		if (rc) {
 			printk(KERN_ERR "Error adding keysig; rc = [%d]\n", rc);
@@ -1322,14 +1324,13 @@
 }
 
 static int
-ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
-				    struct dentry *ecryptfs_dentry,
-				    char *virt)
+ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry,
+				    char *virt, size_t virt_len)
 {
 	int rc;
 
 	rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt,
-				  0, crypt_stat->num_header_bytes_at_front);
+				  0, virt_len);
 	if (rc)
 		printk(KERN_ERR "%s: Error attempting to write header "
 		       "information to lower file; rc = [%d]\n", __func__,
@@ -1339,7 +1340,6 @@
 
 static int
 ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
-				 struct ecryptfs_crypt_stat *crypt_stat,
 				 char *page_virt, size_t size)
 {
 	int rc;
@@ -1349,6 +1349,17 @@
 	return rc;
 }
 
+static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask,
+					       unsigned int order)
+{
+	struct page *page;
+
+	page = alloc_pages(gfp_mask | __GFP_ZERO, order);
+	if (page)
+		return (unsigned long) page_address(page);
+	return 0;
+}
+
 /**
  * ecryptfs_write_metadata
  * @ecryptfs_dentry: The eCryptfs dentry
@@ -1365,7 +1376,9 @@
 {
 	struct ecryptfs_crypt_stat *crypt_stat =
 		&ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+	unsigned int order;
 	char *virt;
+	size_t virt_len;
 	size_t size = 0;
 	int rc = 0;
 
@@ -1381,33 +1394,35 @@
 		rc = -EINVAL;
 		goto out;
 	}
+	virt_len = crypt_stat->num_header_bytes_at_front;
+	order = get_order(virt_len);
 	/* Released in this function */
-	virt = (char *)get_zeroed_page(GFP_KERNEL);
+	virt = (char *)ecryptfs_get_zeroed_pages(GFP_KERNEL, order);
 	if (!virt) {
 		printk(KERN_ERR "%s: Out of memory\n", __func__);
 		rc = -ENOMEM;
 		goto out;
 	}
-	rc = ecryptfs_write_headers_virt(virt, PAGE_CACHE_SIZE, &size,
-					 crypt_stat, ecryptfs_dentry);
+	rc = ecryptfs_write_headers_virt(virt, virt_len, &size, crypt_stat,
+					 ecryptfs_dentry);
 	if (unlikely(rc)) {
 		printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n",
 		       __func__, rc);
 		goto out_free;
 	}
 	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
-		rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry,
-						      crypt_stat, virt, size);
+		rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt,
+						      size);
 	else
-		rc = ecryptfs_write_metadata_to_contents(crypt_stat,
-							 ecryptfs_dentry, virt);
+		rc = ecryptfs_write_metadata_to_contents(ecryptfs_dentry, virt,
+							 virt_len);
 	if (rc) {
 		printk(KERN_ERR "%s: Error writing metadata out to lower file; "
 		       "rc = [%d]\n", __func__, rc);
 		goto out_free;
 	}
 out_free:
-	free_page((unsigned long)virt);
+	free_pages((unsigned long)virt, order);
 out:
 	return rc;
 }
@@ -2206,17 +2221,19 @@
 					 struct dentry *ecryptfs_dir_dentry,
 					 const char *name, size_t name_size)
 {
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+		&ecryptfs_superblock_to_private(
+			ecryptfs_dir_dentry->d_sb)->mount_crypt_stat;
 	char *decoded_name;
 	size_t decoded_name_size;
 	size_t packet_size;
 	int rc = 0;
 
-	if ((name_size > ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE)
+	if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
+	    && !(mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
+	    && (name_size > ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE)
 	    && (strncmp(name, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX,
 			ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) == 0)) {
-		struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
-			&ecryptfs_superblock_to_private(
-				ecryptfs_dir_dentry->d_sb)->mount_crypt_stat;
 		const char *orig_name = name;
 		size_t orig_name_size = name_size;
 
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index c11fc95..ac749d4 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -328,6 +328,7 @@
  */
 struct ecryptfs_global_auth_tok {
 #define ECRYPTFS_AUTH_TOK_INVALID 0x00000001
+#define ECRYPTFS_AUTH_TOK_FNEK    0x00000002
 	u32 flags;
 	struct list_head mount_crypt_stat_list;
 	struct key *global_auth_tok_key;
@@ -619,7 +620,6 @@
 		       u32 flags);
 int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
 					struct dentry *lower_dentry,
-					struct ecryptfs_crypt_stat *crypt_stat,
 					struct inode *ecryptfs_dir_inode,
 					struct nameidata *ecryptfs_nd);
 int ecryptfs_decode_and_decrypt_filename(char **decrypted_name,
@@ -696,7 +696,7 @@
 int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig);
 int
 ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
-			   char *sig);
+			   char *sig, u32 global_auth_tok_flags);
 int ecryptfs_get_global_auth_tok_for_sig(
 	struct ecryptfs_global_auth_tok **global_auth_tok,
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig);
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 5697899..55b3145 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -246,7 +246,6 @@
  */
 int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
 					struct dentry *lower_dentry,
-					struct ecryptfs_crypt_stat *crypt_stat,
 					struct inode *ecryptfs_dir_inode,
 					struct nameidata *ecryptfs_nd)
 {
@@ -254,6 +253,7 @@
 	struct vfsmount *lower_mnt;
 	struct inode *lower_inode;
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
+	struct ecryptfs_crypt_stat *crypt_stat;
 	char *page_virt = NULL;
 	u64 file_size;
 	int rc = 0;
@@ -314,6 +314,11 @@
 			goto out_free_kmem;
 		}
 	}
+	crypt_stat = &ecryptfs_inode_to_private(
+					ecryptfs_dentry->d_inode)->crypt_stat;
+	/* TODO: lock for crypt_stat comparison */
+	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
+			ecryptfs_set_default_sizes(crypt_stat);
 	rc = ecryptfs_read_and_validate_header_region(page_virt,
 						      ecryptfs_dentry->d_inode);
 	if (rc) {
@@ -362,9 +367,7 @@
 {
 	char *encrypted_and_encoded_name = NULL;
 	size_t encrypted_and_encoded_name_size;
-	struct ecryptfs_crypt_stat *crypt_stat = NULL;
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL;
-	struct ecryptfs_inode_info *inode_info;
 	struct dentry *lower_dir_dentry, *lower_dentry;
 	int rc = 0;
 
@@ -388,26 +391,15 @@
 	}
 	if (lower_dentry->d_inode)
 		goto lookup_and_interpose;
-	inode_info =  ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
-	if (inode_info) {
-		crypt_stat = &inode_info->crypt_stat;
-		/* TODO: lock for crypt_stat comparison */
-		if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
-			ecryptfs_set_default_sizes(crypt_stat);
-	}
-	if (crypt_stat)
-		mount_crypt_stat = crypt_stat->mount_crypt_stat;
-	else
-		mount_crypt_stat = &ecryptfs_superblock_to_private(
-			ecryptfs_dentry->d_sb)->mount_crypt_stat;
-	if (!(crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCRYPT_FILENAMES))
-	    && !(mount_crypt_stat && (mount_crypt_stat->flags
-				     & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)))
+	mount_crypt_stat = &ecryptfs_superblock_to_private(
+				ecryptfs_dentry->d_sb)->mount_crypt_stat;
+	if (!(mount_crypt_stat
+	    && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)))
 		goto lookup_and_interpose;
 	dput(lower_dentry);
 	rc = ecryptfs_encrypt_and_encode_filename(
 		&encrypted_and_encoded_name, &encrypted_and_encoded_name_size,
-		crypt_stat, mount_crypt_stat, ecryptfs_dentry->d_name.name,
+		NULL, mount_crypt_stat, ecryptfs_dentry->d_name.name,
 		ecryptfs_dentry->d_name.len);
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to encrypt and encode "
@@ -426,7 +418,7 @@
 	}
 lookup_and_interpose:
 	rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry,
-						 crypt_stat, ecryptfs_dir_inode,
+						 ecryptfs_dir_inode,
 						 ecryptfs_nd);
 	goto out;
 out_d_drop:
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index ff53942..e4a6223 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -2375,7 +2375,7 @@
 
 int
 ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
-			     char *sig)
+			     char *sig, u32 global_auth_tok_flags)
 {
 	struct ecryptfs_global_auth_tok *new_auth_tok;
 	int rc = 0;
@@ -2389,6 +2389,7 @@
 		goto out;
 	}
 	memcpy(new_auth_tok->sig, sig, ECRYPTFS_SIG_SIZE_HEX);
+	new_auth_tok->flags = global_auth_tok_flags;
 	new_auth_tok->sig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
 	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
 	list_add(&new_auth_tok->mount_crypt_stat_list,
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 789cf2e..aed56c2 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -319,7 +319,7 @@
 		case ecryptfs_opt_ecryptfs_sig:
 			sig_src = args[0].from;
 			rc = ecryptfs_add_global_auth_tok(mount_crypt_stat,
-							  sig_src);
+							  sig_src, 0);
 			if (rc) {
 				printk(KERN_ERR "Error attempting to register "
 				       "global sig; rc = [%d]\n", rc);
@@ -370,7 +370,8 @@
 				ECRYPTFS_SIG_SIZE_HEX] = '\0';
 			rc = ecryptfs_add_global_auth_tok(
 				mount_crypt_stat,
-				mount_crypt_stat->global_default_fnek_sig);
+				mount_crypt_stat->global_default_fnek_sig,
+				ECRYPTFS_AUTH_TOK_FNEK);
 			if (rc) {
 				printk(KERN_ERR "Error attempting to register "
 				       "global fnek sig [%s]; rc = [%d]\n",
diff --git a/fs/exec.c b/fs/exec.c
index 929b580..b9f1c14 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -45,6 +45,7 @@
 #include <linux/proc_fs.h>
 #include <linux/mount.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/syscalls.h>
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
@@ -127,6 +128,9 @@
 				 MAY_READ | MAY_EXEC | MAY_OPEN);
 	if (error)
 		goto exit;
+	error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN);
+	if (error)
+		goto exit;
 
 	file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
 	error = PTR_ERR(file);
@@ -674,6 +678,9 @@
 	err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN);
 	if (err)
 		goto out_path_put;
+	err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN);
+	if (err)
+		goto out_path_put;
 
 	file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
 	if (IS_ERR(file))
@@ -1184,6 +1191,9 @@
 	retval = security_bprm_check(bprm);
 	if (retval)
 		return retval;
+	retval = ima_bprm_check(bprm);
+	if (retval)
+		return retval;
 
 	/* kernel module loader fixup */
 	/* so we don't try to load run modprobe in kernel space. */
@@ -1284,6 +1294,7 @@
 	retval = mutex_lock_interruptible(&current->cred_exec_mutex);
 	if (retval < 0)
 		goto out_free;
+	current->in_execve = 1;
 
 	retval = -ENOMEM;
 	bprm->cred = prepare_exec_creds();
@@ -1337,6 +1348,7 @@
 		goto out;
 
 	/* execve succeeded */
+	current->in_execve = 0;
 	mutex_unlock(&current->cred_exec_mutex);
 	acct_update_integrals(current);
 	free_bprm(bprm);
@@ -1355,6 +1367,7 @@
 	}
 
 out_unlock:
+	current->in_execve = 0;
 	mutex_unlock(&current->cred_exec_mutex);
 
 out_free:
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index e2eab19..e0aa4fe 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1122,7 +1122,8 @@
 	struct ext4_extent_idx *ix;
 	struct ext4_extent *ex;
 	ext4_fsblk_t block;
-	int depth, ee_len;
+	int depth;	/* Note, NOT eh_depth; depth from top of tree */
+	int ee_len;
 
 	BUG_ON(path == NULL);
 	depth = path->p_depth;
@@ -1179,7 +1180,8 @@
 		if (bh == NULL)
 			return -EIO;
 		eh = ext_block_hdr(bh);
-		if (ext4_ext_check_header(inode, eh, depth)) {
+		/* subtract from p_depth to get proper eh_depth */
+		if (ext4_ext_check_header(inode, eh, path->p_depth - depth)) {
 			put_bh(bh);
 			return -EIO;
 		}
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index f18a919..2d2b358 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -188,7 +188,7 @@
 	struct ext4_group_desc *gdp;
 	struct ext4_super_block *es;
 	struct ext4_sb_info *sbi;
-	int fatal = 0, err, count;
+	int fatal = 0, err, count, cleared;
 	ext4_group_t flex_group;
 
 	if (atomic_read(&inode->i_count) > 1) {
@@ -248,8 +248,10 @@
 		goto error_return;
 
 	/* Ok, now we can actually update the inode bitmaps.. */
-	if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
-					bit, bitmap_bh->b_data))
+	spin_lock(sb_bgl_lock(sbi, block_group));
+	cleared = ext4_clear_bit(bit, bitmap_bh->b_data);
+	spin_unlock(sb_bgl_lock(sbi, block_group));
+	if (!cleared)
 		ext4_error(sb, "ext4_free_inode",
 			   "bit already cleared for inode %lu", ino);
 	else {
@@ -696,6 +698,7 @@
 	struct inode *ret;
 	ext4_group_t i;
 	int free = 0;
+	static int once = 1;
 	ext4_group_t flex_group;
 
 	/* Cannot create files in a deleted directory */
@@ -717,7 +720,8 @@
 		ret2 = find_group_flex(sb, dir, &group);
 		if (ret2 == -1) {
 			ret2 = find_group_other(sb, dir, &group);
-			if (ret2 == 0 && printk_ratelimit())
+			if (ret2 == 0 && once)
+				once = 0;
 				printk(KERN_NOTICE "ext4: find_group_flex "
 				       "failed, fallback succeeded dir %lu\n",
 				       dir->i_ino);
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 4415bee..9f61e62 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -1447,7 +1447,7 @@
 	struct ext4_free_extent *gex = &ac->ac_g_ex;
 
 	BUG_ON(ex->fe_len <= 0);
-	BUG_ON(ex->fe_len >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
+	BUG_ON(ex->fe_len > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
 	BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
 	BUG_ON(ac->ac_status != AC_STATUS_CONTINUE);
 
@@ -3292,7 +3292,7 @@
 	}
 	BUG_ON(start + size <= ac->ac_o_ex.fe_logical &&
 			start > ac->ac_o_ex.fe_logical);
-	BUG_ON(size <= 0 || size >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
+	BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
 
 	/* now prepare goal request */
 
@@ -3589,6 +3589,7 @@
 			struct super_block *sb, struct ext4_prealloc_space *pa)
 {
 	ext4_group_t grp;
+	ext4_fsblk_t grp_blk;
 
 	if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0)
 		return;
@@ -3603,8 +3604,12 @@
 	pa->pa_deleted = 1;
 	spin_unlock(&pa->pa_lock);
 
-	/* -1 is to protect from crossing allocation group */
-	ext4_get_group_no_and_offset(sb, pa->pa_pstart - 1, &grp, NULL);
+	grp_blk = pa->pa_pstart;
+	/* If linear, pa_pstart may be in the next group when pa is used up */
+	if (pa->pa_linear)
+		grp_blk--;
+
+	ext4_get_group_no_and_offset(sb, grp_blk, &grp, NULL);
 
 	/*
 	 * possible race:
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 6b74d09..de0004f 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -202,9 +202,9 @@
 	sector_t blocknr;
 
 	/* fat_get_cluster() assumes the requested blocknr isn't truncated. */
-	mutex_lock(&mapping->host->i_mutex);
+	down_read(&mapping->host->i_alloc_sem);
 	blocknr = generic_block_bmap(mapping, block, fat_get_block);
-	mutex_unlock(&mapping->host->i_mutex);
+	up_read(&mapping->host->i_alloc_sem);
 
 	return blocknr;
 }
diff --git a/fs/file_table.c b/fs/file_table.c
index bbeeac6..da806ac 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/eventpoll.h>
 #include <linux/rcupdate.h>
 #include <linux/mount.h>
@@ -279,6 +280,7 @@
 	if (file->f_op && file->f_op->release)
 		file->f_op->release(inode, file);
 	security_file_free(file);
+	ima_file_free(file);
 	if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
 		cdev_put(inode->i_cdev);
 	fops_put(file->f_op);
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index e5eaa62..e3fe991 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -274,6 +274,7 @@
 	int ret;
 
 	BUG_ON(inode->i_state & I_SYNC);
+	WARN_ON(inode->i_state & I_NEW);
 
 	/* Set I_SYNC, reset I_DIRTY */
 	dirty = inode->i_state & I_DIRTY;
@@ -298,6 +299,7 @@
 	}
 
 	spin_lock(&inode_lock);
+	WARN_ON(inode->i_state & I_NEW);
 	inode->i_state &= ~I_SYNC;
 	if (!(inode->i_state & I_FREEING)) {
 		if (!(inode->i_state & I_DIRTY) &&
@@ -470,6 +472,11 @@
 			break;
 		}
 
+		if (inode->i_state & I_NEW) {
+			requeue_io(inode);
+			continue;
+		}
+
 		if (wbc->nonblocking && bdi_write_congested(bdi)) {
 			wbc->encountered_congestion = 1;
 			if (!sb_is_blkdev_sb(sb))
@@ -531,7 +538,7 @@
 		list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
 			struct address_space *mapping;
 
-			if (inode->i_state & (I_FREEING|I_WILL_FREE))
+			if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW))
 				continue;
 			mapping = inode->i_mapping;
 			if (mapping->nrpages == 0)
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index e563a64..3a981b7 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -1,6 +1,10 @@
 config GFS2_FS
 	tristate "GFS2 file system support"
 	depends on EXPERIMENTAL && (64BIT || LBD)
+	select DLM if GFS2_FS_LOCKING_DLM
+	select CONFIGFS_FS if GFS2_FS_LOCKING_DLM
+	select SYSFS if GFS2_FS_LOCKING_DLM
+	select IP_SCTP if DLM_SCTP
 	select FS_POSIX_ACL
 	select CRC32
 	help
@@ -18,17 +22,16 @@
 	  the locking module below. Documentation and utilities for GFS2 can
 	  be found here: http://sources.redhat.com/cluster
 
-	  The "nolock" lock module is now built in to GFS2 by default.
+	  The "nolock" lock module is now built in to GFS2 by default. If
+	  you want to use the DLM, be sure to enable HOTPLUG and IPv4/6
+	  networking.
 
 config GFS2_FS_LOCKING_DLM
-	tristate "GFS2 DLM locking module"
-	depends on GFS2_FS && SYSFS && NET && INET && (IPV6 || IPV6=n)
-	select IP_SCTP if DLM_SCTP
-	select CONFIGFS_FS
-	select DLM
+	bool "GFS2 DLM locking"
+	depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && HOTPLUG
 	help
 	  Multiple node locking module for GFS2
 
-	  Most users of GFS2 will require this module. It provides the locking
+	  Most users of GFS2 will require this. It provides the locking
 	  interface between GFS2 and the DLM, which is required to use GFS2
 	  in a cluster environment.
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
index c1b4ec6a..a851ea4 100644
--- a/fs/gfs2/Makefile
+++ b/fs/gfs2/Makefile
@@ -1,9 +1,9 @@
 obj-$(CONFIG_GFS2_FS) += gfs2.o
 gfs2-y := acl.o bmap.o dir.o eaops.o eattr.o glock.o \
-	glops.o inode.o log.o lops.o locking.o main.o meta_io.o \
+	glops.o inode.o log.o lops.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
 
-obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += locking/dlm/
+gfs2-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o
 
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index e335dce..43764f4 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -15,7 +15,6 @@
 #include <linux/posix_acl.h>
 #include <linux/posix_acl_xattr.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 
 #include "gfs2.h"
 #include "incore.h"
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 11ffc56..3a5d3f8 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -13,7 +13,6 @@
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
 
 #include "gfs2.h"
 #include "incore.h"
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index b7c8e5c..aef4d0c 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -60,7 +60,6 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/vmalloc.h>
-#include <linux/lm_interface.h>
 
 #include "gfs2.h"
 #include "incore.h"
diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c
index f114ba2..dee9b03 100644
--- a/fs/gfs2/eaops.c
+++ b/fs/gfs2/eaops.c
@@ -14,7 +14,6 @@
 #include <linux/capability.h>
 #include <linux/xattr.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index 0d1c76d..899763a 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -13,7 +13,6 @@
 #include <linux/buffer_head.h>
 #include <linux/xattr.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 6b983ae..3984e47 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/completion.h>
 #include <linux/buffer_head.h>
 #include <linux/delay.h>
 #include <linux/sort.h>
@@ -18,7 +17,6 @@
 #include <linux/kallsyms.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/list.h>
-#include <linux/lm_interface.h>
 #include <linux/wait.h>
 #include <linux/module.h>
 #include <linux/rwsem.h>
@@ -155,13 +153,10 @@
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	struct inode *aspace = gl->gl_aspace;
 
-	if (sdp->sd_lockstruct.ls_ops->lm_put_lock)
-		sdp->sd_lockstruct.ls_ops->lm_put_lock(gl->gl_lock);
-
 	if (aspace)
 		gfs2_aspace_put(aspace);
 
-	kmem_cache_free(gfs2_glock_cachep, gl);
+	sdp->sd_lockstruct.ls_ops->lm_put_lock(gfs2_glock_cachep, gl);
 }
 
 /**
@@ -172,6 +167,7 @@
 
 static void gfs2_glock_hold(struct gfs2_glock *gl)
 {
+	GLOCK_BUG_ON(gl, atomic_read(&gl->gl_ref) == 0);
 	atomic_inc(&gl->gl_ref);
 }
 
@@ -211,17 +207,15 @@
 			atomic_dec(&lru_count);
 		}
 		spin_unlock(&lru_lock);
-		GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_UNLOCKED);
-		GLOCK_BUG_ON(gl, !list_empty(&gl->gl_lru));
 		GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
 		glock_free(gl);
 		rv = 1;
 		goto out;
 	}
-	write_unlock(gl_lock_addr(gl->gl_hash));
 	/* 1 for being hashed, 1 for having state != LM_ST_UNLOCKED */
 	if (atomic_read(&gl->gl_ref) == 2)
 		gfs2_glock_schedule_for_reclaim(gl);
+	write_unlock(gl_lock_addr(gl->gl_hash));
 out:
 	return rv;
 }
@@ -256,27 +250,6 @@
 }
 
 /**
- * gfs2_glock_find() - Find glock by lock number
- * @sdp: The GFS2 superblock
- * @name: The lock name
- *
- * Returns: NULL, or the struct gfs2_glock with the requested number
- */
-
-static struct gfs2_glock *gfs2_glock_find(const struct gfs2_sbd *sdp,
-					  const struct lm_lockname *name)
-{
-	unsigned int hash = gl_hash(sdp, name);
-	struct gfs2_glock *gl;
-
-	read_lock(gl_lock_addr(hash));
-	gl = search_bucket(hash, sdp, name);
-	read_unlock(gl_lock_addr(hash));
-
-	return gl;
-}
-
-/**
  * may_grant - check if its ok to grant a new lock
  * @gl: The glock
  * @gh: The lock request which we wish to grant
@@ -523,7 +496,7 @@
 }
 
 static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
-				 unsigned int cur_state, unsigned int req_state,
+				 unsigned int req_state,
 				 unsigned int flags)
 {
 	int ret = LM_OUT_ERROR;
@@ -532,7 +505,7 @@
 		return req_state == LM_ST_UNLOCKED ? 0 : req_state;
 
 	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
-		ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state,
+		ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock,
 							 req_state, flags);
 	return ret;
 }
@@ -575,7 +548,7 @@
 	    gl->gl_state == LM_ST_DEFERRED) &&
 	    !(lck_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
 		lck_flags |= LM_FLAG_TRY_1CB;
-	ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, target, lck_flags);
+	ret = gfs2_lm_lock(sdp, gl, target, lck_flags);
 
 	if (!(ret & LM_OUT_ASYNC)) {
 		finish_xmote(gl, ret);
@@ -624,10 +597,11 @@
 
 	GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags));
 
+	down_read(&gfs2_umount_flush_sem);
 	if (test_bit(GLF_DEMOTE, &gl->gl_flags) &&
 	    gl->gl_demote_state != gl->gl_state) {
 		if (find_first_holder(gl))
-			goto out;
+			goto out_unlock;
 		if (nonblock)
 			goto out_sched;
 		set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
@@ -638,23 +612,26 @@
 			gfs2_demote_wake(gl);
 		ret = do_promote(gl);
 		if (ret == 0)
-			goto out;
+			goto out_unlock;
 		if (ret == 2)
-			return;
+			goto out_sem;
 		gh = find_first_waiter(gl);
 		gl->gl_target = gh->gh_state;
 		if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
 			do_error(gl, 0); /* Fail queued try locks */
 	}
 	do_xmote(gl, gh, gl->gl_target);
+out_sem:
+	up_read(&gfs2_umount_flush_sem);
 	return;
 
 out_sched:
 	gfs2_glock_hold(gl);
 	if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
 		gfs2_glock_put(gl);
-out:
+out_unlock:
 	clear_bit(GLF_LOCK, &gl->gl_flags);
+	goto out_sem;
 }
 
 static void glock_work_func(struct work_struct *work)
@@ -681,18 +658,6 @@
 		gfs2_glock_put(gl);
 }
 
-static int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
-		     void **lockp)
-{
-	int error = -EIO;
-	if (!sdp->sd_lockstruct.ls_ops->lm_get_lock)
-		return 0;
-	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
@@ -719,10 +684,11 @@
 	gl = search_bucket(hash, sdp, &name);
 	read_unlock(gl_lock_addr(hash));
 
-	if (gl || !create) {
-		*glp = gl;
+	*glp = gl;
+	if (gl)
 		return 0;
-	}
+	if (!create)
+		return -ENOENT;
 
 	gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL);
 	if (!gl)
@@ -736,7 +702,9 @@
 	gl->gl_demote_state = LM_ST_EXCLUSIVE;
 	gl->gl_hash = hash;
 	gl->gl_ops = glops;
-	gl->gl_stamp = jiffies;
+	snprintf(gl->gl_strname, GDLM_STRNAME_BYTES, "%8x%16llx", name.ln_type, (unsigned long long)number);
+	memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb));
+	gl->gl_lksb.sb_lvbptr = gl->gl_lvb;
 	gl->gl_tchange = jiffies;
 	gl->gl_object = NULL;
 	gl->gl_sbd = sdp;
@@ -753,10 +721,6 @@
 		}
 	}
 
-	error = gfs2_lm_get_lock(sdp, &name, &gl->gl_lock);
-	if (error)
-		goto fail_aspace;
-
 	write_lock(gl_lock_addr(hash));
 	tmp = search_bucket(hash, sdp, &name);
 	if (tmp) {
@@ -772,9 +736,6 @@
 
 	return 0;
 
-fail_aspace:
-	if (gl->gl_aspace)
-		gfs2_aspace_put(gl->gl_aspace);
 fail:
 	kmem_cache_free(gfs2_glock_cachep, gl);
 	return error;
@@ -966,7 +927,7 @@
 	if (!(gh->gh_flags & LM_FLAG_PRIORITY)) {
 		spin_unlock(&gl->gl_spin);
 		if (sdp->sd_lockstruct.ls_ops->lm_cancel)
-			sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock);
+			sdp->sd_lockstruct.ls_ops->lm_cancel(gl);
 		spin_lock(&gl->gl_spin);
 	}
 	return;
@@ -1051,7 +1012,6 @@
 			spin_lock(&gl->gl_spin);
 			clear_bit(GLF_LOCK, &gl->gl_flags);
 		}
-		gl->gl_stamp = jiffies;
 		if (list_empty(&gl->gl_holders) &&
 		    !test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
 		    !test_bit(GLF_DEMOTE, &gl->gl_flags))
@@ -1240,70 +1200,13 @@
 		gfs2_glock_dq_uninit(&ghs[x]);
 }
 
-static int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp)
+void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
 {
-	int error = -EIO;
-	if (!sdp->sd_lockstruct.ls_ops->lm_hold_lvb)
-		return 0;
-	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
- *
- */
-
-int gfs2_lvb_hold(struct gfs2_glock *gl)
-{
-	int error;
-
-	if (!atomic_read(&gl->gl_lvb_count)) {
-		error = gfs2_lm_hold_lvb(gl->gl_sbd, gl->gl_lock, &gl->gl_lvb);
-		if (error) 
-			return error;
-		gfs2_glock_hold(gl);
-	}
-	atomic_inc(&gl->gl_lvb_count);
-
-	return 0;
-}
-
-/**
- * gfs2_lvb_unhold - detach a LVB from a glock
- * @gl: The glock in question
- *
- */
-
-void gfs2_lvb_unhold(struct gfs2_glock *gl)
-{
-	struct gfs2_sbd *sdp = gl->gl_sbd;
-
-	gfs2_glock_hold(gl);
-	gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0);
-	if (atomic_dec_and_test(&gl->gl_lvb_count)) {
-		if (sdp->sd_lockstruct.ls_ops->lm_unhold_lvb)
-			sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(gl->gl_lock, gl->gl_lvb);
-		gl->gl_lvb = NULL;
-		gfs2_glock_put(gl);
-	}
-	gfs2_glock_put(gl);
-}
-
-static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name,
-			unsigned int state)
-{
-	struct gfs2_glock *gl;
 	unsigned long delay = 0;
 	unsigned long holdtime;
 	unsigned long now = jiffies;
 
-	gl = gfs2_glock_find(sdp, name);
-	if (!gl)
-		return;
-
+	gfs2_glock_hold(gl);
 	holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
 	if (time_before(now, holdtime))
 		delay = holdtime - now;
@@ -1317,74 +1220,33 @@
 		gfs2_glock_put(gl);
 }
 
-static void gfs2_jdesc_make_dirty(struct gfs2_sbd *sdp, unsigned int jid)
-{
-	struct gfs2_jdesc *jd;
-
-	spin_lock(&sdp->sd_jindex_spin);
-	list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
-		if (jd->jd_jid != jid)
-			continue;
-		jd->jd_dirty = 1;
-		break;
-	}
-	spin_unlock(&sdp->sd_jindex_spin);
-}
-
 /**
- * gfs2_glock_cb - Callback used by locking module
- * @sdp: Pointer to the superblock
- * @type: Type of callback
- * @data: Type dependent data pointer
+ * gfs2_glock_complete - Callback used by locking
+ * @gl: Pointer to the glock
+ * @ret: The return value from the dlm
  *
- * Called by the locking module when it wants to tell us something.
- * Either we need to drop a lock, one of our ASYNC requests completed, or
- * a journal from another client needs to be recovered.
  */
 
-void gfs2_glock_cb(void *cb_data, unsigned int type, void *data)
+void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
 {
-	struct gfs2_sbd *sdp = cb_data;
-
-	switch (type) {
-	case LM_CB_NEED_E:
-		blocking_cb(sdp, data, LM_ST_UNLOCKED);
-		return;
-
-	case LM_CB_NEED_D:
-		blocking_cb(sdp, data, LM_ST_DEFERRED);
-		return;
-
-	case LM_CB_NEED_S:
-		blocking_cb(sdp, data, LM_ST_SHARED);
-		return;
-
-	case LM_CB_ASYNC: {
-		struct lm_async_cb *async = data;
-		struct gfs2_glock *gl;
-
-		down_read(&gfs2_umount_flush_sem);
-		gl = gfs2_glock_find(sdp, &async->lc_name);
-		if (gfs2_assert_warn(sdp, gl))
+	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	gl->gl_reply = ret;
+	if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) {
+		struct gfs2_holder *gh;
+		spin_lock(&gl->gl_spin);
+		gh = find_first_waiter(gl);
+		if ((!(gh && (gh->gh_flags & LM_FLAG_NOEXP)) &&
+		     (gl->gl_target != LM_ST_UNLOCKED)) ||
+		    ((ret & ~LM_OUT_ST_MASK) != 0))
+			set_bit(GLF_FROZEN, &gl->gl_flags);
+		spin_unlock(&gl->gl_spin);
+		if (test_bit(GLF_FROZEN, &gl->gl_flags))
 			return;
-		gl->gl_reply = async->lc_ret;
-		set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
-		if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
-			gfs2_glock_put(gl);
-		up_read(&gfs2_umount_flush_sem);
-		return;
 	}
-
-	case LM_CB_NEED_RECOVERY:
-		gfs2_jdesc_make_dirty(sdp, *(unsigned int *)data);
-		if (sdp->sd_recoverd_process)
-			wake_up_process(sdp->sd_recoverd_process);
-		return;
-
-	default:
-		gfs2_assert_warn(sdp, 0);
-		return;
-	}
+	set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
+	gfs2_glock_hold(gl);
+	if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
+		gfs2_glock_put(gl);
 }
 
 /**
@@ -1515,6 +1377,25 @@
 	return has_entries;
 }
 
+
+/**
+ * thaw_glock - thaw out a glock which has an unprocessed reply waiting
+ * @gl: The glock to thaw
+ *
+ * N.B. When we freeze a glock, we leave a ref to the glock outstanding,
+ * so this has to result in the ref count being dropped by one.
+ */
+
+static void thaw_glock(struct gfs2_glock *gl)
+{
+	if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))
+		return;
+	set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
+	gfs2_glock_hold(gl);
+	if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
+		gfs2_glock_put(gl);
+}
+
 /**
  * clear_glock - look at a glock and see if we can free it from glock cache
  * @gl: the glock to look at
@@ -1540,6 +1421,20 @@
 }
 
 /**
+ * gfs2_glock_thaw - Thaw any frozen glocks
+ * @sdp: The super block
+ *
+ */
+
+void gfs2_glock_thaw(struct gfs2_sbd *sdp)
+{
+	unsigned x;
+
+	for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
+		examine_bucket(thaw_glock, sdp, x);
+}
+
+/**
  * gfs2_gl_hash_clear - Empty out the glock hash table
  * @sdp: the filesystem
  * @wait: wait until it's all gone
@@ -1619,7 +1514,7 @@
 	if (flags & LM_FLAG_NOEXP)
 		*p++ = 'e';
 	if (flags & LM_FLAG_ANY)
-		*p++ = 'a';
+		*p++ = 'A';
 	if (flags & LM_FLAG_PRIORITY)
 		*p++ = 'p';
 	if (flags & GL_ASYNC)
@@ -1683,6 +1578,10 @@
 		*p++ = 'i';
 	if (test_bit(GLF_REPLY_PENDING, gflags))
 		*p++ = 'r';
+	if (test_bit(GLF_INITIAL, gflags))
+		*p++ = 'I';
+	if (test_bit(GLF_FROZEN, gflags))
+		*p++ = 'F';
 	*p = 0;
 	return buf;
 }
@@ -1717,14 +1616,13 @@
 	dtime *= 1000000/HZ; /* demote time in uSec */
 	if (!test_bit(GLF_DEMOTE, &gl->gl_flags))
 		dtime = 0;
-	gfs2_print_dbg(seq, "G:  s:%s n:%u/%llu f:%s t:%s d:%s/%llu l:%d a:%d r:%d\n",
+	gfs2_print_dbg(seq, "G:  s:%s n:%u/%llu f:%s t:%s d:%s/%llu a:%d r:%d\n",
 		  state2str(gl->gl_state),
 		  gl->gl_name.ln_type,
 		  (unsigned long long)gl->gl_name.ln_number,
 		  gflags2str(gflags_buf, &gl->gl_flags),
 		  state2str(gl->gl_target),
 		  state2str(gl->gl_demote_state), dtime,
-		  atomic_read(&gl->gl_lvb_count),
 		  atomic_read(&gl->gl_ail_count),
 		  atomic_read(&gl->gl_ref));
 
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 543ec7e..a602a28 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -11,15 +11,130 @@
 #define __GLOCK_DOT_H__
 
 #include <linux/sched.h>
+#include <linux/parser.h>
 #include "incore.h"
 
-/* Flags for lock requests; used in gfs2_holder gh_flag field.
-   From lm_interface.h:
+/* Options for hostdata parser */
+
+enum {
+	Opt_jid,
+	Opt_id,
+	Opt_first,
+	Opt_nodir,
+	Opt_err,
+};
+
+/*
+ * lm_lockname types
+ */
+
+#define LM_TYPE_RESERVED	0x00
+#define LM_TYPE_NONDISK		0x01
+#define LM_TYPE_INODE		0x02
+#define LM_TYPE_RGRP		0x03
+#define LM_TYPE_META		0x04
+#define LM_TYPE_IOPEN		0x05
+#define LM_TYPE_FLOCK		0x06
+#define LM_TYPE_PLOCK		0x07
+#define LM_TYPE_QUOTA		0x08
+#define LM_TYPE_JOURNAL		0x09
+
+/*
+ * lm_lock() states
+ *
+ * SHARED is compatible with SHARED, not with DEFERRED or EX.
+ * DEFERRED is compatible with DEFERRED, not with SHARED or EX.
+ */
+
+#define LM_ST_UNLOCKED		0
+#define LM_ST_EXCLUSIVE		1
+#define LM_ST_DEFERRED		2
+#define LM_ST_SHARED		3
+
+/*
+ * lm_lock() flags
+ *
+ * LM_FLAG_TRY
+ * Don't wait to acquire the lock if it can't be granted immediately.
+ *
+ * LM_FLAG_TRY_1CB
+ * Send one blocking callback if TRY is set and the lock is not granted.
+ *
+ * LM_FLAG_NOEXP
+ * GFS sets this flag on lock requests it makes while doing journal recovery.
+ * These special requests should not be blocked due to the recovery like
+ * ordinary locks would be.
+ *
+ * LM_FLAG_ANY
+ * A SHARED request may also be granted in DEFERRED, or a DEFERRED request may
+ * also be granted in SHARED.  The preferred state is whichever is compatible
+ * with other granted locks, or the specified state if no other locks exist.
+ *
+ * LM_FLAG_PRIORITY
+ * Override fairness considerations.  Suppose a lock is held in a shared state
+ * and there is a pending request for the deferred state.  A shared lock
+ * request with the priority flag would be allowed to bypass the deferred
+ * request and directly join the other shared lock.  A shared lock request
+ * without the priority flag might be forced to wait until the deferred
+ * requested had acquired and released the lock.
+ */
+
 #define LM_FLAG_TRY		0x00000001
 #define LM_FLAG_TRY_1CB		0x00000002
 #define LM_FLAG_NOEXP		0x00000004
 #define LM_FLAG_ANY		0x00000008
-#define LM_FLAG_PRIORITY	0x00000010 */
+#define LM_FLAG_PRIORITY	0x00000010
+#define GL_ASYNC		0x00000040
+#define GL_EXACT		0x00000080
+#define GL_SKIP			0x00000100
+#define GL_ATIME		0x00000200
+#define GL_NOCACHE		0x00000400
+  
+/*
+ * lm_lock() and lm_async_cb return flags
+ *
+ * LM_OUT_ST_MASK
+ * Masks the lower two bits of lock state in the returned value.
+ *
+ * LM_OUT_CANCELED
+ * The lock request was canceled.
+ *
+ * LM_OUT_ASYNC
+ * The result of the request will be returned in an LM_CB_ASYNC callback.
+ *
+ */
+
+#define LM_OUT_ST_MASK		0x00000003
+#define LM_OUT_CANCELED		0x00000008
+#define LM_OUT_ASYNC		0x00000080
+#define LM_OUT_ERROR		0x00000100
+
+/*
+ * lm_recovery_done() messages
+ */
+
+#define LM_RD_GAVEUP		308
+#define LM_RD_SUCCESS		309
+
+#define GLR_TRYFAILED		13
+
+struct lm_lockops {
+	const char *lm_proto_name;
+	int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname);
+ 	void (*lm_unmount) (struct gfs2_sbd *sdp);
+	void (*lm_withdraw) (struct gfs2_sbd *sdp);
+	void (*lm_put_lock) (struct kmem_cache *cachep, void *gl);
+	unsigned int (*lm_lock) (struct gfs2_glock *gl,
+				 unsigned int req_state, unsigned int flags);
+	void (*lm_cancel) (struct gfs2_glock *gl);
+	const match_table_t *lm_tokens;
+};
+
+#define LM_FLAG_TRY		0x00000001
+#define LM_FLAG_TRY_1CB		0x00000002
+#define LM_FLAG_NOEXP		0x00000004
+#define LM_FLAG_ANY		0x00000008
+#define LM_FLAG_PRIORITY	0x00000010
 
 #define GL_ASYNC		0x00000040
 #define GL_EXACT		0x00000080
@@ -128,10 +243,12 @@
 int gfs2_lvb_hold(struct gfs2_glock *gl);
 void gfs2_lvb_unhold(struct gfs2_glock *gl);
 
-void gfs2_glock_cb(void *cb_data, unsigned int type, void *data);
+void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state);
+void gfs2_glock_complete(struct gfs2_glock *gl, int ret);
 void gfs2_reclaim_glock(struct gfs2_sbd *sdp);
 void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
 void gfs2_glock_finish_truncate(struct gfs2_inode *ip);
+void gfs2_glock_thaw(struct gfs2_sbd *sdp);
 
 int __init gfs2_glock_init(void);
 void gfs2_glock_exit(void);
@@ -141,4 +258,6 @@
 int gfs2_register_debugfs(void);
 void gfs2_unregister_debugfs(void);
 
+extern const struct lm_lockops gfs2_dlm_ops;
+
 #endif /* __GLOCK_DOT_H__ */
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 8522d3a..bf23a62 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -12,7 +12,6 @@
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <linux/bio.h>
 
 #include "gfs2.h"
@@ -38,19 +37,24 @@
 static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
-	unsigned int blocks;
 	struct list_head *head = &gl->gl_ail_list;
 	struct gfs2_bufdata *bd;
 	struct buffer_head *bh;
-	int error;
+	struct gfs2_trans tr;
 
-	blocks = atomic_read(&gl->gl_ail_count);
-	if (!blocks)
+	memset(&tr, 0, sizeof(tr));
+	tr.tr_revokes = atomic_read(&gl->gl_ail_count);
+
+	if (!tr.tr_revokes)
 		return;
 
-	error = gfs2_trans_begin(sdp, 0, blocks);
-	if (gfs2_assert_withdraw(sdp, !error))
-		return;
+	/* A shortened, inline version of gfs2_trans_begin() */
+	tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64));
+	tr.tr_ip = (unsigned long)__builtin_return_address(0);
+	INIT_LIST_HEAD(&tr.tr_list_buf);
+	gfs2_log_reserve(sdp, tr.tr_reserved);
+	BUG_ON(current->journal_info);
+	current->journal_info = &tr;
 
 	gfs2_log_lock(sdp);
 	while (!list_empty(head)) {
@@ -72,29 +76,7 @@
 }
 
 /**
- * gfs2_pte_inval - Sync and invalidate all PTEs associated with a glock
- * @gl: the glock
- *
- */
-
-static void gfs2_pte_inval(struct gfs2_glock *gl)
-{
-	struct gfs2_inode *ip;
-	struct inode *inode;
-
-	ip = gl->gl_object;
-	inode = &ip->i_inode;
-	if (!ip || !S_ISREG(inode->i_mode))
-		return;
-
-	unmap_shared_mapping_range(inode->i_mapping, 0, 0);
-	if (test_bit(GIF_SW_PAGED, &ip->i_flags))
-		set_bit(GLF_DIRTY, &gl->gl_flags);
-
-}
-
-/**
- * meta_go_sync - sync out the metadata for this glock
+ * rgrp_go_sync - sync out the metadata for this glock
  * @gl: the glock
  *
  * Called when demoting or unlocking an EX glock.  We must flush
@@ -102,36 +84,42 @@
  * not return to caller to demote/unlock the glock until I/O is complete.
  */
 
-static void meta_go_sync(struct gfs2_glock *gl)
+static void rgrp_go_sync(struct gfs2_glock *gl)
 {
-	if (gl->gl_state != LM_ST_EXCLUSIVE)
-		return;
+	struct address_space *metamapping = gl->gl_aspace->i_mapping;
+	int error;
 
-	if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) {
-		gfs2_log_flush(gl->gl_sbd, gl);
-		gfs2_meta_sync(gl);
-		gfs2_ail_empty_gl(gl);
-	}
+	if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
+		return;
+	BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
+
+	gfs2_log_flush(gl->gl_sbd, gl);
+	filemap_fdatawrite(metamapping);
+	error = filemap_fdatawait(metamapping);
+        mapping_set_error(metamapping, error);
+	gfs2_ail_empty_gl(gl);
 }
 
 /**
- * meta_go_inval - invalidate the metadata for this glock
+ * rgrp_go_inval - invalidate the metadata for this glock
  * @gl: the glock
  * @flags:
  *
+ * We never used LM_ST_DEFERRED with resource groups, so that we
+ * should always see the metadata flag set here.
+ *
  */
 
-static void meta_go_inval(struct gfs2_glock *gl, int flags)
+static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
 {
-	if (!(flags & DIO_METADATA))
-		return;
+	struct address_space *mapping = gl->gl_aspace->i_mapping;
 
-	gfs2_meta_inval(gl);
-	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) {
+	BUG_ON(!(flags & DIO_METADATA));
+	gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
+	truncate_inode_pages(mapping, 0);
+
+	if (gl->gl_object) {
 		struct gfs2_rgrpd *rgd = (struct gfs2_rgrpd *)gl->gl_object;
-
 		rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
 	}
 }
@@ -148,48 +136,54 @@
 	struct address_space *metamapping = gl->gl_aspace->i_mapping;
 	int error;
 
-	if (gl->gl_state != LM_ST_UNLOCKED)
-		gfs2_pte_inval(gl);
-	if (gl->gl_state != LM_ST_EXCLUSIVE)
-		return;
-
 	if (ip && !S_ISREG(ip->i_inode.i_mode))
 		ip = NULL;
+	if (ip && test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
+		unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0);
+	if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
+		return;
 
-	if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
-		gfs2_log_flush(gl->gl_sbd, gl);
-		filemap_fdatawrite(metamapping);
-		if (ip) {
-			struct address_space *mapping = ip->i_inode.i_mapping;
-			filemap_fdatawrite(mapping);
-			error = filemap_fdatawait(mapping);
-			mapping_set_error(mapping, error);
-		}
-		error = filemap_fdatawait(metamapping);
-		mapping_set_error(metamapping, error);
-		clear_bit(GLF_DIRTY, &gl->gl_flags);
-		gfs2_ail_empty_gl(gl);
+	BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
+
+	gfs2_log_flush(gl->gl_sbd, gl);
+	filemap_fdatawrite(metamapping);
+	if (ip) {
+		struct address_space *mapping = ip->i_inode.i_mapping;
+		filemap_fdatawrite(mapping);
+		error = filemap_fdatawait(mapping);
+		mapping_set_error(mapping, error);
 	}
+	error = filemap_fdatawait(metamapping);
+	mapping_set_error(metamapping, error);
+	gfs2_ail_empty_gl(gl);
 }
 
 /**
  * inode_go_inval - prepare a inode glock to be released
  * @gl: the glock
  * @flags:
+ * 
+ * Normally we invlidate everything, but if we are moving into
+ * LM_ST_DEFERRED from LM_ST_SHARED or LM_ST_EXCLUSIVE then we
+ * can keep hold of the metadata, since it won't have changed.
  *
  */
 
 static void inode_go_inval(struct gfs2_glock *gl, int flags)
 {
 	struct gfs2_inode *ip = gl->gl_object;
-	int meta = (flags & DIO_METADATA);
 
-	if (meta) {
-		gfs2_meta_inval(gl);
+	gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
+
+	if (flags & DIO_METADATA) {
+		struct address_space *mapping = gl->gl_aspace->i_mapping;
+		truncate_inode_pages(mapping, 0);
 		if (ip)
 			set_bit(GIF_INVALID, &ip->i_flags);
 	}
 
+	if (ip == GFS2_I(gl->gl_sbd->sd_rindex))
+		gl->gl_sbd->sd_rindex_uptodate = 0;
 	if (ip && S_ISREG(ip->i_inode.i_mode))
 		truncate_inode_pages(ip->i_inode.i_mapping, 0);
 }
@@ -390,20 +384,7 @@
 	return 0;
 }
 
-/**
- * quota_go_demote_ok - Check to see if it's ok to unlock a quota glock
- * @gl: the glock
- *
- * Returns: 1 if it's ok
- */
-
-static int quota_go_demote_ok(const struct gfs2_glock *gl)
-{
-	return !atomic_read(&gl->gl_lvb_count);
-}
-
 const struct gfs2_glock_operations gfs2_meta_glops = {
-	.go_xmote_th = meta_go_sync,
 	.go_type = LM_TYPE_META,
 };
 
@@ -418,8 +399,8 @@
 };
 
 const struct gfs2_glock_operations gfs2_rgrp_glops = {
-	.go_xmote_th = meta_go_sync,
-	.go_inval = meta_go_inval,
+	.go_xmote_th = rgrp_go_sync,
+	.go_inval = rgrp_go_inval,
 	.go_demote_ok = rgrp_go_demote_ok,
 	.go_lock = rgrp_go_lock,
 	.go_unlock = rgrp_go_unlock,
@@ -448,7 +429,6 @@
 };
 
 const struct gfs2_glock_operations gfs2_quota_glops = {
-	.go_demote_ok = quota_go_demote_ok,
 	.go_type = LM_TYPE_QUOTA,
 };
 
@@ -456,3 +436,15 @@
 	.go_type = LM_TYPE_JOURNAL,
 };
 
+const struct gfs2_glock_operations *gfs2_glops_list[] = {
+	[LM_TYPE_META] = &gfs2_meta_glops,
+	[LM_TYPE_INODE] = &gfs2_inode_glops,
+	[LM_TYPE_RGRP] = &gfs2_rgrp_glops,
+	[LM_TYPE_NONDISK] = &gfs2_trans_glops,
+	[LM_TYPE_IOPEN] = &gfs2_iopen_glops,
+	[LM_TYPE_FLOCK] = &gfs2_flock_glops,
+	[LM_TYPE_NONDISK] = &gfs2_nondisk_glops,
+	[LM_TYPE_QUOTA] = &gfs2_quota_glops,
+	[LM_TYPE_JOURNAL] = &gfs2_journal_glops,
+};
+
diff --git a/fs/gfs2/glops.h b/fs/gfs2/glops.h
index a1d9b5b..b3aa2e3 100644
--- a/fs/gfs2/glops.h
+++ b/fs/gfs2/glops.h
@@ -21,5 +21,6 @@
 extern const struct gfs2_glock_operations gfs2_nondisk_glops;
 extern const struct gfs2_glock_operations gfs2_quota_glops;
 extern const struct gfs2_glock_operations gfs2_journal_glops;
+extern const struct gfs2_glock_operations *gfs2_glops_list[];
 
 #endif /* __GLOPS_DOT_H__ */
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 608849d..399d1b9 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -12,6 +12,8 @@
 
 #include <linux/fs.h>
 #include <linux/workqueue.h>
+#include <linux/dlm.h>
+#include <linux/buffer_head.h>
 
 #define DIO_WAIT	0x00000010
 #define DIO_METADATA	0x00000020
@@ -26,6 +28,7 @@
 struct gfs2_ail;
 struct gfs2_jdesc;
 struct gfs2_sbd;
+struct lm_lockops;
 
 typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret);
 
@@ -121,6 +124,28 @@
 	struct list_head bd_ail_gl_list;
 };
 
+/*
+ * Internally, we prefix things with gdlm_ and GDLM_ (for gfs-dlm) since a
+ * prefix of lock_dlm_ gets awkward.
+ */
+
+#define GDLM_STRNAME_BYTES	25
+#define GDLM_LVB_SIZE		32
+
+enum {
+	DFL_BLOCK_LOCKS		= 0,
+};
+
+struct lm_lockname {
+	u64 ln_number;
+	unsigned int ln_type;
+};
+
+#define lm_name_equal(name1, name2) \
+        (((name1)->ln_number == (name2)->ln_number) && \
+         ((name1)->ln_type == (name2)->ln_type))
+
+
 struct gfs2_glock_operations {
 	void (*go_xmote_th) (struct gfs2_glock *gl);
 	int (*go_xmote_bh) (struct gfs2_glock *gl, struct gfs2_holder *gh);
@@ -162,6 +187,8 @@
 	GLF_LFLUSH			= 7,
 	GLF_INVALIDATE_IN_PROGRESS	= 8,
 	GLF_REPLY_PENDING		= 9,
+	GLF_INITIAL			= 10,
+	GLF_FROZEN			= 11,
 };
 
 struct gfs2_glock {
@@ -176,16 +203,15 @@
 	unsigned int gl_target;
 	unsigned int gl_reply;
 	unsigned int gl_hash;
+	unsigned int gl_req;
 	unsigned int gl_demote_state; /* state requested by remote node */
 	unsigned long gl_demote_time; /* time of first demote request */
 	struct list_head gl_holders;
 
 	const struct gfs2_glock_operations *gl_ops;
-	void *gl_lock;
-	char *gl_lvb;
-	atomic_t gl_lvb_count;
-
-	unsigned long gl_stamp;
+	char gl_strname[GDLM_STRNAME_BYTES];
+	struct dlm_lksb gl_lksb;
+	char gl_lvb[32];
 	unsigned long gl_tchange;
 	void *gl_object;
 
@@ -283,7 +309,9 @@
 
 struct gfs2_quota_data {
 	struct list_head qd_list;
-	unsigned int qd_count;
+	struct list_head qd_reclaim;
+
+	atomic_t qd_count;
 
 	u32 qd_id;
 	unsigned long qd_flags;		/* QDF_... */
@@ -303,7 +331,6 @@
 
 	u64 qd_sync_gen;
 	unsigned long qd_last_warn;
-	unsigned long qd_last_touched;
 };
 
 struct gfs2_trans {
@@ -390,7 +417,7 @@
 	unsigned int ar_suiddir:1;		/* suiddir support */
 	unsigned int ar_data:2;			/* ordered/writeback */
 	unsigned int ar_meta:1;			/* mount metafs */
-	unsigned int ar_num_glockd;		/* Number of glockd threads */
+	unsigned int ar_discard:1;		/* discard requests */
 };
 
 struct gfs2_tune {
@@ -406,7 +433,6 @@
 	unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */
 	unsigned int gt_quota_scale_num; /* Numerator */
 	unsigned int gt_quota_scale_den; /* Denominator */
-	unsigned int gt_quota_cache_secs;
 	unsigned int gt_quota_quantum; /* Secs between syncs to quota file */
 	unsigned int gt_new_files_jdata;
 	unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */
@@ -445,6 +471,31 @@
 
 	char sb_lockproto[GFS2_LOCKNAME_LEN];
 	char sb_locktable[GFS2_LOCKNAME_LEN];
+	u8 sb_uuid[16];
+};
+
+/*
+ * lm_mount() return values
+ *
+ * ls_jid - the journal ID this node should use
+ * ls_first - this node is the first to mount the file system
+ * ls_lockspace - lock module's context for this file system
+ * ls_ops - lock module's functions
+ */
+
+struct lm_lockstruct {
+	u32 ls_id;
+	unsigned int ls_jid;
+	unsigned int ls_first;
+	unsigned int ls_first_done;
+	unsigned int ls_nodir;
+	const struct lm_lockops *ls_ops;
+	unsigned long ls_flags;
+	dlm_lockspace_t *ls_dlm;
+
+	int ls_recover_jid;
+	int ls_recover_jid_done;
+	int ls_recover_jid_status;
 };
 
 struct gfs2_sbd {
@@ -520,7 +571,6 @@
 	spinlock_t sd_jindex_spin;
 	struct mutex sd_jindex_mutex;
 	unsigned int sd_journals;
-	unsigned long sd_jindex_refresh_time;
 
 	struct gfs2_jdesc *sd_jdesc;
 	struct gfs2_holder sd_journal_gh;
@@ -540,7 +590,6 @@
 
 	struct list_head sd_quota_list;
 	atomic_t sd_quota_count;
-	spinlock_t sd_quota_spin;
 	struct mutex sd_quota_mutex;
 	wait_queue_head_t sd_quota_wait;
 	struct list_head sd_trunc_list;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 3b87c18..7b277d44 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -16,7 +16,6 @@
 #include <linux/sort.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
 #include <linux/security.h>
 #include <linux/time.h>
 
@@ -137,16 +136,16 @@
 
 	if (S_ISREG(mode)) {
 		inode->i_op = &gfs2_file_iops;
-		if (sdp->sd_args.ar_localflocks)
-			inode->i_fop = &gfs2_file_fops_nolock;
+		if (gfs2_localflocks(sdp))
+			inode->i_fop = gfs2_file_fops_nolock;
 		else
-			inode->i_fop = &gfs2_file_fops;
+			inode->i_fop = gfs2_file_fops;
 	} else if (S_ISDIR(mode)) {
 		inode->i_op = &gfs2_dir_iops;
-		if (sdp->sd_args.ar_localflocks)
-			inode->i_fop = &gfs2_dir_fops_nolock;
+		if (gfs2_localflocks(sdp))
+			inode->i_fop = gfs2_dir_fops_nolock;
 		else
-			inode->i_fop = &gfs2_dir_fops;
+			inode->i_fop = gfs2_dir_fops;
 	} else if (S_ISLNK(mode)) {
 		inode->i_op = &gfs2_symlink_iops;
 	} else {
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index d532936..dca4fee 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -101,12 +101,26 @@
 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 file_operations gfs2_file_fops;
-extern const struct file_operations gfs2_dir_fops;
-extern const struct file_operations gfs2_file_fops_nolock;
-extern const struct file_operations gfs2_dir_fops_nolock;
+extern const struct file_operations *gfs2_file_fops_nolock;
+extern const struct file_operations *gfs2_dir_fops_nolock;
 
 extern void gfs2_set_inode_flags(struct inode *inode);
+ 
+#ifdef CONFIG_GFS2_FS_LOCKING_DLM
+extern const struct file_operations *gfs2_file_fops;
+extern const struct file_operations *gfs2_dir_fops;
+static inline int gfs2_localflocks(const struct gfs2_sbd *sdp)
+{
+	return sdp->sd_args.ar_localflocks;
+}
+#else /* Single node only */
+#define gfs2_file_fops NULL
+#define gfs2_dir_fops NULL
+static inline int gfs2_localflocks(const struct gfs2_sbd *sdp)
+{
+	return 1;
+}
+#endif /* CONFIG_GFS2_FS_LOCKING_DLM */
 
 #endif /* __INODE_DOT_H__ */
 
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
new file mode 100644
index 0000000..46df988
--- /dev/null
+++ b/fs/gfs2/lock_dlm.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+ * Copyright (C) 2004-2009 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/dlm.h>
+#include <linux/types.h>
+#include <linux/gfs2_ondisk.h>
+
+#include "incore.h"
+#include "glock.h"
+#include "util.h"
+
+
+static void gdlm_ast(void *arg)
+{
+	struct gfs2_glock *gl = arg;
+	unsigned ret = gl->gl_state;
+
+	BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
+
+	if (gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID)
+		memset(gl->gl_lvb, 0, GDLM_LVB_SIZE);
+
+	switch (gl->gl_lksb.sb_status) {
+	case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */
+		kmem_cache_free(gfs2_glock_cachep, gl);
+		return;
+	case -DLM_ECANCEL: /* Cancel while getting lock */
+		ret |= LM_OUT_CANCELED;
+		goto out;
+	case -EAGAIN: /* Try lock fails */
+		goto out;
+	case -EINVAL: /* Invalid */
+	case -ENOMEM: /* Out of memory */
+		ret |= LM_OUT_ERROR;
+		goto out;
+	case 0: /* Success */
+		break;
+	default: /* Something unexpected */
+		BUG();
+	}
+
+	ret = gl->gl_req;
+	if (gl->gl_lksb.sb_flags & DLM_SBF_ALTMODE) {
+		if (gl->gl_req == LM_ST_SHARED)
+			ret = LM_ST_DEFERRED;
+		else if (gl->gl_req == LM_ST_DEFERRED)
+			ret = LM_ST_SHARED;
+		else
+			BUG();
+	}
+
+	set_bit(GLF_INITIAL, &gl->gl_flags);
+	gfs2_glock_complete(gl, ret);
+	return;
+out:
+	if (!test_bit(GLF_INITIAL, &gl->gl_flags))
+		gl->gl_lksb.sb_lkid = 0;
+	gfs2_glock_complete(gl, ret);
+}
+
+static void gdlm_bast(void *arg, int mode)
+{
+	struct gfs2_glock *gl = arg;
+
+	switch (mode) {
+	case DLM_LOCK_EX:
+		gfs2_glock_cb(gl, LM_ST_UNLOCKED);
+		break;
+	case DLM_LOCK_CW:
+		gfs2_glock_cb(gl, LM_ST_DEFERRED);
+		break;
+	case DLM_LOCK_PR:
+		gfs2_glock_cb(gl, LM_ST_SHARED);
+		break;
+	default:
+		printk(KERN_ERR "unknown bast mode %d", mode);
+		BUG();
+	}
+}
+
+/* convert gfs lock-state to dlm lock-mode */
+
+static int make_mode(const unsigned int lmstate)
+{
+	switch (lmstate) {
+	case LM_ST_UNLOCKED:
+		return DLM_LOCK_NL;
+	case LM_ST_EXCLUSIVE:
+		return DLM_LOCK_EX;
+	case LM_ST_DEFERRED:
+		return DLM_LOCK_CW;
+	case LM_ST_SHARED:
+		return DLM_LOCK_PR;
+	}
+	printk(KERN_ERR "unknown LM state %d", lmstate);
+	BUG();
+	return -1;
+}
+
+static u32 make_flags(const u32 lkid, const unsigned int gfs_flags,
+		      const int req)
+{
+	u32 lkf = 0;
+
+	if (gfs_flags & LM_FLAG_TRY)
+		lkf |= DLM_LKF_NOQUEUE;
+
+	if (gfs_flags & LM_FLAG_TRY_1CB) {
+		lkf |= DLM_LKF_NOQUEUE;
+		lkf |= DLM_LKF_NOQUEUEBAST;
+	}
+
+	if (gfs_flags & LM_FLAG_PRIORITY) {
+		lkf |= DLM_LKF_NOORDER;
+		lkf |= DLM_LKF_HEADQUE;
+	}
+
+	if (gfs_flags & LM_FLAG_ANY) {
+		if (req == DLM_LOCK_PR)
+			lkf |= DLM_LKF_ALTCW;
+		else if (req == DLM_LOCK_CW)
+			lkf |= DLM_LKF_ALTPR;
+		else
+			BUG();
+	}
+
+	if (lkid != 0) 
+		lkf |= DLM_LKF_CONVERT;
+
+	lkf |= DLM_LKF_VALBLK;
+
+	return lkf;
+}
+
+static unsigned int gdlm_lock(struct gfs2_glock *gl,
+			      unsigned int req_state, unsigned int flags)
+{
+	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	int error;
+	int req;
+	u32 lkf;
+
+	gl->gl_req = req_state;
+	req = make_mode(req_state);
+	lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req);
+
+	/*
+	 * Submit the actual lock request.
+	 */
+
+	error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname,
+			 GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
+	if (error == -EAGAIN)
+		return 0;
+	if (error)
+		return LM_OUT_ERROR;
+	return LM_OUT_ASYNC;
+}
+
+static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr)
+{
+	struct gfs2_glock *gl = ptr;
+	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	int error;
+
+	if (gl->gl_lksb.sb_lkid == 0) {
+		kmem_cache_free(cachep, gl);
+		return;
+	}
+
+	error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK,
+			   NULL, gl);
+	if (error) {
+		printk(KERN_ERR "gdlm_unlock %x,%llx err=%d\n",
+		       gl->gl_name.ln_type,
+		       (unsigned long long)gl->gl_name.ln_number, error);
+		return;
+	}
+}
+
+static void gdlm_cancel(struct gfs2_glock *gl)
+{
+	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
+}
+
+static int gdlm_mount(struct gfs2_sbd *sdp, const char *fsname)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	int error;
+
+	if (fsname == NULL) {
+		fs_info(sdp, "no fsname found\n");
+		return -EINVAL;
+	}
+
+	error = dlm_new_lockspace(fsname, strlen(fsname), &ls->ls_dlm,
+				  DLM_LSFL_FS | DLM_LSFL_NEWEXCL |
+				  (ls->ls_nodir ? DLM_LSFL_NODIR : 0),
+				  GDLM_LVB_SIZE);
+	if (error)
+		printk(KERN_ERR "dlm_new_lockspace error %d", error);
+
+	return error;
+}
+
+static void gdlm_unmount(struct gfs2_sbd *sdp)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+
+	if (ls->ls_dlm) {
+		dlm_release_lockspace(ls->ls_dlm, 2);
+		ls->ls_dlm = NULL;
+	}
+}
+
+static const match_table_t dlm_tokens = {
+	{ Opt_jid, "jid=%d"},
+	{ Opt_id, "id=%d"},
+	{ Opt_first, "first=%d"},
+	{ Opt_nodir, "nodir=%d"},
+	{ Opt_err, NULL },
+};
+
+const struct lm_lockops gfs2_dlm_ops = {
+	.lm_proto_name = "lock_dlm",
+	.lm_mount = gdlm_mount,
+	.lm_unmount = gdlm_unmount,
+	.lm_put_lock = gdlm_put_lock,
+	.lm_lock = gdlm_lock,
+	.lm_cancel = gdlm_cancel,
+	.lm_tokens = &dlm_tokens,
+};
+
diff --git a/fs/gfs2/locking.c b/fs/gfs2/locking.c
deleted file mode 100644
index 523243a..0000000
--- a/fs/gfs2/locking.c
+++ /dev/null
@@ -1,232 +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/module.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <linux/kmod.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/lm_interface.h>
-
-struct lmh_wrapper {
-	struct list_head lw_list;
-	const struct lm_lockops *lw_ops;
-};
-
-static int nolock_mount(char *table_name, char *host_data,
-			lm_callback_t cb, void *cb_data,
-			unsigned int min_lvb_size, int flags,
-			struct lm_lockstruct *lockstruct,
-			struct kobject *fskobj);
-
-/* List of registered low-level locking protocols.  A file system selects one
-   of them by name at mount time, e.g. lock_nolock, lock_dlm. */
-
-static const struct lm_lockops nolock_ops = {
-	.lm_proto_name = "lock_nolock",
-	.lm_mount = nolock_mount,
-};
-
-static struct lmh_wrapper nolock_proto  = {
-	.lw_list = LIST_HEAD_INIT(nolock_proto.lw_list),
-	.lw_ops = &nolock_ops,
-};
-
-static LIST_HEAD(lmh_list);
-static DEFINE_MUTEX(lmh_lock);
-
-static int nolock_mount(char *table_name, char *host_data,
-			lm_callback_t cb, void *cb_data,
-			unsigned int min_lvb_size, int flags,
-			struct lm_lockstruct *lockstruct,
-			struct kobject *fskobj)
-{
-	char *c;
-	unsigned int jid;
-
-	c = strstr(host_data, "jid=");
-	if (!c)
-		jid = 0;
-	else {
-		c += 4;
-		sscanf(c, "%u", &jid);
-	}
-
-	lockstruct->ls_jid = jid;
-	lockstruct->ls_first = 1;
-	lockstruct->ls_lvb_size = min_lvb_size;
-	lockstruct->ls_ops = &nolock_ops;
-	lockstruct->ls_flags = LM_LSFLAG_LOCAL;
-
-	return 0;
-}
-
-/**
- * gfs2_register_lockproto - Register a low-level locking protocol
- * @proto: the protocol definition
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-int gfs2_register_lockproto(const struct lm_lockops *proto)
-{
-	struct lmh_wrapper *lw;
-
-	mutex_lock(&lmh_lock);
-
-	list_for_each_entry(lw, &lmh_list, lw_list) {
-		if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) {
-			mutex_unlock(&lmh_lock);
-			printk(KERN_INFO "GFS2: protocol %s already exists\n",
-			       proto->lm_proto_name);
-			return -EEXIST;
-		}
-	}
-
-	lw = kzalloc(sizeof(struct lmh_wrapper), GFP_KERNEL);
-	if (!lw) {
-		mutex_unlock(&lmh_lock);
-		return -ENOMEM;
-	}
-
-	lw->lw_ops = proto;
-	list_add(&lw->lw_list, &lmh_list);
-
-	mutex_unlock(&lmh_lock);
-
-	return 0;
-}
-
-/**
- * gfs2_unregister_lockproto - Unregister a low-level locking protocol
- * @proto: the protocol definition
- *
- */
-
-void gfs2_unregister_lockproto(const struct lm_lockops *proto)
-{
-	struct lmh_wrapper *lw;
-
-	mutex_lock(&lmh_lock);
-
-	list_for_each_entry(lw, &lmh_list, lw_list) {
-		if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) {
-			list_del(&lw->lw_list);
-			mutex_unlock(&lmh_lock);
-			kfree(lw);
-			return;
-		}
-	}
-
-	mutex_unlock(&lmh_lock);
-
-	printk(KERN_WARNING "GFS2: can't unregister lock protocol %s\n",
-	       proto->lm_proto_name);
-}
-
-/**
- * gfs2_mount_lockproto - Mount a lock protocol
- * @proto_name - the name of the protocol
- * @table_name - the name of the lock space
- * @host_data - data specific to this host
- * @cb - the callback to the code using the lock module
- * @sdp - The GFS2 superblock
- * @min_lvb_size - the mininum LVB size that the caller can deal with
- * @flags - LM_MFLAG_*
- * @lockstruct - a structure returned describing the mount
- *
- * Returns: 0 on success, -EXXX on failure
- */
-
-int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data,
-			 lm_callback_t cb, void *cb_data,
-			 unsigned int min_lvb_size, int flags,
-			 struct lm_lockstruct *lockstruct,
-			 struct kobject *fskobj)
-{
-	struct lmh_wrapper *lw = NULL;
-	int try = 0;
-	int error, found;
-
-
-retry:
-	mutex_lock(&lmh_lock);
-
-	if (list_empty(&nolock_proto.lw_list))
-		list_add(&nolock_proto.lw_list, &lmh_list);
-
-	found = 0;
-	list_for_each_entry(lw, &lmh_list, lw_list) {
-		if (!strcmp(lw->lw_ops->lm_proto_name, proto_name)) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
-		if (!try && capable(CAP_SYS_MODULE)) {
-			try = 1;
-			mutex_unlock(&lmh_lock);
-			request_module(proto_name);
-			goto retry;
-		}
-		printk(KERN_INFO "GFS2: can't find protocol %s\n", proto_name);
-		error = -ENOENT;
-		goto out;
-	}
-
-	if (lw->lw_ops->lm_owner &&
-	    !try_module_get(lw->lw_ops->lm_owner)) {
-		try = 0;
-		mutex_unlock(&lmh_lock);
-		msleep(1000);
-		goto retry;
-	}
-
-	error = lw->lw_ops->lm_mount(table_name, host_data, cb, cb_data,
-				     min_lvb_size, flags, lockstruct, fskobj);
-	if (error)
-		module_put(lw->lw_ops->lm_owner);
-out:
-	mutex_unlock(&lmh_lock);
-	return error;
-}
-
-void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct)
-{
-	mutex_lock(&lmh_lock);
-	if (lockstruct->ls_ops->lm_unmount)
-		lockstruct->ls_ops->lm_unmount(lockstruct->ls_lockspace);
-	if (lockstruct->ls_ops->lm_owner)
-		module_put(lockstruct->ls_ops->lm_owner);
-	mutex_unlock(&lmh_lock);
-}
-
-/**
- * gfs2_withdraw_lockproto - abnormally unmount a lock module
- * @lockstruct: the lockstruct passed into mount
- *
- */
-
-void gfs2_withdraw_lockproto(struct lm_lockstruct *lockstruct)
-{
-	mutex_lock(&lmh_lock);
-	lockstruct->ls_ops->lm_withdraw(lockstruct->ls_lockspace);
-	if (lockstruct->ls_ops->lm_owner)
-		module_put(lockstruct->ls_ops->lm_owner);
-	mutex_unlock(&lmh_lock);
-}
-
-EXPORT_SYMBOL_GPL(gfs2_register_lockproto);
-EXPORT_SYMBOL_GPL(gfs2_unregister_lockproto);
-
diff --git a/fs/gfs2/locking/dlm/Makefile b/fs/gfs2/locking/dlm/Makefile
deleted file mode 100644
index 2609bb6..0000000
--- a/fs/gfs2/locking/dlm/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.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
deleted file mode 100644
index 2482c90..0000000
--- a/fs/gfs2/locking/dlm/lock.c
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-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 "lock_dlm.h"
-
-static char junk_lvb[GDLM_LVB_SIZE];
-
-
-/* convert dlm lock-mode to gfs lock-state */
-
-static s16 gdlm_make_lmstate(s16 dlmmode)
-{
-	switch (dlmmode) {
-	case DLM_LOCK_IV:
-	case DLM_LOCK_NL:
-		return LM_ST_UNLOCKED;
-	case DLM_LOCK_EX:
-		return LM_ST_EXCLUSIVE;
-	case DLM_LOCK_CW:
-		return LM_ST_DEFERRED;
-	case DLM_LOCK_PR:
-		return LM_ST_SHARED;
-	}
-	gdlm_assert(0, "unknown DLM mode %d", dlmmode);
-	return -1;
-}
-
-/* A lock placed on this queue is re-submitted to DLM as soon as the lock_dlm
-   thread gets to it. */
-
-static void queue_submit(struct gdlm_lock *lp)
-{
-	struct gdlm_ls *ls = lp->ls;
-
-	spin_lock(&ls->async_lock);
-	list_add_tail(&lp->delay_list, &ls->submit);
-	spin_unlock(&ls->async_lock);
-	wake_up(&ls->thread_wait);
-}
-
-static void wake_up_ast(struct gdlm_lock *lp)
-{
-	clear_bit(LFL_AST_WAIT, &lp->flags);
-	smp_mb__after_clear_bit();
-	wake_up_bit(&lp->flags, LFL_AST_WAIT);
-}
-
-static void gdlm_delete_lp(struct gdlm_lock *lp)
-{
-	struct gdlm_ls *ls = lp->ls;
-
-	spin_lock(&ls->async_lock);
-	if (!list_empty(&lp->delay_list))
-		list_del_init(&lp->delay_list);
-	ls->all_locks_count--;
-	spin_unlock(&ls->async_lock);
-
-	kfree(lp);
-}
-
-static void gdlm_queue_delayed(struct gdlm_lock *lp)
-{
-	struct gdlm_ls *ls = lp->ls;
-
-	spin_lock(&ls->async_lock);
-	list_add_tail(&lp->delay_list, &ls->delayed);
-	spin_unlock(&ls->async_lock);
-}
-
-static void process_complete(struct gdlm_lock *lp)
-{
-	struct gdlm_ls *ls = lp->ls;
-	struct lm_async_cb acb;
-
-	memset(&acb, 0, sizeof(acb));
-
-	if (lp->lksb.sb_status == -DLM_ECANCEL) {
-		log_info("complete dlm cancel %x,%llx flags %lx",
-		 	 lp->lockname.ln_type,
-			 (unsigned long long)lp->lockname.ln_number,
-			 lp->flags);
-
-		lp->req = lp->cur;
-		acb.lc_ret |= LM_OUT_CANCELED;
-		if (lp->cur == DLM_LOCK_IV)
-			lp->lksb.sb_lkid = 0;
-		goto out;
-	}
-
-	if (test_and_clear_bit(LFL_DLM_UNLOCK, &lp->flags)) {
-		if (lp->lksb.sb_status != -DLM_EUNLOCK) {
-			log_info("unlock sb_status %d %x,%llx flags %lx",
-				 lp->lksb.sb_status, lp->lockname.ln_type,
-				 (unsigned long long)lp->lockname.ln_number,
-				 lp->flags);
-			return;
-		}
-
-		lp->cur = DLM_LOCK_IV;
-		lp->req = DLM_LOCK_IV;
-		lp->lksb.sb_lkid = 0;
-
-		if (test_and_clear_bit(LFL_UNLOCK_DELETE, &lp->flags)) {
-			gdlm_delete_lp(lp);
-			return;
-		}
-		goto out;
-	}
-
-	if (lp->lksb.sb_flags & DLM_SBF_VALNOTVALID)
-		memset(lp->lksb.sb_lvbptr, 0, GDLM_LVB_SIZE);
-
-	if (lp->lksb.sb_flags & DLM_SBF_ALTMODE) {
-		if (lp->req == DLM_LOCK_PR)
-			lp->req = DLM_LOCK_CW;
-		else if (lp->req == DLM_LOCK_CW)
-			lp->req = DLM_LOCK_PR;
-	}
-
-	/*
-	 * A canceled lock request.  The lock was just taken off the delayed
-	 * list and was never even submitted to dlm.
-	 */
-
-	if (test_and_clear_bit(LFL_CANCEL, &lp->flags)) {
-		log_info("complete internal cancel %x,%llx",
-		 	 lp->lockname.ln_type,
-			 (unsigned long long)lp->lockname.ln_number);
-		lp->req = lp->cur;
-		acb.lc_ret |= LM_OUT_CANCELED;
-		goto out;
-	}
-
-	/*
-	 * An error occured.
-	 */
-
-	if (lp->lksb.sb_status) {
-		/* a "normal" error */
-		if ((lp->lksb.sb_status == -EAGAIN) &&
-		    (lp->lkf & DLM_LKF_NOQUEUE)) {
-			lp->req = lp->cur;
-			if (lp->cur == DLM_LOCK_IV)
-				lp->lksb.sb_lkid = 0;
-			goto out;
-		}
-
-		/* this could only happen with cancels I think */
-		log_info("ast sb_status %d %x,%llx flags %lx",
-			 lp->lksb.sb_status, lp->lockname.ln_type,
-			 (unsigned long long)lp->lockname.ln_number,
-			 lp->flags);
-		return;
-	}
-
-	/*
-	 * This is an AST for an EX->EX conversion for sync_lvb from GFS.
-	 */
-
-	if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) {
-		wake_up_ast(lp);
-		return;
-	}
-
-	/*
-	 * A lock has been demoted to NL because it initially completed during
-	 * BLOCK_LOCKS.  Now it must be requested in the originally requested
-	 * mode.
-	 */
-
-	if (test_and_clear_bit(LFL_REREQUEST, &lp->flags)) {
-		gdlm_assert(lp->req == DLM_LOCK_NL, "%x,%llx",
-			    lp->lockname.ln_type,
-			    (unsigned long long)lp->lockname.ln_number);
-		gdlm_assert(lp->prev_req > DLM_LOCK_NL, "%x,%llx",
-			    lp->lockname.ln_type,
-			    (unsigned long long)lp->lockname.ln_number);
-
-		lp->cur = DLM_LOCK_NL;
-		lp->req = lp->prev_req;
-		lp->prev_req = DLM_LOCK_IV;
-		lp->lkf &= ~DLM_LKF_CONVDEADLK;
-
-		set_bit(LFL_NOCACHE, &lp->flags);
-
-		if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) &&
-		    !test_bit(LFL_NOBLOCK, &lp->flags))
-			gdlm_queue_delayed(lp);
-		else
-			queue_submit(lp);
-		return;
-	}
-
-	/*
-	 * A request is granted during dlm recovery.  It may be granted
-	 * because the locks of a failed node were cleared.  In that case,
-	 * there may be inconsistent data beneath this lock and we must wait
-	 * for recovery to complete to use it.  When gfs recovery is done this
-	 * granted lock will be converted to NL and then reacquired in this
-	 * granted state.
-	 */
-
-	if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) &&
-	    !test_bit(LFL_NOBLOCK, &lp->flags) &&
-	    lp->req != DLM_LOCK_NL) {
-
-		lp->cur = lp->req;
-		lp->prev_req = lp->req;
-		lp->req = DLM_LOCK_NL;
-		lp->lkf |= DLM_LKF_CONVERT;
-		lp->lkf &= ~DLM_LKF_CONVDEADLK;
-
-		log_debug("rereq %x,%llx id %x %d,%d",
-			  lp->lockname.ln_type,
-			  (unsigned long long)lp->lockname.ln_number,
-			  lp->lksb.sb_lkid, lp->cur, lp->req);
-
-		set_bit(LFL_REREQUEST, &lp->flags);
-		queue_submit(lp);
-		return;
-	}
-
-	/*
-	 * DLM demoted the lock to NL before it was granted so GFS must be
-	 * told it cannot cache data for this lock.
-	 */
-
-	if (lp->lksb.sb_flags & DLM_SBF_DEMOTED)
-		set_bit(LFL_NOCACHE, &lp->flags);
-
-out:
-	/*
-	 * This is an internal lock_dlm lock
-	 */
-
-	if (test_bit(LFL_INLOCK, &lp->flags)) {
-		clear_bit(LFL_NOBLOCK, &lp->flags);
-		lp->cur = lp->req;
-		wake_up_ast(lp);
-		return;
-	}
-
-	/*
-	 * Normal completion of a lock request.  Tell GFS it now has the lock.
-	 */
-
-	clear_bit(LFL_NOBLOCK, &lp->flags);
-	lp->cur = lp->req;
-
-	acb.lc_name = lp->lockname;
-	acb.lc_ret |= gdlm_make_lmstate(lp->cur);
-
-	ls->fscb(ls->sdp, LM_CB_ASYNC, &acb);
-}
-
-static void gdlm_ast(void *astarg)
-{
-	struct gdlm_lock *lp = astarg;
-	clear_bit(LFL_ACTIVE, &lp->flags);
-	process_complete(lp);
-}
-
-static void process_blocking(struct gdlm_lock *lp, int bast_mode)
-{
-	struct gdlm_ls *ls = lp->ls;
-	unsigned int cb = 0;
-
-	switch (gdlm_make_lmstate(bast_mode)) {
-	case LM_ST_EXCLUSIVE:
-		cb = LM_CB_NEED_E;
-		break;
-	case LM_ST_DEFERRED:
-		cb = LM_CB_NEED_D;
-		break;
-	case LM_ST_SHARED:
-		cb = LM_CB_NEED_S;
-		break;
-	default:
-		gdlm_assert(0, "unknown bast mode %u", bast_mode);
-	}
-
-	ls->fscb(ls->sdp, cb, &lp->lockname);
-}
-
-
-static void gdlm_bast(void *astarg, int mode)
-{
-	struct gdlm_lock *lp = astarg;
-
-	if (!mode) {
-		printk(KERN_INFO "lock_dlm: bast mode zero %x,%llx\n",
-			lp->lockname.ln_type,
-			(unsigned long long)lp->lockname.ln_number);
-		return;
-	}
-
-	process_blocking(lp, mode);
-}
-
-/* convert gfs lock-state to dlm lock-mode */
-
-static s16 make_mode(s16 lmstate)
-{
-	switch (lmstate) {
-	case LM_ST_UNLOCKED:
-		return DLM_LOCK_NL;
-	case LM_ST_EXCLUSIVE:
-		return DLM_LOCK_EX;
-	case LM_ST_DEFERRED:
-		return DLM_LOCK_CW;
-	case LM_ST_SHARED:
-		return DLM_LOCK_PR;
-	}
-	gdlm_assert(0, "unknown LM state %d", lmstate);
-	return -1;
-}
-
-
-/* verify agreement with GFS on the current lock state, NB: DLM_LOCK_NL and
-   DLM_LOCK_IV are both considered LM_ST_UNLOCKED by GFS. */
-
-static void check_cur_state(struct gdlm_lock *lp, unsigned int cur_state)
-{
-	s16 cur = make_mode(cur_state);
-	if (lp->cur != DLM_LOCK_IV)
-		gdlm_assert(lp->cur == cur, "%d, %d", lp->cur, cur);
-}
-
-static inline unsigned int make_flags(struct gdlm_lock *lp,
-				      unsigned int gfs_flags,
-				      s16 cur, s16 req)
-{
-	unsigned int lkf = 0;
-
-	if (gfs_flags & LM_FLAG_TRY)
-		lkf |= DLM_LKF_NOQUEUE;
-
-	if (gfs_flags & LM_FLAG_TRY_1CB) {
-		lkf |= DLM_LKF_NOQUEUE;
-		lkf |= DLM_LKF_NOQUEUEBAST;
-	}
-
-	if (gfs_flags & LM_FLAG_PRIORITY) {
-		lkf |= DLM_LKF_NOORDER;
-		lkf |= DLM_LKF_HEADQUE;
-	}
-
-	if (gfs_flags & LM_FLAG_ANY) {
-		if (req == DLM_LOCK_PR)
-			lkf |= DLM_LKF_ALTCW;
-		else if (req == DLM_LOCK_CW)
-			lkf |= DLM_LKF_ALTPR;
-	}
-
-	if (lp->lksb.sb_lkid != 0) {
-		lkf |= DLM_LKF_CONVERT;
-	}
-
-	if (lp->lvb)
-		lkf |= DLM_LKF_VALBLK;
-
-	return lkf;
-}
-
-/* make_strname - convert GFS lock numbers to a string */
-
-static inline void make_strname(const struct lm_lockname *lockname,
-				struct gdlm_strname *str)
-{
-	sprintf(str->name, "%8x%16llx", lockname->ln_type,
-		(unsigned long long)lockname->ln_number);
-	str->namelen = GDLM_STRNAME_BYTES;
-}
-
-static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
-			  struct gdlm_lock **lpp)
-{
-	struct gdlm_lock *lp;
-
-	lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS);
-	if (!lp)
-		return -ENOMEM;
-
-	lp->lockname = *name;
-	make_strname(name, &lp->strname);
-	lp->ls = ls;
-	lp->cur = DLM_LOCK_IV;
-	INIT_LIST_HEAD(&lp->delay_list);
-
-	spin_lock(&ls->async_lock);
-	ls->all_locks_count++;
-	spin_unlock(&ls->async_lock);
-
-	*lpp = lp;
-	return 0;
-}
-
-int gdlm_get_lock(void *lockspace, struct lm_lockname *name,
-		  void **lockp)
-{
-	struct gdlm_lock *lp;
-	int error;
-
-	error = gdlm_create_lp(lockspace, name, &lp);
-
-	*lockp = lp;
-	return error;
-}
-
-void gdlm_put_lock(void *lock)
-{
-	gdlm_delete_lp(lock);
-}
-
-unsigned int gdlm_do_lock(struct gdlm_lock *lp)
-{
-	struct gdlm_ls *ls = lp->ls;
-	int error, bast = 1;
-
-	/*
-	 * When recovery is in progress, delay lock requests for submission
-	 * once recovery is done.  Requests for recovery (NOEXP) and unlocks
-	 * can pass.
-	 */
-
-	if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) &&
-	    !test_bit(LFL_NOBLOCK, &lp->flags) && lp->req != DLM_LOCK_NL) {
-		gdlm_queue_delayed(lp);
-		return LM_OUT_ASYNC;
-	}
-
-	/*
-	 * Submit the actual lock request.
-	 */
-
-	if (test_bit(LFL_NOBAST, &lp->flags))
-		bast = 0;
-
-	set_bit(LFL_ACTIVE, &lp->flags);
-
-	log_debug("lk %x,%llx id %x %d,%d %x", lp->lockname.ln_type,
-		  (unsigned long long)lp->lockname.ln_number, lp->lksb.sb_lkid,
-		  lp->cur, lp->req, lp->lkf);
-
-	error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf,
-			 lp->strname.name, lp->strname.namelen, 0, gdlm_ast,
-			 lp, bast ? gdlm_bast : NULL);
-
-	if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) {
-		lp->lksb.sb_status = -EAGAIN;
-		gdlm_ast(lp);
-		error = 0;
-	}
-
-	if (error) {
-		log_error("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x "
-			  "flags=%lx", ls->fsname, lp->lockname.ln_type,
-			  (unsigned long long)lp->lockname.ln_number, error,
-			  lp->cur, lp->req, lp->lkf, lp->flags);
-		return LM_OUT_ERROR;
-	}
-	return LM_OUT_ASYNC;
-}
-
-static unsigned int gdlm_do_unlock(struct gdlm_lock *lp)
-{
-	struct gdlm_ls *ls = lp->ls;
-	unsigned int lkf = 0;
-	int error;
-
-	set_bit(LFL_DLM_UNLOCK, &lp->flags);
-	set_bit(LFL_ACTIVE, &lp->flags);
-
-	if (lp->lvb)
-		lkf = DLM_LKF_VALBLK;
-
-	log_debug("un %x,%llx %x %d %x", lp->lockname.ln_type,
-		  (unsigned long long)lp->lockname.ln_number,
-		  lp->lksb.sb_lkid, lp->cur, lkf);
-
-	error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, lkf, NULL, lp);
-
-	if (error) {
-		log_error("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x "
-			  "flags=%lx", ls->fsname, lp->lockname.ln_type,
-			  (unsigned long long)lp->lockname.ln_number, error,
-			  lp->cur, lp->req, lp->lkf, lp->flags);
-		return LM_OUT_ERROR;
-	}
-	return LM_OUT_ASYNC;
-}
-
-unsigned int gdlm_lock(void *lock, unsigned int cur_state,
-		       unsigned int req_state, unsigned int flags)
-{
-	struct gdlm_lock *lp = lock;
-
-	if (req_state == LM_ST_UNLOCKED)
-		return gdlm_unlock(lock, cur_state);
-
-	if (req_state == LM_ST_UNLOCKED)
-		return gdlm_unlock(lock, cur_state);
-
-	clear_bit(LFL_DLM_CANCEL, &lp->flags);
-	if (flags & LM_FLAG_NOEXP)
-		set_bit(LFL_NOBLOCK, &lp->flags);
-
-	check_cur_state(lp, cur_state);
-	lp->req = make_mode(req_state);
-	lp->lkf = make_flags(lp, flags, lp->cur, lp->req);
-
-	return gdlm_do_lock(lp);
-}
-
-unsigned int gdlm_unlock(void *lock, unsigned int cur_state)
-{
-	struct gdlm_lock *lp = lock;
-
-	clear_bit(LFL_DLM_CANCEL, &lp->flags);
-	if (lp->cur == DLM_LOCK_IV)
-		return 0;
-	return gdlm_do_unlock(lp);
-}
-
-void gdlm_cancel(void *lock)
-{
-	struct gdlm_lock *lp = lock;
-	struct gdlm_ls *ls = lp->ls;
-	int error, delay_list = 0;
-
-	if (test_bit(LFL_DLM_CANCEL, &lp->flags))
-		return;
-
-	log_info("gdlm_cancel %x,%llx flags %lx", lp->lockname.ln_type,
-		 (unsigned long long)lp->lockname.ln_number, lp->flags);
-
-	spin_lock(&ls->async_lock);
-	if (!list_empty(&lp->delay_list)) {
-		list_del_init(&lp->delay_list);
-		delay_list = 1;
-	}
-	spin_unlock(&ls->async_lock);
-
-	if (delay_list) {
-		set_bit(LFL_CANCEL, &lp->flags);
-		set_bit(LFL_ACTIVE, &lp->flags);
-		gdlm_ast(lp);
-		return;
-	}
-
-	if (!test_bit(LFL_ACTIVE, &lp->flags) ||
-	    test_bit(LFL_DLM_UNLOCK, &lp->flags)) {
-		log_info("gdlm_cancel skip %x,%llx flags %lx",
-		 	 lp->lockname.ln_type,
-			 (unsigned long long)lp->lockname.ln_number, lp->flags);
-		return;
-	}
-
-	/* the lock is blocked in the dlm */
-
-	set_bit(LFL_DLM_CANCEL, &lp->flags);
-	set_bit(LFL_ACTIVE, &lp->flags);
-
-	error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, DLM_LKF_CANCEL,
-			   NULL, lp);
-
-	log_info("gdlm_cancel rv %d %x,%llx flags %lx", error,
-		 lp->lockname.ln_type,
-		 (unsigned long long)lp->lockname.ln_number, lp->flags);
-
-	if (error == -EBUSY)
-		clear_bit(LFL_DLM_CANCEL, &lp->flags);
-}
-
-static int gdlm_add_lvb(struct gdlm_lock *lp)
-{
-	char *lvb;
-
-	lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
-	if (!lvb)
-		return -ENOMEM;
-
-	lp->lksb.sb_lvbptr = lvb;
-	lp->lvb = lvb;
-	return 0;
-}
-
-static void gdlm_del_lvb(struct gdlm_lock *lp)
-{
-	kfree(lp->lvb);
-	lp->lvb = NULL;
-	lp->lksb.sb_lvbptr = NULL;
-}
-
-static int gdlm_ast_wait(void *word)
-{
-	schedule();
-	return 0;
-}
-
-/* This can do a synchronous dlm request (requiring a lock_dlm thread to get
-   the completion) because gfs won't call hold_lvb() during a callback (from
-   the context of a lock_dlm thread). */
-
-static int hold_null_lock(struct gdlm_lock *lp)
-{
-	struct gdlm_lock *lpn = NULL;
-	int error;
-
-	if (lp->hold_null) {
-		printk(KERN_INFO "lock_dlm: lvb already held\n");
-		return 0;
-	}
-
-	error = gdlm_create_lp(lp->ls, &lp->lockname, &lpn);
-	if (error)
-		goto out;
-
-	lpn->lksb.sb_lvbptr = junk_lvb;
-	lpn->lvb = junk_lvb;
-
-	lpn->req = DLM_LOCK_NL;
-	lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE;
-	set_bit(LFL_NOBAST, &lpn->flags);
-	set_bit(LFL_INLOCK, &lpn->flags);
-	set_bit(LFL_AST_WAIT, &lpn->flags);
-
-	gdlm_do_lock(lpn);
-	wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE);
-	error = lpn->lksb.sb_status;
-	if (error) {
-		printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n",
-		       error);
-		gdlm_delete_lp(lpn);
-		lpn = NULL;
-	}
-out:
-	lp->hold_null = lpn;
-	return error;
-}
-
-/* This cannot do a synchronous dlm request (requiring a lock_dlm thread to get
-   the completion) because gfs may call unhold_lvb() during a callback (from
-   the context of a lock_dlm thread) which could cause a deadlock since the
-   other lock_dlm thread could be engaged in recovery. */
-
-static void unhold_null_lock(struct gdlm_lock *lp)
-{
-	struct gdlm_lock *lpn = lp->hold_null;
-
-	gdlm_assert(lpn, "%x,%llx", lp->lockname.ln_type,
-		    (unsigned long long)lp->lockname.ln_number);
-	lpn->lksb.sb_lvbptr = NULL;
-	lpn->lvb = NULL;
-	set_bit(LFL_UNLOCK_DELETE, &lpn->flags);
-	gdlm_do_unlock(lpn);
-	lp->hold_null = NULL;
-}
-
-/* Acquire a NL lock because gfs requires the value block to remain
-   intact on the resource while the lvb is "held" even if it's holding no locks
-   on the resource. */
-
-int gdlm_hold_lvb(void *lock, char **lvbp)
-{
-	struct gdlm_lock *lp = lock;
-	int error;
-
-	error = gdlm_add_lvb(lp);
-	if (error)
-		return error;
-
-	*lvbp = lp->lvb;
-
-	error = hold_null_lock(lp);
-	if (error)
-		gdlm_del_lvb(lp);
-
-	return error;
-}
-
-void gdlm_unhold_lvb(void *lock, char *lvb)
-{
-	struct gdlm_lock *lp = lock;
-
-	unhold_null_lock(lp);
-	gdlm_del_lvb(lp);
-}
-
-void gdlm_submit_delayed(struct gdlm_ls *ls)
-{
-	struct gdlm_lock *lp, *safe;
-
-	spin_lock(&ls->async_lock);
-	list_for_each_entry_safe(lp, safe, &ls->delayed, delay_list) {
-		list_del_init(&lp->delay_list);
-		list_add_tail(&lp->delay_list, &ls->submit);
-	}
-	spin_unlock(&ls->async_lock);
-	wake_up(&ls->thread_wait);
-}
-
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h
deleted file mode 100644
index 3c98e7c..0000000
--- a/fs/gfs2/locking/dlm/lock_dlm.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-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.
- */
-
-#ifndef LOCK_DLM_DOT_H
-#define LOCK_DLM_DOT_H
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/list.h>
-#include <linux/socket.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/kobject.h>
-#include <linux/fcntl.h>
-#include <linux/wait.h>
-#include <net/sock.h>
-
-#include <linux/dlm.h>
-#include <linux/dlm_plock.h>
-#include <linux/lm_interface.h>
-
-/*
- * Internally, we prefix things with gdlm_ and GDLM_ (for gfs-dlm) since a
- * prefix of lock_dlm_ gets awkward.  Externally, GFS refers to this module
- * as "lock_dlm".
- */
-
-#define GDLM_STRNAME_BYTES	24
-#define GDLM_LVB_SIZE		32
-#define GDLM_DROP_COUNT		0
-#define GDLM_DROP_PERIOD	60
-#define GDLM_NAME_LEN		128
-
-/* GFS uses 12 bytes to identify a resource (32 bit type + 64 bit number).
-   We sprintf these numbers into a 24 byte string of hex values to make them
-   human-readable (to make debugging simpler.) */
-
-struct gdlm_strname {
-	unsigned char		name[GDLM_STRNAME_BYTES];
-	unsigned short		namelen;
-};
-
-enum {
-	DFL_BLOCK_LOCKS		= 0,
-	DFL_SPECTATOR		= 1,
-	DFL_WITHDRAW		= 2,
-};
-
-struct gdlm_ls {
-	u32		id;
-	int			jid;
-	int			first;
-	int			first_done;
-	unsigned long		flags;
-	struct kobject		kobj;
-	char			clustername[GDLM_NAME_LEN];
-	char			fsname[GDLM_NAME_LEN];
-	int			fsflags;
-	dlm_lockspace_t		*dlm_lockspace;
-	lm_callback_t		fscb;
-	struct gfs2_sbd		*sdp;
-	int			recover_jid;
-	int			recover_jid_done;
-	int			recover_jid_status;
-	spinlock_t		async_lock;
-	struct list_head	delayed;
-	struct list_head	submit;
-	u32		all_locks_count;
-	wait_queue_head_t	wait_control;
-	struct task_struct	*thread;
-	wait_queue_head_t	thread_wait;
-};
-
-enum {
-	LFL_NOBLOCK		= 0,
-	LFL_NOCACHE		= 1,
-	LFL_DLM_UNLOCK		= 2,
-	LFL_DLM_CANCEL		= 3,
-	LFL_SYNC_LVB		= 4,
-	LFL_FORCE_PROMOTE	= 5,
-	LFL_REREQUEST		= 6,
-	LFL_ACTIVE		= 7,
-	LFL_INLOCK		= 8,
-	LFL_CANCEL		= 9,
-	LFL_NOBAST		= 10,
-	LFL_HEADQUE		= 11,
-	LFL_UNLOCK_DELETE	= 12,
-	LFL_AST_WAIT		= 13,
-};
-
-struct gdlm_lock {
-	struct gdlm_ls		*ls;
-	struct lm_lockname	lockname;
-	struct gdlm_strname	strname;
-	char			*lvb;
-	struct dlm_lksb		lksb;
-
-	s16			cur;
-	s16			req;
-	s16			prev_req;
-	u32			lkf;		/* dlm flags DLM_LKF_ */
-	unsigned long		flags;		/* lock_dlm flags LFL_ */
-
-	struct list_head	delay_list;	/* delayed */
-	struct gdlm_lock	*hold_null;	/* NL lock for hold_lvb */
-};
-
-#define gdlm_assert(assertion, fmt, args...)                                  \
-do {                                                                          \
-	if (unlikely(!(assertion))) {                                         \
-		printk(KERN_EMERG "lock_dlm: fatal assertion failed \"%s\"\n" \
-				  "lock_dlm:  " fmt "\n",                     \
-				  #assertion, ##args);                        \
-		BUG();                                                        \
-	}                                                                     \
-} while (0)
-
-#define log_print(lev, fmt, arg...) printk(lev "lock_dlm: " fmt "\n" , ## arg)
-#define log_info(fmt, arg...)  log_print(KERN_INFO , fmt , ## arg)
-#define log_error(fmt, arg...) log_print(KERN_ERR , fmt , ## arg)
-#ifdef LOCK_DLM_LOG_DEBUG
-#define log_debug(fmt, arg...) log_print(KERN_DEBUG , fmt , ## arg)
-#else
-#define log_debug(fmt, arg...)
-#endif
-
-/* sysfs.c */
-
-int gdlm_sysfs_init(void);
-void gdlm_sysfs_exit(void);
-int gdlm_kobject_setup(struct gdlm_ls *, struct kobject *);
-void gdlm_kobject_release(struct gdlm_ls *);
-
-/* thread.c */
-
-int gdlm_init_threads(struct gdlm_ls *);
-void gdlm_release_threads(struct gdlm_ls *);
-
-/* lock.c */
-
-void gdlm_submit_delayed(struct gdlm_ls *);
-unsigned int gdlm_do_lock(struct gdlm_lock *);
-
-int gdlm_get_lock(void *, struct lm_lockname *, void **);
-void gdlm_put_lock(void *);
-unsigned int gdlm_lock(void *, unsigned int, unsigned int, unsigned int);
-unsigned int gdlm_unlock(void *, unsigned int);
-void gdlm_cancel(void *);
-int gdlm_hold_lvb(void *, char **);
-void gdlm_unhold_lvb(void *, char *);
-
-/* mount.c */
-
-extern const struct lm_lockops gdlm_ops;
-
-#endif
-
diff --git a/fs/gfs2/locking/dlm/main.c b/fs/gfs2/locking/dlm/main.c
deleted file mode 100644
index b9a03a7..0000000
--- a/fs/gfs2/locking/dlm/main.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-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/init.h>
-
-#include "lock_dlm.h"
-
-static int __init init_lock_dlm(void)
-{
-	int error;
-
-	error = gfs2_register_lockproto(&gdlm_ops);
-	if (error) {
-		printk(KERN_WARNING "lock_dlm:  can't register protocol: %d\n",
-		       error);
-		return error;
-	}
-
-	error = gdlm_sysfs_init();
-	if (error) {
-		gfs2_unregister_lockproto(&gdlm_ops);
-		return error;
-	}
-
-	printk(KERN_INFO
-	       "Lock_DLM (built %s %s) installed\n", __DATE__, __TIME__);
-	return 0;
-}
-
-static void __exit exit_lock_dlm(void)
-{
-	gdlm_sysfs_exit();
-	gfs2_unregister_lockproto(&gdlm_ops);
-}
-
-module_init(init_lock_dlm);
-module_exit(exit_lock_dlm);
-
-MODULE_DESCRIPTION("GFS DLM Locking Module");
-MODULE_AUTHOR("Red Hat, Inc.");
-MODULE_LICENSE("GPL");
-
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
deleted file mode 100644
index 1aa7eb6..0000000
--- a/fs/gfs2/locking/dlm/mount.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-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 "lock_dlm.h"
-
-const struct lm_lockops gdlm_ops;
-
-
-static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs2_sbd *sdp,
-				 int flags, char *table_name)
-{
-	struct gdlm_ls *ls;
-	char buf[256], *p;
-
-	ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL);
-	if (!ls)
-		return NULL;
-
-	ls->fscb = cb;
-	ls->sdp = sdp;
-	ls->fsflags = flags;
-	spin_lock_init(&ls->async_lock);
-	INIT_LIST_HEAD(&ls->delayed);
-	INIT_LIST_HEAD(&ls->submit);
-	init_waitqueue_head(&ls->thread_wait);
-	init_waitqueue_head(&ls->wait_control);
-	ls->jid = -1;
-
-	strncpy(buf, table_name, 256);
-	buf[255] = '\0';
-
-	p = strchr(buf, ':');
-	if (!p) {
-		log_info("invalid table_name \"%s\"", table_name);
-		kfree(ls);
-		return NULL;
-	}
-	*p = '\0';
-	p++;
-
-	strncpy(ls->clustername, buf, GDLM_NAME_LEN);
-	strncpy(ls->fsname, p, GDLM_NAME_LEN);
-
-	return ls;
-}
-
-static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
-{
-	char data[256];
-	char *options, *x, *y;
-	int error = 0;
-
-	memset(data, 0, 256);
-	strncpy(data, data_arg, 255);
-
-	if (!strlen(data)) {
-		log_error("no mount options, (u)mount helpers not installed");
-		return -EINVAL;
-	}
-
-	for (options = data; (x = strsep(&options, ":")); ) {
-		if (!*x)
-			continue;
-
-		y = strchr(x, '=');
-		if (y)
-			*y++ = 0;
-
-		if (!strcmp(x, "jid")) {
-			if (!y) {
-				log_error("need argument to jid");
-				error = -EINVAL;
-				break;
-			}
-			sscanf(y, "%u", &ls->jid);
-
-		} else if (!strcmp(x, "first")) {
-			if (!y) {
-				log_error("need argument to first");
-				error = -EINVAL;
-				break;
-			}
-			sscanf(y, "%u", &ls->first);
-
-		} else if (!strcmp(x, "id")) {
-			if (!y) {
-				log_error("need argument to id");
-				error = -EINVAL;
-				break;
-			}
-			sscanf(y, "%u", &ls->id);
-
-		} else if (!strcmp(x, "nodir")) {
-			if (!y) {
-				log_error("need argument to nodir");
-				error = -EINVAL;
-				break;
-			}
-			sscanf(y, "%u", nodir);
-
-		} else {
-			log_error("unkonwn option: %s", x);
-			error = -EINVAL;
-			break;
-		}
-	}
-
-	return error;
-}
-
-static int gdlm_mount(char *table_name, char *host_data,
-			lm_callback_t cb, void *cb_data,
-			unsigned int min_lvb_size, int flags,
-			struct lm_lockstruct *lockstruct,
-			struct kobject *fskobj)
-{
-	struct gdlm_ls *ls;
-	int error = -ENOMEM, nodir = 0;
-
-	if (min_lvb_size > GDLM_LVB_SIZE)
-		goto out;
-
-	ls = init_gdlm(cb, cb_data, flags, table_name);
-	if (!ls)
-		goto out;
-
-	error = make_args(ls, host_data, &nodir);
-	if (error)
-		goto out;
-
-	error = gdlm_init_threads(ls);
-	if (error)
-		goto out_free;
-
-	error = gdlm_kobject_setup(ls, fskobj);
-	if (error)
-		goto out_thread;
-
-	error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
-				  &ls->dlm_lockspace,
-				  DLM_LSFL_FS | DLM_LSFL_NEWEXCL |
-				  (nodir ? DLM_LSFL_NODIR : 0),
-				  GDLM_LVB_SIZE);
-	if (error) {
-		log_error("dlm_new_lockspace error %d", error);
-		goto out_kobj;
-	}
-
-	lockstruct->ls_jid = ls->jid;
-	lockstruct->ls_first = ls->first;
-	lockstruct->ls_lockspace = ls;
-	lockstruct->ls_ops = &gdlm_ops;
-	lockstruct->ls_flags = 0;
-	lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
-	return 0;
-
-out_kobj:
-	gdlm_kobject_release(ls);
-out_thread:
-	gdlm_release_threads(ls);
-out_free:
-	kfree(ls);
-out:
-	return error;
-}
-
-static void gdlm_unmount(void *lockspace)
-{
-	struct gdlm_ls *ls = lockspace;
-
-	log_debug("unmount flags %lx", ls->flags);
-
-	/* FIXME: serialize unmount and withdraw in case they
-	   happen at once.  Also, if unmount follows withdraw,
-	   wait for withdraw to finish. */
-
-	if (test_bit(DFL_WITHDRAW, &ls->flags))
-		goto out;
-
-	gdlm_kobject_release(ls);
-	dlm_release_lockspace(ls->dlm_lockspace, 2);
-	gdlm_release_threads(ls);
-	BUG_ON(ls->all_locks_count);
-out:
-	kfree(ls);
-}
-
-static void gdlm_recovery_done(void *lockspace, unsigned int jid,
-                               unsigned int message)
-{
-	char env_jid[20];
-	char env_status[20];
-	char *envp[] = { env_jid, env_status, NULL };
-	struct gdlm_ls *ls = lockspace;
-	ls->recover_jid_done = jid;
-	ls->recover_jid_status = message;
-	sprintf(env_jid, "JID=%d", jid);
-	sprintf(env_status, "RECOVERY=%s",
-		message == LM_RD_SUCCESS ? "Done" : "Failed");
-	kobject_uevent_env(&ls->kobj, KOBJ_CHANGE, envp);
-}
-
-static void gdlm_others_may_mount(void *lockspace)
-{
-	char *message = "FIRSTMOUNT=Done";
-	char *envp[] = { message, NULL };
-	struct gdlm_ls *ls = lockspace;
-	ls->first_done = 1;
-	kobject_uevent_env(&ls->kobj, KOBJ_CHANGE, envp);
-}
-
-/* Userspace gets the offline uevent, blocks new gfs locks on
-   other mounters, and lets us know (sets WITHDRAW flag).  Then,
-   userspace leaves the mount group while we leave the lockspace. */
-
-static void gdlm_withdraw(void *lockspace)
-{
-	struct gdlm_ls *ls = lockspace;
-
-	kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
-
-	wait_event_interruptible(ls->wait_control,
-				 test_bit(DFL_WITHDRAW, &ls->flags));
-
-	dlm_release_lockspace(ls->dlm_lockspace, 2);
-	gdlm_release_threads(ls);
-	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,
-	.lm_others_may_mount = gdlm_others_may_mount,
-	.lm_unmount = gdlm_unmount,
-	.lm_withdraw = gdlm_withdraw,
-	.lm_get_lock = gdlm_get_lock,
-	.lm_put_lock = gdlm_put_lock,
-	.lm_lock = gdlm_lock,
-	.lm_unlock = gdlm_unlock,
-	.lm_plock = gdlm_plock,
-	.lm_punlock = gdlm_punlock,
-	.lm_plock_get = gdlm_plock_get,
-	.lm_cancel = gdlm_cancel,
-	.lm_hold_lvb = gdlm_hold_lvb,
-	.lm_unhold_lvb = gdlm_unhold_lvb,
-	.lm_recovery_done = gdlm_recovery_done,
-	.lm_owner = THIS_MODULE,
-};
-
diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c
deleted file mode 100644
index 9b7edcf..0000000
--- a/fs/gfs2/locking/dlm/sysfs.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-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/ctype.h>
-#include <linux/stat.h>
-
-#include "lock_dlm.h"
-
-static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf)
-{
-	return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name);
-}
-
-static ssize_t block_show(struct gdlm_ls *ls, char *buf)
-{
-	ssize_t ret;
-	int val = 0;
-
-	if (test_bit(DFL_BLOCK_LOCKS, &ls->flags))
-		val = 1;
-	ret = sprintf(buf, "%d\n", val);
-	return ret;
-}
-
-static ssize_t block_store(struct gdlm_ls *ls, const char *buf, size_t len)
-{
-	ssize_t ret = len;
-	int val;
-
-	val = simple_strtol(buf, NULL, 0);
-
-	if (val == 1)
-		set_bit(DFL_BLOCK_LOCKS, &ls->flags);
-	else if (val == 0) {
-		clear_bit(DFL_BLOCK_LOCKS, &ls->flags);
-		gdlm_submit_delayed(ls);
-	} else {
-		ret = -EINVAL;
-	}
-	return ret;
-}
-
-static ssize_t withdraw_show(struct gdlm_ls *ls, char *buf)
-{
-	ssize_t ret;
-	int val = 0;
-
-	if (test_bit(DFL_WITHDRAW, &ls->flags))
-		val = 1;
-	ret = sprintf(buf, "%d\n", val);
-	return ret;
-}
-
-static ssize_t withdraw_store(struct gdlm_ls *ls, const char *buf, size_t len)
-{
-	ssize_t ret = len;
-	int val;
-
-	val = simple_strtol(buf, NULL, 0);
-
-	if (val == 1)
-		set_bit(DFL_WITHDRAW, &ls->flags);
-	else
-		ret = -EINVAL;
-	wake_up(&ls->wait_control);
-	return ret;
-}
-
-static ssize_t id_show(struct gdlm_ls *ls, char *buf)
-{
-	return sprintf(buf, "%u\n", ls->id);
-}
-
-static ssize_t jid_show(struct gdlm_ls *ls, char *buf)
-{
-	return sprintf(buf, "%d\n", ls->jid);
-}
-
-static ssize_t first_show(struct gdlm_ls *ls, char *buf)
-{
-	return sprintf(buf, "%d\n", ls->first);
-}
-
-static ssize_t first_done_show(struct gdlm_ls *ls, char *buf)
-{
-	return sprintf(buf, "%d\n", ls->first_done);
-}
-
-static ssize_t recover_show(struct gdlm_ls *ls, char *buf)
-{
-	return sprintf(buf, "%d\n", ls->recover_jid);
-}
-
-static ssize_t recover_store(struct gdlm_ls *ls, const char *buf, size_t len)
-{
-	ls->recover_jid = simple_strtol(buf, NULL, 0);
-	ls->fscb(ls->sdp, LM_CB_NEED_RECOVERY, &ls->recover_jid);
-	return len;
-}
-
-static ssize_t recover_done_show(struct gdlm_ls *ls, char *buf)
-{
-	return sprintf(buf, "%d\n", ls->recover_jid_done);
-}
-
-static ssize_t recover_status_show(struct gdlm_ls *ls, char *buf)
-{
-	return sprintf(buf, "%d\n", ls->recover_jid_status);
-}
-
-struct gdlm_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct gdlm_ls *, char *);
-	ssize_t (*store)(struct gdlm_ls *, const char *, size_t);
-};
-
-#define GDLM_ATTR(_name,_mode,_show,_store) \
-static struct gdlm_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store)
-
-GDLM_ATTR(proto_name,     0444, proto_name_show,     NULL);
-GDLM_ATTR(block,          0644, block_show,          block_store);
-GDLM_ATTR(withdraw,       0644, withdraw_show,       withdraw_store);
-GDLM_ATTR(id,             0444, id_show,             NULL);
-GDLM_ATTR(jid,            0444, jid_show,            NULL);
-GDLM_ATTR(first,          0444, first_show,          NULL);
-GDLM_ATTR(first_done,     0444, first_done_show,     NULL);
-GDLM_ATTR(recover,        0644, recover_show,        recover_store);
-GDLM_ATTR(recover_done,   0444, recover_done_show,   NULL);
-GDLM_ATTR(recover_status, 0444, recover_status_show, NULL);
-
-static struct attribute *gdlm_attrs[] = {
-	&gdlm_attr_proto_name.attr,
-	&gdlm_attr_block.attr,
-	&gdlm_attr_withdraw.attr,
-	&gdlm_attr_id.attr,
-	&gdlm_attr_jid.attr,
-	&gdlm_attr_first.attr,
-	&gdlm_attr_first_done.attr,
-	&gdlm_attr_recover.attr,
-	&gdlm_attr_recover_done.attr,
-	&gdlm_attr_recover_status.attr,
-	NULL,
-};
-
-static ssize_t gdlm_attr_show(struct kobject *kobj, struct attribute *attr,
-			      char *buf)
-{
-	struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj);
-	struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr);
-	return a->show ? a->show(ls, buf) : 0;
-}
-
-static ssize_t gdlm_attr_store(struct kobject *kobj, struct attribute *attr,
-			       const char *buf, size_t len)
-{
-	struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj);
-	struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr);
-	return a->store ? a->store(ls, buf, len) : len;
-}
-
-static struct sysfs_ops gdlm_attr_ops = {
-	.show  = gdlm_attr_show,
-	.store = gdlm_attr_store,
-};
-
-static struct kobj_type gdlm_ktype = {
-	.default_attrs = gdlm_attrs,
-	.sysfs_ops     = &gdlm_attr_ops,
-};
-
-static struct kset *gdlm_kset;
-
-int gdlm_kobject_setup(struct gdlm_ls *ls, struct kobject *fskobj)
-{
-	int error;
-
-	ls->kobj.kset = gdlm_kset;
-	error = kobject_init_and_add(&ls->kobj, &gdlm_ktype, fskobj,
-				     "lock_module");
-	if (error)
-		log_error("can't register kobj %d", error);
-	kobject_uevent(&ls->kobj, KOBJ_ADD);
-
-	return error;
-}
-
-void gdlm_kobject_release(struct gdlm_ls *ls)
-{
-	kobject_put(&ls->kobj);
-}
-
-static int gdlm_uevent(struct kset *kset, struct kobject *kobj,
-		       struct kobj_uevent_env *env)
-{
-        struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj);
-        add_uevent_var(env, "LOCKTABLE=%s:%s", ls->clustername, ls->fsname);
-        add_uevent_var(env, "LOCKPROTO=lock_dlm");
-        return 0;
-}
-
-static struct kset_uevent_ops gdlm_uevent_ops = {
-	.uevent = gdlm_uevent,
-};
-
-
-int gdlm_sysfs_init(void)
-{
-	gdlm_kset = kset_create_and_add("lock_dlm", &gdlm_uevent_ops, kernel_kobj);
-	if (!gdlm_kset) {
-		printk(KERN_WARNING "%s: can not create kset\n", __func__);
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-void gdlm_sysfs_exit(void)
-{
-	kset_unregister(gdlm_kset);
-}
-
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c
deleted file mode 100644
index 38823ef..0000000
--- a/fs/gfs2/locking/dlm/thread.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-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 "lock_dlm.h"
-
-static inline int no_work(struct gdlm_ls *ls)
-{
-	int ret;
-
-	spin_lock(&ls->async_lock);
-	ret = list_empty(&ls->submit);
-	spin_unlock(&ls->async_lock);
-
-	return ret;
-}
-
-static int gdlm_thread(void *data)
-{
-	struct gdlm_ls *ls = (struct gdlm_ls *) data;
-	struct gdlm_lock *lp = NULL;
-
-	while (!kthread_should_stop()) {
-		wait_event_interruptible(ls->thread_wait,
-				!no_work(ls) || kthread_should_stop());
-
-		spin_lock(&ls->async_lock);
-
-		if (!list_empty(&ls->submit)) {
-			lp = list_entry(ls->submit.next, struct gdlm_lock,
-					delay_list);
-			list_del_init(&lp->delay_list);
-			spin_unlock(&ls->async_lock);
-			gdlm_do_lock(lp);
-			spin_lock(&ls->async_lock);
-		}
-		spin_unlock(&ls->async_lock);
-	}
-
-	return 0;
-}
-
-int gdlm_init_threads(struct gdlm_ls *ls)
-{
-	struct task_struct *p;
-	int error;
-
-	p = kthread_run(gdlm_thread, ls, "lock_dlm");
-	error = IS_ERR(p);
-	if (error) {
-		log_error("can't start lock_dlm thread %d", error);
-		return error;
-	}
-	ls->thread = p;
-
-	return 0;
-}
-
-void gdlm_release_threads(struct gdlm_ls *ls)
-{
-	kthread_stop(ls->thread);
-}
-
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index ad30585..98918a7 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -14,7 +14,6 @@
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 4390f6f..80e4f5f 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -13,7 +13,6 @@
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 
 #include "gfs2.h"
 #include "incore.h"
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index 7cacfde..a6892ed 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <asm/atomic.h>
 
 #include "gfs2.h"
@@ -23,6 +22,12 @@
 #include "sys.h"
 #include "util.h"
 #include "glock.h"
+#include "quota.h"
+
+static struct shrinker qd_shrinker = {
+	.shrink = gfs2_shrink_qd_memory,
+	.seeks = DEFAULT_SEEKS,
+};
 
 static void gfs2_init_inode_once(void *foo)
 {
@@ -41,8 +46,6 @@
 	INIT_HLIST_NODE(&gl->gl_list);
 	spin_lock_init(&gl->gl_spin);
 	INIT_LIST_HEAD(&gl->gl_holders);
-	gl->gl_lvb = NULL;
-	atomic_set(&gl->gl_lvb_count, 0);
 	INIT_LIST_HEAD(&gl->gl_lru);
 	INIT_LIST_HEAD(&gl->gl_ail_list);
 	atomic_set(&gl->gl_ail_count, 0);
@@ -100,6 +103,8 @@
 	if (!gfs2_quotad_cachep)
 		goto fail;
 
+	register_shrinker(&qd_shrinker);
+
 	error = register_filesystem(&gfs2_fs_type);
 	if (error)
 		goto fail;
@@ -117,6 +122,7 @@
 fail_unregister:
 	unregister_filesystem(&gfs2_fs_type);
 fail:
+	unregister_shrinker(&qd_shrinker);
 	gfs2_glock_exit();
 
 	if (gfs2_quotad_cachep)
@@ -145,6 +151,7 @@
 
 static void __exit exit_gfs2_fs(void)
 {
+	unregister_shrinker(&qd_shrinker);
 	gfs2_glock_exit();
 	gfs2_unregister_debugfs();
 	unregister_filesystem(&gfs2_fs_type);
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 0985362..8d6f132 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -19,7 +19,6 @@
 #include <linux/delay.h>
 #include <linux/bio.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -90,27 +89,6 @@
 }
 
 /**
- * gfs2_meta_inval - Invalidate all buffers associated with a glock
- * @gl: the glock
- *
- */
-
-void gfs2_meta_inval(struct gfs2_glock *gl)
-{
-	struct gfs2_sbd *sdp = gl->gl_sbd;
-	struct inode *aspace = gl->gl_aspace;
-	struct address_space *mapping = gl->gl_aspace->i_mapping;
-
-	gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count));
-
-	atomic_inc(&aspace->i_writecount);
-	truncate_inode_pages(mapping, 0);
-	atomic_dec(&aspace->i_writecount);
-
-	gfs2_assert_withdraw(sdp, !mapping->nrpages);
-}
-
-/**
  * gfs2_meta_sync - Sync all buffers associated with a glock
  * @gl: The glock
  *
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index b1a5f36..de270c2 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -40,7 +40,6 @@
 struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp);
 void gfs2_aspace_put(struct inode *aspace);
 
-void gfs2_meta_inval(struct gfs2_glock *gl);
 void gfs2_meta_sync(struct gfs2_glock *gl);
 
 struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno);
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c
index 3cb0a44..f7e8527 100644
--- a/fs/gfs2/mount.c
+++ b/fs/gfs2/mount.c
@@ -12,12 +12,11 @@
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <linux/parser.h>
 
 #include "gfs2.h"
 #include "incore.h"
-#include "mount.h"
+#include "super.h"
 #include "sys.h"
 #include "util.h"
 
@@ -37,11 +36,15 @@
 	Opt_quota_off,
 	Opt_quota_account,
 	Opt_quota_on,
+	Opt_quota,
+	Opt_noquota,
 	Opt_suiddir,
 	Opt_nosuiddir,
 	Opt_data_writeback,
 	Opt_data_ordered,
 	Opt_meta,
+	Opt_discard,
+	Opt_nodiscard,
 	Opt_err,
 };
 
@@ -61,11 +64,15 @@
 	{Opt_quota_off, "quota=off"},
 	{Opt_quota_account, "quota=account"},
 	{Opt_quota_on, "quota=on"},
+	{Opt_quota, "quota"},
+	{Opt_noquota, "noquota"},
 	{Opt_suiddir, "suiddir"},
 	{Opt_nosuiddir, "nosuiddir"},
 	{Opt_data_writeback, "data=writeback"},
 	{Opt_data_ordered, "data=ordered"},
 	{Opt_meta, "meta"},
+	{Opt_discard, "discard"},
+	{Opt_nodiscard, "nodiscard"},
 	{Opt_err, NULL}
 };
 
@@ -77,101 +84,46 @@
  * Return: errno
  */
 
-int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
+int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options)
 {
-	struct gfs2_args *args = &sdp->sd_args;
-	char *data = data_arg;
-	char *options, *o, *v;
-	int error = 0;
-
-	if (!remount) {
-		/*  Set some defaults  */
-		args->ar_quota = GFS2_QUOTA_DEFAULT;
-		args->ar_data = GFS2_DATA_DEFAULT;
-	}
+	char *o;
+	int token;
+	substring_t tmp[MAX_OPT_ARGS];
 
 	/* Split the options into tokens with the "," character and
 	   process them */
 
-	for (options = data; (o = strsep(&options, ",")); ) {
-		int token;
-		substring_t tmp[MAX_OPT_ARGS];
-
-		if (!*o)
+	while (1) {
+		o = strsep(&options, ",");
+		if (o == NULL)
+			break;
+		if (*o == '\0')
 			continue;
 
 		token = match_token(o, tokens, tmp);
 		switch (token) {
 		case Opt_lockproto:
-			v = match_strdup(&tmp[0]);
-			if (!v) {
-				fs_info(sdp, "no memory for lockproto\n");
-				error = -ENOMEM;
-				goto out_error;
-			}
-
-			if (remount && strcmp(v, args->ar_lockproto)) {
-				kfree(v);
-				goto cant_remount;
-			}
-			
-			strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN);
-			args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0;
-			kfree(v);
+			match_strlcpy(args->ar_lockproto, &tmp[0],
+				      GFS2_LOCKNAME_LEN);
 			break;
 		case Opt_locktable:
-			v = match_strdup(&tmp[0]);
-			if (!v) {
-				fs_info(sdp, "no memory for locktable\n");
-				error = -ENOMEM;
-				goto out_error;
-			}
-
-			if (remount && strcmp(v, args->ar_locktable)) {
-				kfree(v);
-				goto cant_remount;
-			}
-
-			strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN);
-			args->ar_locktable[GFS2_LOCKNAME_LEN - 1]  = 0;
-			kfree(v);
+			match_strlcpy(args->ar_locktable, &tmp[0],
+				      GFS2_LOCKNAME_LEN);
 			break;
 		case Opt_hostdata:
-			v = match_strdup(&tmp[0]);
-			if (!v) {
-				fs_info(sdp, "no memory for hostdata\n");
-				error = -ENOMEM;
-				goto out_error;
-			}
-
-			if (remount && strcmp(v, args->ar_hostdata)) {
-				kfree(v);
-				goto cant_remount;
-			}
-
-			strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN);
-			args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0;
-			kfree(v);
+			match_strlcpy(args->ar_hostdata, &tmp[0],
+				      GFS2_LOCKNAME_LEN);
 			break;
 		case Opt_spectator:
-			if (remount && !args->ar_spectator)
-				goto cant_remount;
 			args->ar_spectator = 1;
-			sdp->sd_vfs->s_flags |= MS_RDONLY;
 			break;
 		case Opt_ignore_local_fs:
-			if (remount && !args->ar_ignore_local_fs)
-				goto cant_remount;
 			args->ar_ignore_local_fs = 1;
 			break;
 		case Opt_localflocks:
-			if (remount && !args->ar_localflocks)
-				goto cant_remount;
 			args->ar_localflocks = 1;
 			break;
 		case Opt_localcaching:
-			if (remount && !args->ar_localcaching)
-				goto cant_remount;
 			args->ar_localcaching = 1;
 			break;
 		case Opt_debug:
@@ -181,25 +133,23 @@
 			args->ar_debug = 0;
 			break;
 		case Opt_upgrade:
-			if (remount && !args->ar_upgrade)
-				goto cant_remount;
 			args->ar_upgrade = 1;
 			break;
 		case Opt_acl:
 			args->ar_posix_acl = 1;
-			sdp->sd_vfs->s_flags |= MS_POSIXACL;
 			break;
 		case Opt_noacl:
 			args->ar_posix_acl = 0;
-			sdp->sd_vfs->s_flags &= ~MS_POSIXACL;
 			break;
 		case Opt_quota_off:
+		case Opt_noquota:
 			args->ar_quota = GFS2_QUOTA_OFF;
 			break;
 		case Opt_quota_account:
 			args->ar_quota = GFS2_QUOTA_ACCOUNT;
 			break;
 		case Opt_quota_on:
+		case Opt_quota:
 			args->ar_quota = GFS2_QUOTA_ON;
 			break;
 		case Opt_suiddir:
@@ -215,29 +165,21 @@
 			args->ar_data = GFS2_DATA_ORDERED;
 			break;
 		case Opt_meta:
-			if (remount && args->ar_meta != 1)
-				goto cant_remount;
 			args->ar_meta = 1;
 			break;
+		case Opt_discard:
+			args->ar_discard = 1;
+			break;
+		case Opt_nodiscard:
+			args->ar_discard = 0;
+			break;
 		case Opt_err:
 		default:
-			fs_info(sdp, "unknown option: %s\n", o);
-			error = -EINVAL;
-			goto out_error;
+			fs_info(sdp, "invalid mount option: %s\n", o);
+			return -EINVAL;
 		}
 	}
 
-out_error:
-	if (error)
-		fs_info(sdp, "invalid mount option(s)\n");
-
-	if (data != data_arg)
-		kfree(data);
-
-	return error;
-
-cant_remount:
-	fs_info(sdp, "can't remount with option %s\n", o);
-	return -EINVAL;
+	return 0;
 }
 
diff --git a/fs/gfs2/mount.h b/fs/gfs2/mount.h
deleted file mode 100644
index 401288a..0000000
--- a/fs/gfs2/mount.h
+++ /dev/null
@@ -1,17 +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 __MOUNT_DOT_H__
-#define __MOUNT_DOT_H__
-
-struct gfs2_sbd;
-
-int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount);
-
-#endif /* __MOUNT_DOT_H__ */
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 4ddab67..a6dde17 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -19,7 +19,6 @@
 #include <linux/writeback.h>
 #include <linux/swap.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <linux/backing-dev.h>
 
 #include "gfs2.h"
@@ -442,6 +441,7 @@
 	 */
 	if (unlikely(page->index)) {
 		zero_user(page, 0, PAGE_CACHE_SIZE);
+		SetPageUptodate(page);
 		return 0;
 	}
 
@@ -1096,6 +1096,7 @@
 	.releasepage = gfs2_releasepage,
 	.direct_IO = gfs2_direct_IO,
 	.migratepage = buffer_migrate_page,
+	.is_partially_uptodate = block_is_partially_uptodate,
 };
 
 static const struct address_space_operations gfs2_ordered_aops = {
@@ -1111,6 +1112,7 @@
 	.releasepage = gfs2_releasepage,
 	.direct_IO = gfs2_direct_IO,
 	.migratepage = buffer_migrate_page,
+	.is_partially_uptodate = block_is_partially_uptodate,
 };
 
 static const struct address_space_operations gfs2_jdata_aops = {
@@ -1125,6 +1127,7 @@
 	.bmap = gfs2_bmap,
 	.invalidatepage = gfs2_invalidatepage,
 	.releasepage = gfs2_releasepage,
+	.is_partially_uptodate = block_is_partially_uptodate,
 };
 
 void gfs2_set_aops(struct inode *inode)
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
index c2ad363..5eb57b0 100644
--- a/fs/gfs2/ops_dentry.c
+++ b/fs/gfs2/ops_dentry.c
@@ -13,7 +13,6 @@
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
 
 #include "gfs2.h"
 #include "incore.h"
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index 7fdeb14..9200ef2 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -14,7 +14,6 @@
 #include <linux/exportfs.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
 
 #include "gfs2.h"
 #include "incore.h"
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 93fe41b..3b9e8de 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -20,9 +20,10 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/ext2_fs.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
 #include <linux/writeback.h>
 #include <asm/uaccess.h>
+#include <linux/dlm.h>
+#include <linux/dlm_plock.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -354,7 +355,9 @@
 	if (ret)
 		goto out;
 
+	set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
 	set_bit(GIF_SW_PAGED, &ip->i_flags);
+
 	ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required);
 	if (ret || !alloc_required)
 		goto out_unlock;
@@ -560,57 +563,24 @@
 	return ret;
 }
 
+#ifdef CONFIG_GFS2_FS_LOCKING_DLM
+
 /**
  * gfs2_setlease - acquire/release a file lease
  * @file: the file pointer
  * @arg: lease type
  * @fl: file lock
  *
+ * We don't currently have a way to enforce a lease across the whole
+ * cluster; until we do, disable leases (by just returning -EINVAL),
+ * unless the administrator has requested purely local locking.
+ *
  * Returns: errno
  */
 
 static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl)
 {
-	struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
-
-	/*
-	 * We don't currently have a way to enforce a lease across the whole
-	 * cluster; until we do, disable leases (by just returning -EINVAL),
-	 * unless the administrator has requested purely local locking.
-	 */
-	if (!sdp->sd_args.ar_localflocks)
-		return -EINVAL;
-	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;
+	return -EINVAL;
 }
 
 /**
@@ -626,9 +596,7 @@
 {
 	struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
 	struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
-	struct lm_lockname name =
-		{ .ln_number = ip->i_no_addr,
-		  .ln_type = LM_TYPE_PLOCK };
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
 
 	if (!(fl->fl_flags & FL_POSIX))
 		return -ENOLCK;
@@ -640,12 +608,14 @@
 		cmd = F_SETLK;
 		fl->fl_type = F_UNLCK;
 	}
+	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+		return -EIO;
 	if (IS_GETLK(cmd))
-		return gfs2_lm_plock_get(sdp, &name, file, fl);
+		return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
 	else if (fl->fl_type == F_UNLCK)
-		return gfs2_lm_punlock(sdp, &name, file, fl);
+		return dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl);
 	else
-		return gfs2_lm_plock(sdp, &name, file, cmd, fl);
+		return dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl);
 }
 
 static int do_flock(struct file *file, int cmd, struct file_lock *fl)
@@ -732,7 +702,7 @@
 	}
 }
 
-const struct file_operations gfs2_file_fops = {
+const struct file_operations *gfs2_file_fops = &(const struct file_operations){
 	.llseek		= gfs2_llseek,
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
@@ -750,7 +720,7 @@
 	.setlease	= gfs2_setlease,
 };
 
-const struct file_operations gfs2_dir_fops = {
+const struct file_operations *gfs2_dir_fops = &(const struct file_operations){
 	.readdir	= gfs2_readdir,
 	.unlocked_ioctl	= gfs2_ioctl,
 	.open		= gfs2_open,
@@ -760,7 +730,9 @@
 	.flock		= gfs2_flock,
 };
 
-const struct file_operations gfs2_file_fops_nolock = {
+#endif /* CONFIG_GFS2_FS_LOCKING_DLM */
+
+const struct file_operations *gfs2_file_fops_nolock = &(const struct file_operations){
 	.llseek		= gfs2_llseek,
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
@@ -773,10 +745,10 @@
 	.fsync		= gfs2_fsync,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
-	.setlease	= gfs2_setlease,
+	.setlease	= generic_setlease,
 };
 
-const struct file_operations gfs2_dir_fops_nolock = {
+const struct file_operations *gfs2_dir_fops_nolock = &(const struct file_operations){
 	.readdir	= gfs2_readdir,
 	.unlocked_ioctl	= gfs2_ioctl,
 	.open		= gfs2_open,
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index f91eebd..51883b3 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -17,7 +17,6 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -25,7 +24,6 @@
 #include "glock.h"
 #include "glops.h"
 #include "inode.h"
-#include "mount.h"
 #include "recovery.h"
 #include "rgrp.h"
 #include "super.h"
@@ -64,7 +62,6 @@
 	gt->gt_quota_warn_period = 10;
 	gt->gt_quota_scale_num = 1;
 	gt->gt_quota_scale_den = 1;
-	gt->gt_quota_cache_secs = 300;
 	gt->gt_quota_quantum = 60;
 	gt->gt_new_files_jdata = 0;
 	gt->gt_max_readahead = 1 << 18;
@@ -100,7 +97,6 @@
 	mutex_init(&sdp->sd_jindex_mutex);
 
 	INIT_LIST_HEAD(&sdp->sd_quota_list);
-	spin_lock_init(&sdp->sd_quota_spin);
 	mutex_init(&sdp->sd_quota_mutex);
 	init_waitqueue_head(&sdp->sd_quota_wait);
 	INIT_LIST_HEAD(&sdp->sd_trunc_list);
@@ -238,6 +234,7 @@
 
 	memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
 	memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
+	memcpy(sb->sb_uuid, str->sb_uuid, 16);
 }
 
 /**
@@ -299,15 +296,15 @@
 	__free_page(page);
 	return 0;
 }
+
 /**
  * gfs2_read_sb - Read super block
  * @sdp: The GFS2 superblock
- * @gl: the glock for the superblock (assumed to be held)
  * @silent: Don't print message if mount fails
  *
  */
 
-static int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
+static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent)
 {
 	u32 hash_blocks, ind_blocks, leaf_blocks;
 	u32 tmp_blocks;
@@ -527,7 +524,7 @@
 		return ret;
 	}
 
-	ret = gfs2_read_sb(sdp, sb_gh.gh_gl, silent);
+	ret = gfs2_read_sb(sdp, silent);
 	if (ret) {
 		fs_err(sdp, "can't read superblock: %d\n", ret);
 		goto out;
@@ -630,13 +627,13 @@
 	return rc;
 }
 
-static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
+static void gfs2_others_may_mount(struct gfs2_sbd *sdp)
 {
-	if (!sdp->sd_lockstruct.ls_ops->lm_others_may_mount)
-		return;
-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
-		sdp->sd_lockstruct.ls_ops->lm_others_may_mount(
-					sdp->sd_lockstruct.ls_lockspace);
+	char *message = "FIRSTMOUNT=Done";
+	char *envp[] = { message, NULL };
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	ls->ls_first_done = 1;
+	kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp);
 }
 
 /**
@@ -796,7 +793,7 @@
 			}
 		}
 
-		gfs2_lm_others_may_mount(sdp);
+		gfs2_others_may_mount(sdp);
 	} else if (!sdp->sd_args.ar_spectator) {
 		error = gfs2_recover_journal(sdp->sd_jdesc);
 		if (error) {
@@ -1005,7 +1002,6 @@
 		goto fail_quotad;
 
 	sdp->sd_log_flush_time = jiffies;
-	sdp->sd_jindex_refresh_time = jiffies;
 
 	p = kthread_run(gfs2_logd, sdp, "gfs2_logd");
 	error = IS_ERR(p);
@@ -1033,6 +1029,17 @@
 	return error;
 }
 
+static const match_table_t nolock_tokens = {
+	{ Opt_jid, "jid=%d\n", },
+	{ Opt_err, NULL },
+};
+
+static const struct lm_lockops nolock_ops = {
+	.lm_proto_name = "lock_nolock",
+	.lm_put_lock = kmem_cache_free,
+	.lm_tokens = &nolock_tokens,
+};
+
 /**
  * gfs2_lm_mount - mount a locking protocol
  * @sdp: the filesystem
@@ -1044,31 +1051,73 @@
 
 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;
+	const struct lm_lockops *lm;
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	struct gfs2_args *args = &sdp->sd_args;
+	const char *proto = sdp->sd_proto_name;
+	const char *table = sdp->sd_table_name;
+	const char *fsname;
+	char *o, *options;
+	int ret;
 
-	if (sdp->sd_args.ar_spectator)
-		flags |= LM_MFLAG_SPECTATOR;
+	if (!strcmp("lock_nolock", proto)) {
+		lm = &nolock_ops;
+		sdp->sd_args.ar_localflocks = 1;
+		sdp->sd_args.ar_localcaching = 1;
+#ifdef CONFIG_GFS2_FS_LOCKING_DLM
+	} else if (!strcmp("lock_dlm", proto)) {
+		lm = &gfs2_dlm_ops;
+#endif
+	} else {
+		printk(KERN_INFO "GFS2: can't find protocol %s\n", proto);
+		return -ENOENT;
+	}
 
 	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;
-	}
+	ls->ls_ops = lm;
+	ls->ls_first = 1;
+	ls->ls_id = 0;
 
-	if (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;
+	for (options = args->ar_hostdata; (o = strsep(&options, ":")); ) {
+		substring_t tmp[MAX_OPT_ARGS];
+		int token, option;
+
+		if (!o || !*o)
+			continue;
+
+		token = match_token(o, *lm->lm_tokens, tmp);
+		switch (token) {
+		case Opt_jid:
+			ret = match_int(&tmp[0], &option);
+			if (ret || option < 0) 
+				goto hostdata_error;
+			ls->ls_jid = option;
+			break;
+		case Opt_id:
+			ret = match_int(&tmp[0], &option);
+			if (ret)
+				goto hostdata_error;
+			ls->ls_id = option;
+			break;
+		case Opt_first:
+			ret = match_int(&tmp[0], &option);
+			if (ret || (option != 0 && option != 1))
+				goto hostdata_error;
+			ls->ls_first = option;
+			break;
+		case Opt_nodir:
+			ret = match_int(&tmp[0], &option);
+			if (ret || (option != 0 && option != 1))
+				goto hostdata_error;
+			ls->ls_nodir = option;
+			break;
+		case Opt_err:
+		default:
+hostdata_error:
+			fs_info(sdp, "unknown hostdata (%s)\n", o);
+			return -EINVAL;
+		}
 	}
 
 	if (sdp->sd_args.ar_spectator)
@@ -1077,22 +1126,25 @@
 		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;
+	fsname = strchr(table, ':');
+	if (fsname)
+		fsname++;
+	if (lm->lm_mount == NULL) {
+		fs_info(sdp, "Now mounting FS...\n");
+		return 0;
 	}
-
-out:
-	return error;
+	ret = lm->lm_mount(sdp, fsname);
+	if (ret == 0)
+		fs_info(sdp, "Joined cluster. Now mounting FS...\n");
+	return ret;
 }
 
 void gfs2_lm_unmount(struct gfs2_sbd *sdp)
 {
-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
-		gfs2_unmount_lockproto(&sdp->sd_lockstruct);
+	const struct lm_lockops *lm = sdp->sd_lockstruct.ls_ops;
+	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) &&
+	    lm->lm_unmount)
+		lm->lm_unmount(sdp);
 }
 
 /**
@@ -1116,12 +1168,20 @@
 		return -ENOMEM;
 	}
 
-	error = gfs2_mount_args(sdp, (char *)data, 0);
+	sdp->sd_args.ar_quota = GFS2_QUOTA_DEFAULT;
+	sdp->sd_args.ar_data = GFS2_DATA_DEFAULT;
+
+	error = gfs2_mount_args(sdp, &sdp->sd_args, data);
 	if (error) {
 		printk(KERN_WARNING "GFS2: can't parse mount arguments\n");
 		goto fail;
 	}
 
+	if (sdp->sd_args.ar_spectator)
+                sb->s_flags |= MS_RDONLY;
+	if (sdp->sd_args.ar_posix_acl)
+		sb->s_flags |= MS_POSIXACL;
+
 	sb->s_magic = GFS2_MAGIC;
 	sb->s_op = &gfs2_super_ops;
 	sb->s_export_op = &gfs2_export_ops;
@@ -1199,6 +1259,8 @@
 		dput(sdp->sd_root_dir);
 	if (sdp->sd_master_dir)
 		dput(sdp->sd_master_dir);
+	if (sb->s_root)
+		dput(sb->s_root);
 	sb->s_root = NULL;
 fail_locking:
 	init_locking(sdp, &mount_gh, UNDO);
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 4987754..abd5429 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -18,7 +18,6 @@
 #include <linux/posix_acl.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
 #include <linux/fiemap.h>
 #include <asm/uaccess.h>
 
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 320323d..4580195 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -19,7 +19,6 @@
 #include <linux/delay.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
 #include <linux/time.h>
 
 #include "gfs2.h"
@@ -27,7 +26,6 @@
 #include "glock.h"
 #include "inode.h"
 #include "log.h"
-#include "mount.h"
 #include "quota.h"
 #include "recovery.h"
 #include "rgrp.h"
@@ -40,6 +38,8 @@
 #include "bmap.h"
 #include "meta_io.h"
 
+#define args_neq(a1, a2, x) ((a1)->ar_##x != (a2)->ar_##x)
+
 /**
  * gfs2_write_inode - Make sure the inode is stable on the disk
  * @inode: The inode
@@ -435,25 +435,45 @@
 static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
 {
 	struct gfs2_sbd *sdp = sb->s_fs_info;
+	struct gfs2_args args = sdp->sd_args; /* Default to current settings */
 	int error;
 
-	error = gfs2_mount_args(sdp, data, 1);
+	error = gfs2_mount_args(sdp, &args, data);
 	if (error)
 		return error;
 
+	/* Not allowed to change locking details */
+	if (strcmp(args.ar_lockproto, sdp->sd_args.ar_lockproto) ||
+	    strcmp(args.ar_locktable, sdp->sd_args.ar_locktable) ||
+	    strcmp(args.ar_hostdata, sdp->sd_args.ar_hostdata))
+		return -EINVAL;
+
+	/* Some flags must not be changed */
+	if (args_neq(&args, &sdp->sd_args, spectator) ||
+	    args_neq(&args, &sdp->sd_args, ignore_local_fs) ||
+	    args_neq(&args, &sdp->sd_args, localflocks) ||
+	    args_neq(&args, &sdp->sd_args, localcaching) ||
+	    args_neq(&args, &sdp->sd_args, meta))
+		return -EINVAL;
+
 	if (sdp->sd_args.ar_spectator)
 		*flags |= MS_RDONLY;
-	else {
-		if (*flags & MS_RDONLY) {
-			if (!(sb->s_flags & MS_RDONLY))
-				error = gfs2_make_fs_ro(sdp);
-		} else if (!(*flags & MS_RDONLY) &&
-			   (sb->s_flags & MS_RDONLY)) {
+
+	if ((sb->s_flags ^ *flags) & MS_RDONLY) {
+		if (*flags & MS_RDONLY)
+			error = gfs2_make_fs_ro(sdp);
+		else
 			error = gfs2_make_fs_rw(sdp);
-		}
+		if (error)
+			return error;
 	}
 
-	return error;
+	sdp->sd_args = args;
+	if (sdp->sd_args.ar_posix_acl)
+		sb->s_flags |= MS_POSIXACL;
+	else
+		sb->s_flags &= ~MS_POSIXACL;
+	return 0;
 }
 
 /**
@@ -588,6 +608,8 @@
 		}
 		seq_printf(s, ",data=%s", state);
 	}
+	if (args->ar_discard)
+		seq_printf(s, ",discard");
 
 	return 0;
 }
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index b08d096..8d53f66 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -45,7 +45,6 @@
 #include <linux/fs.h>
 #include <linux/bio.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
@@ -80,6 +79,51 @@
 	u32 qc_id;
 };
 
+static LIST_HEAD(qd_lru_list);
+static atomic_t qd_lru_count = ATOMIC_INIT(0);
+static spinlock_t qd_lru_lock = SPIN_LOCK_UNLOCKED;
+
+int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask)
+{
+	struct gfs2_quota_data *qd;
+	struct gfs2_sbd *sdp;
+
+	if (nr == 0)
+		goto out;
+
+	if (!(gfp_mask & __GFP_FS))
+		return -1;
+
+	spin_lock(&qd_lru_lock);
+	while (nr && !list_empty(&qd_lru_list)) {
+		qd = list_entry(qd_lru_list.next,
+				struct gfs2_quota_data, qd_reclaim);
+		sdp = qd->qd_gl->gl_sbd;
+
+		/* Free from the filesystem-specific list */
+		list_del(&qd->qd_list);
+
+		gfs2_assert_warn(sdp, !qd->qd_change);
+		gfs2_assert_warn(sdp, !qd->qd_slot_count);
+		gfs2_assert_warn(sdp, !qd->qd_bh_count);
+
+		gfs2_glock_put(qd->qd_gl);
+		atomic_dec(&sdp->sd_quota_count);
+
+		/* Delete it from the common reclaim list */
+		list_del_init(&qd->qd_reclaim);
+		atomic_dec(&qd_lru_count);
+		spin_unlock(&qd_lru_lock);
+		kmem_cache_free(gfs2_quotad_cachep, qd);
+		spin_lock(&qd_lru_lock);
+		nr--;
+	}
+	spin_unlock(&qd_lru_lock);
+
+out:
+	return (atomic_read(&qd_lru_count) * sysctl_vfs_cache_pressure) / 100;
+}
+
 static u64 qd2offset(struct gfs2_quota_data *qd)
 {
 	u64 offset;
@@ -100,22 +144,18 @@
 	if (!qd)
 		return -ENOMEM;
 
-	qd->qd_count = 1;
+	atomic_set(&qd->qd_count, 1);
 	qd->qd_id = id;
 	if (user)
 		set_bit(QDF_USER, &qd->qd_flags);
 	qd->qd_slot = -1;
+	INIT_LIST_HEAD(&qd->qd_reclaim);
 
 	error = gfs2_glock_get(sdp, 2 * (u64)id + !user,
 			      &gfs2_quota_glops, CREATE, &qd->qd_gl);
 	if (error)
 		goto fail;
 
-	error = gfs2_lvb_hold(qd->qd_gl);
-	gfs2_glock_put(qd->qd_gl);
-	if (error)
-		goto fail;
-
 	*qdp = qd;
 
 	return 0;
@@ -135,11 +175,17 @@
 
 	for (;;) {
 		found = 0;
-		spin_lock(&sdp->sd_quota_spin);
+		spin_lock(&qd_lru_lock);
 		list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
 			if (qd->qd_id == id &&
 			    !test_bit(QDF_USER, &qd->qd_flags) == !user) {
-				qd->qd_count++;
+				if (!atomic_read(&qd->qd_count) &&
+				    !list_empty(&qd->qd_reclaim)) {
+					/* Remove it from reclaim list */
+					list_del_init(&qd->qd_reclaim);
+					atomic_dec(&qd_lru_count);
+				}
+				atomic_inc(&qd->qd_count);
 				found = 1;
 				break;
 			}
@@ -155,11 +201,11 @@
 			new_qd = NULL;
 		}
 
-		spin_unlock(&sdp->sd_quota_spin);
+		spin_unlock(&qd_lru_lock);
 
 		if (qd || !create) {
 			if (new_qd) {
-				gfs2_lvb_unhold(new_qd->qd_gl);
+				gfs2_glock_put(new_qd->qd_gl);
 				kmem_cache_free(gfs2_quotad_cachep, new_qd);
 			}
 			*qdp = qd;
@@ -175,21 +221,18 @@
 static void qd_hold(struct gfs2_quota_data *qd)
 {
 	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
-
-	spin_lock(&sdp->sd_quota_spin);
-	gfs2_assert(sdp, qd->qd_count);
-	qd->qd_count++;
-	spin_unlock(&sdp->sd_quota_spin);
+	gfs2_assert(sdp, atomic_read(&qd->qd_count));
+	atomic_inc(&qd->qd_count);
 }
 
 static void qd_put(struct gfs2_quota_data *qd)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
-	spin_lock(&sdp->sd_quota_spin);
-	gfs2_assert(sdp, qd->qd_count);
-	if (!--qd->qd_count)
-		qd->qd_last_touched = jiffies;
-	spin_unlock(&sdp->sd_quota_spin);
+	if (atomic_dec_and_lock(&qd->qd_count, &qd_lru_lock)) {
+		/* Add to the reclaim list */
+		list_add_tail(&qd->qd_reclaim, &qd_lru_list);
+		atomic_inc(&qd_lru_count);
+		spin_unlock(&qd_lru_lock);
+	}
 }
 
 static int slot_get(struct gfs2_quota_data *qd)
@@ -198,10 +241,10 @@
 	unsigned int c, o = 0, b;
 	unsigned char byte = 0;
 
-	spin_lock(&sdp->sd_quota_spin);
+	spin_lock(&qd_lru_lock);
 
 	if (qd->qd_slot_count++) {
-		spin_unlock(&sdp->sd_quota_spin);
+		spin_unlock(&qd_lru_lock);
 		return 0;
 	}
 
@@ -225,13 +268,13 @@
 
 	sdp->sd_quota_bitmap[c][o] |= 1 << b;
 
-	spin_unlock(&sdp->sd_quota_spin);
+	spin_unlock(&qd_lru_lock);
 
 	return 0;
 
 fail:
 	qd->qd_slot_count--;
-	spin_unlock(&sdp->sd_quota_spin);
+	spin_unlock(&qd_lru_lock);
 	return -ENOSPC;
 }
 
@@ -239,23 +282,23 @@
 {
 	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
 
-	spin_lock(&sdp->sd_quota_spin);
+	spin_lock(&qd_lru_lock);
 	gfs2_assert(sdp, qd->qd_slot_count);
 	qd->qd_slot_count++;
-	spin_unlock(&sdp->sd_quota_spin);
+	spin_unlock(&qd_lru_lock);
 }
 
 static void slot_put(struct gfs2_quota_data *qd)
 {
 	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
 
-	spin_lock(&sdp->sd_quota_spin);
+	spin_lock(&qd_lru_lock);
 	gfs2_assert(sdp, qd->qd_slot_count);
 	if (!--qd->qd_slot_count) {
 		gfs2_icbit_munge(sdp, sdp->sd_quota_bitmap, qd->qd_slot, 0);
 		qd->qd_slot = -1;
 	}
-	spin_unlock(&sdp->sd_quota_spin);
+	spin_unlock(&qd_lru_lock);
 }
 
 static int bh_get(struct gfs2_quota_data *qd)
@@ -330,7 +373,7 @@
 	if (sdp->sd_vfs->s_flags & MS_RDONLY)
 		return 0;
 
-	spin_lock(&sdp->sd_quota_spin);
+	spin_lock(&qd_lru_lock);
 
 	list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
 		if (test_bit(QDF_LOCKED, &qd->qd_flags) ||
@@ -341,8 +384,8 @@
 		list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
 
 		set_bit(QDF_LOCKED, &qd->qd_flags);
-		gfs2_assert_warn(sdp, qd->qd_count);
-		qd->qd_count++;
+		gfs2_assert_warn(sdp, atomic_read(&qd->qd_count));
+		atomic_inc(&qd->qd_count);
 		qd->qd_change_sync = qd->qd_change;
 		gfs2_assert_warn(sdp, qd->qd_slot_count);
 		qd->qd_slot_count++;
@@ -354,7 +397,7 @@
 	if (!found)
 		qd = NULL;
 
-	spin_unlock(&sdp->sd_quota_spin);
+	spin_unlock(&qd_lru_lock);
 
 	if (qd) {
 		gfs2_assert_warn(sdp, qd->qd_change_sync);
@@ -379,24 +422,24 @@
 	if (sdp->sd_vfs->s_flags & MS_RDONLY)
 		return 0;
 
-	spin_lock(&sdp->sd_quota_spin);
+	spin_lock(&qd_lru_lock);
 
 	if (test_bit(QDF_LOCKED, &qd->qd_flags) ||
 	    !test_bit(QDF_CHANGE, &qd->qd_flags)) {
-		spin_unlock(&sdp->sd_quota_spin);
+		spin_unlock(&qd_lru_lock);
 		return 0;
 	}
 
 	list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
 
 	set_bit(QDF_LOCKED, &qd->qd_flags);
-	gfs2_assert_warn(sdp, qd->qd_count);
-	qd->qd_count++;
+	gfs2_assert_warn(sdp, atomic_read(&qd->qd_count));
+	atomic_inc(&qd->qd_count);
 	qd->qd_change_sync = qd->qd_change;
 	gfs2_assert_warn(sdp, qd->qd_slot_count);
 	qd->qd_slot_count++;
 
-	spin_unlock(&sdp->sd_quota_spin);
+	spin_unlock(&qd_lru_lock);
 
 	gfs2_assert_warn(sdp, qd->qd_change_sync);
 	if (bh_get(qd)) {
@@ -556,9 +599,9 @@
 	x = be64_to_cpu(qc->qc_change) + change;
 	qc->qc_change = cpu_to_be64(x);
 
-	spin_lock(&sdp->sd_quota_spin);
+	spin_lock(&qd_lru_lock);
 	qd->qd_change = x;
-	spin_unlock(&sdp->sd_quota_spin);
+	spin_unlock(&qd_lru_lock);
 
 	if (!x) {
 		gfs2_assert_warn(sdp, test_bit(QDF_CHANGE, &qd->qd_flags));
@@ -802,8 +845,8 @@
 		loff_t pos;
 		gfs2_glock_dq_uninit(q_gh);
 		error = gfs2_glock_nq_init(qd->qd_gl,
-					  LM_ST_EXCLUSIVE, GL_NOCACHE,
-					  q_gh);
+					   LM_ST_EXCLUSIVE, GL_NOCACHE,
+					   q_gh);
 		if (error)
 			return error;
 
@@ -820,7 +863,6 @@
 
 		gfs2_glock_dq_uninit(&i_gh);
 
-
 		gfs2_quota_in(&q, buf);
 		qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
 		qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC);
@@ -890,9 +932,9 @@
 	if (!qd->qd_qb.qb_limit)
 		return 0;
 
-	spin_lock(&sdp->sd_quota_spin);
+	spin_lock(&qd_lru_lock);
 	value = qd->qd_change;
-	spin_unlock(&sdp->sd_quota_spin);
+	spin_unlock(&qd_lru_lock);
 
 	spin_lock(&gt->gt_spin);
 	num = gt->gt_quota_scale_num;
@@ -985,9 +1027,9 @@
 			continue;
 
 		value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
-		spin_lock(&sdp->sd_quota_spin);
+		spin_lock(&qd_lru_lock);
 		value += qd->qd_change;
-		spin_unlock(&sdp->sd_quota_spin);
+		spin_unlock(&qd_lru_lock);
 
 		if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) {
 			print_message(qd, "exceeded");
@@ -1171,13 +1213,12 @@
 			qd->qd_change = qc.qc_change;
 			qd->qd_slot = slot;
 			qd->qd_slot_count = 1;
-			qd->qd_last_touched = jiffies;
 
-			spin_lock(&sdp->sd_quota_spin);
+			spin_lock(&qd_lru_lock);
 			gfs2_icbit_munge(sdp, sdp->sd_quota_bitmap, slot, 1);
 			list_add(&qd->qd_list, &sdp->sd_quota_list);
 			atomic_inc(&sdp->sd_quota_count);
-			spin_unlock(&sdp->sd_quota_spin);
+			spin_unlock(&qd_lru_lock);
 
 			found++;
 		}
@@ -1197,73 +1238,48 @@
 	return error;
 }
 
-static void gfs2_quota_scan(struct gfs2_sbd *sdp)
-{
-	struct gfs2_quota_data *qd, *safe;
-	LIST_HEAD(dead);
-
-	spin_lock(&sdp->sd_quota_spin);
-	list_for_each_entry_safe(qd, safe, &sdp->sd_quota_list, qd_list) {
-		if (!qd->qd_count &&
-		    time_after_eq(jiffies, qd->qd_last_touched +
-			        gfs2_tune_get(sdp, gt_quota_cache_secs) * HZ)) {
-			list_move(&qd->qd_list, &dead);
-			gfs2_assert_warn(sdp,
-					 atomic_read(&sdp->sd_quota_count) > 0);
-			atomic_dec(&sdp->sd_quota_count);
-		}
-	}
-	spin_unlock(&sdp->sd_quota_spin);
-
-	while (!list_empty(&dead)) {
-		qd = list_entry(dead.next, struct gfs2_quota_data, qd_list);
-		list_del(&qd->qd_list);
-
-		gfs2_assert_warn(sdp, !qd->qd_change);
-		gfs2_assert_warn(sdp, !qd->qd_slot_count);
-		gfs2_assert_warn(sdp, !qd->qd_bh_count);
-
-		gfs2_lvb_unhold(qd->qd_gl);
-		kmem_cache_free(gfs2_quotad_cachep, qd);
-	}
-}
-
 void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
 {
 	struct list_head *head = &sdp->sd_quota_list;
 	struct gfs2_quota_data *qd;
 	unsigned int x;
 
-	spin_lock(&sdp->sd_quota_spin);
+	spin_lock(&qd_lru_lock);
 	while (!list_empty(head)) {
 		qd = list_entry(head->prev, struct gfs2_quota_data, qd_list);
 
-		if (qd->qd_count > 1 ||
-		    (qd->qd_count && !test_bit(QDF_CHANGE, &qd->qd_flags))) {
+		if (atomic_read(&qd->qd_count) > 1 ||
+		    (atomic_read(&qd->qd_count) &&
+		     !test_bit(QDF_CHANGE, &qd->qd_flags))) {
 			list_move(&qd->qd_list, head);
-			spin_unlock(&sdp->sd_quota_spin);
+			spin_unlock(&qd_lru_lock);
 			schedule();
-			spin_lock(&sdp->sd_quota_spin);
+			spin_lock(&qd_lru_lock);
 			continue;
 		}
 
 		list_del(&qd->qd_list);
+		/* Also remove if this qd exists in the reclaim list */
+		if (!list_empty(&qd->qd_reclaim)) {
+			list_del_init(&qd->qd_reclaim);
+			atomic_dec(&qd_lru_count);
+		}
 		atomic_dec(&sdp->sd_quota_count);
-		spin_unlock(&sdp->sd_quota_spin);
+		spin_unlock(&qd_lru_lock);
 
-		if (!qd->qd_count) {
+		if (!atomic_read(&qd->qd_count)) {
 			gfs2_assert_warn(sdp, !qd->qd_change);
 			gfs2_assert_warn(sdp, !qd->qd_slot_count);
 		} else
 			gfs2_assert_warn(sdp, qd->qd_slot_count == 1);
 		gfs2_assert_warn(sdp, !qd->qd_bh_count);
 
-		gfs2_lvb_unhold(qd->qd_gl);
+		gfs2_glock_put(qd->qd_gl);
 		kmem_cache_free(gfs2_quotad_cachep, qd);
 
-		spin_lock(&sdp->sd_quota_spin);
+		spin_lock(&qd_lru_lock);
 	}
-	spin_unlock(&sdp->sd_quota_spin);
+	spin_unlock(&qd_lru_lock);
 
 	gfs2_assert_warn(sdp, !atomic_read(&sdp->sd_quota_count));
 
@@ -1341,9 +1357,6 @@
 		quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t,
 				   &quotad_timeo, &tune->gt_quota_quantum);
 
-		/* FIXME: This should be turned into a shrinker */
-		gfs2_quota_scan(sdp);
-
 		/* Check for & recover partially truncated inodes */
 		quotad_check_trunc_list(sdp);
 
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
index cec9032..0fa5fa6 100644
--- a/fs/gfs2/quota.h
+++ b/fs/gfs2/quota.h
@@ -49,4 +49,6 @@
 	return ret;
 }
 
+extern int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask);
+
 #endif /* __QUOTA_DOT_H__ */
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index efd09c3..247e8f7 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -13,7 +13,6 @@
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
@@ -427,20 +426,23 @@
 }
 
 
-static void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
-				  unsigned int message)
+static void gfs2_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
+                               unsigned int message)
 {
-	if (!sdp->sd_lockstruct.ls_ops->lm_recovery_done)
-		return;
-
-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
-		sdp->sd_lockstruct.ls_ops->lm_recovery_done(
-			sdp->sd_lockstruct.ls_lockspace, jid, message);
+	char env_jid[20];
+	char env_status[20];
+	char *envp[] = { env_jid, env_status, NULL };
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+        ls->ls_recover_jid_done = jid;
+        ls->ls_recover_jid_status = message;
+	sprintf(env_jid, "JID=%d", jid);
+	sprintf(env_status, "RECOVERY=%s",
+		message == LM_RD_SUCCESS ? "Done" : "Failed");
+        kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp);
 }
 
-
 /**
- * gfs2_recover_journal - recovery a given journal
+ * gfs2_recover_journal - recover a given journal
  * @jd: the struct gfs2_jdesc describing the journal
  *
  * Acquire the journal's lock, check to see if the journal is clean, and
@@ -561,7 +563,7 @@
 	if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
 		gfs2_glock_dq_uninit(&ji_gh);
 
-	gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
+	gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
 
 	if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
 		gfs2_glock_dq_uninit(&j_gh);
@@ -581,7 +583,7 @@
 	fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done");
 
 fail:
-	gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP);
+	gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP);
 	return error;
 }
 
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 8b01c63..f03d024 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -13,8 +13,8 @@
 #include <linux/buffer_head.h>
 #include <linux/fs.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <linux/prefetch.h>
+#include <linux/blkdev.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -132,81 +132,90 @@
 }
 
 /**
+ * gfs2_bit_search
+ * @ptr: Pointer to bitmap data
+ * @mask: Mask to use (normally 0x55555.... but adjusted for search start)
+ * @state: The state we are searching for
+ *
+ * We xor the bitmap data with a patter which is the bitwise opposite
+ * of what we are looking for, this gives rise to a pattern of ones
+ * wherever there is a match. Since we have two bits per entry, we
+ * take this pattern, shift it down by one place and then and it with
+ * the original. All the even bit positions (0,2,4, etc) then represent
+ * successful matches, so we mask with 0x55555..... to remove the unwanted
+ * odd bit positions.
+ *
+ * This allows searching of a whole u64 at once (32 blocks) with a
+ * single test (on 64 bit arches).
+ */
+
+static inline u64 gfs2_bit_search(const __le64 *ptr, u64 mask, u8 state)
+{
+	u64 tmp;
+	static const u64 search[] = {
+		[0] = 0xffffffffffffffffULL,
+		[1] = 0xaaaaaaaaaaaaaaaaULL,
+		[2] = 0x5555555555555555ULL,
+		[3] = 0x0000000000000000ULL,
+	};
+	tmp = le64_to_cpu(*ptr) ^ search[state];
+	tmp &= (tmp >> 1);
+	tmp &= mask;
+	return tmp;
+}
+
+/**
  * gfs2_bitfit - Search an rgrp's bitmap buffer to find a bit-pair representing
  *       a block in a given allocation state.
  * @buffer: the buffer that holds the bitmaps
- * @buflen: the length (in bytes) of the buffer
+ * @len: the length (in bytes) of the buffer
  * @goal: start search at this block's bit-pair (within @buffer)
- * @old_state: GFS2_BLKST_XXX the state of the block we're looking for.
+ * @state: GFS2_BLKST_XXX the state of the block we're looking for.
  *
  * Scope of @goal and returned block number is only within this bitmap buffer,
  * not entire rgrp or filesystem.  @buffer will be offset from the actual
- * beginning of a bitmap block buffer, skipping any header structures.
+ * beginning of a bitmap block buffer, skipping any header structures, but
+ * headers are always a multiple of 64 bits long so that the buffer is
+ * always aligned to a 64 bit boundary.
+ *
+ * The size of the buffer is in bytes, but is it assumed that it is
+ * always ok to to read a complete multiple of 64 bits at the end
+ * of the block in case the end is no aligned to a natural boundary.
  *
  * Return: the block number (bitmap buffer scope) that was found
  */
 
-static u32 gfs2_bitfit(const u8 *buffer, unsigned int buflen, u32 goal,
-		       u8 old_state)
+static u32 gfs2_bitfit(const u8 *buf, const unsigned int len,
+		       u32 goal, u8 state)
 {
-	const u8 *byte, *start, *end;
-	int bit, startbit;
-	u32 g1, g2, misaligned;
-	unsigned long *plong;
-	unsigned long lskipval;
+	u32 spoint = (goal << 1) & ((8*sizeof(u64)) - 1);
+	const __le64 *ptr = ((__le64 *)buf) + (goal >> 5);
+	const __le64 *end = (__le64 *)(buf + ALIGN(len, sizeof(u64)));
+	u64 tmp;
+	u64 mask = 0x5555555555555555ULL;
+	u32 bit;
 
-	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));
-		}
-		bit += GFS2_BIT_SIZE;
-		if (bit >= GFS2_NBBY * GFS2_BIT_SIZE) {
-			bit = 0;
-			byte++;
-			misaligned--;
-			if (!misaligned) {
-				plong = (unsigned long *)byte;
-				goto ulong_aligned;
-			}
-		}
-	}
-	return BFITNOENT;
+	BUG_ON(state > 3);
 
-/* 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 - sizeof(unsigned long)) {
-		prefetch(plong + 1);
-		if (((*plong) & LBITMASK) != lskipval)
-			break;
-		plong++;
+	/* Mask off bits we don't care about at the start of the search */
+	mask <<= spoint;
+	tmp = gfs2_bit_search(ptr, mask, state);
+	ptr++;
+	while(tmp == 0 && ptr < end) {
+		tmp = gfs2_bit_search(ptr, 0x5555555555555555ULL, state);
+		ptr++;
 	}
-	if ((unsigned char *)plong < end) {
-		byte = (const u8 *)plong;
-		misaligned += sizeof(unsigned long) - 1;
-		goto misaligned;
-	}
-	return BFITNOENT;
+	/* Mask off any bits which are more than len bytes from the start */
+	if (ptr == end && (len & (sizeof(u64) - 1)))
+		tmp &= (((u64)~0) >> (64 - 8*(len & (sizeof(u64) - 1))));
+	/* Didn't find anything, so return */
+	if (tmp == 0)
+		return BFITNOENT;
+	ptr--;
+	bit = fls64(tmp);
+	bit--;		/* fls64 always adds one to the bit count */
+	bit /= 2;	/* two bits per entry in the bitmap */
+	return (((const unsigned char *)ptr - buf) * GFS2_NBBY) + bit;
 }
 
 /**
@@ -831,6 +840,58 @@
 	spin_unlock(&sdp->sd_rindex_spin);
 }
 
+static void gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
+				    const struct gfs2_bitmap *bi)
+{
+	struct super_block *sb = sdp->sd_vfs;
+	struct block_device *bdev = sb->s_bdev;
+	const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize /
+					   bdev_hardsect_size(sb->s_bdev);
+	u64 blk;
+	sector_t start = 0;
+	sector_t nr_sects = 0;
+	int rv;
+	unsigned int x;
+
+	for (x = 0; x < bi->bi_len; x++) {
+		const u8 *orig = bi->bi_bh->b_data + bi->bi_offset + x;
+		const u8 *clone = bi->bi_clone + bi->bi_offset + x;
+		u8 diff = ~(*orig | (*orig >> 1)) & (*clone | (*clone >> 1));
+		diff &= 0x55;
+		if (diff == 0)
+			continue;
+		blk = offset + ((bi->bi_start + x) * GFS2_NBBY);
+		blk *= sects_per_blk; /* convert to sectors */
+		while(diff) {
+			if (diff & 1) {
+				if (nr_sects == 0)
+					goto start_new_extent;
+				if ((start + nr_sects) != blk) {
+					rv = blkdev_issue_discard(bdev, start,
+							    nr_sects, GFP_NOFS);
+					if (rv)
+						goto fail;
+					nr_sects = 0;
+start_new_extent:
+					start = blk;
+				}
+				nr_sects += sects_per_blk;
+			}
+			diff >>= 2;
+			blk += sects_per_blk;
+		}
+	}
+	if (nr_sects) {
+		rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS);
+		if (rv)
+			goto fail;
+	}
+	return;
+fail:
+	fs_warn(sdp, "error %d on discard request, turning discards off for this filesystem", rv);
+	sdp->sd_args.ar_discard = 0;
+}
+
 void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd)
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
@@ -841,6 +902,8 @@
 		struct gfs2_bitmap *bi = rgd->rd_bits + x;
 		if (!bi->bi_clone)
 			continue;
+		if (sdp->sd_args.ar_discard)
+			gfs2_rgrp_send_discards(sdp, rgd->rd_data0, bi);
 		memcpy(bi->bi_clone + bi->bi_offset,
 		       bi->bi_bh->b_data + bi->bi_offset, bi->bi_len);
 	}
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 141b781..601913e 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -15,7 +15,6 @@
 #include <linux/crc32.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/bio.h>
-#include <linux/lm_interface.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -339,7 +338,6 @@
 				    struct gfs2_holder *t_gh)
 {
 	struct gfs2_inode *ip;
-	struct gfs2_holder ji_gh;
 	struct gfs2_jdesc *jd;
 	struct lfcc *lfcc;
 	LIST_HEAD(list);
@@ -387,7 +385,6 @@
 		gfs2_glock_dq_uninit(&lfcc->gh);
 		kfree(lfcc);
 	}
-	gfs2_glock_dq_uninit(&ji_gh);
 	return error;
 }
 
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
index f6b8b00..91abdbe 100644
--- a/fs/gfs2/super.h
+++ b/fs/gfs2/super.h
@@ -14,7 +14,7 @@
 #include <linux/dcache.h>
 #include "incore.h"
 
-void gfs2_lm_unmount(struct gfs2_sbd *sdp);
+extern void gfs2_lm_unmount(struct gfs2_sbd *sdp);
 
 static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
 {
@@ -27,21 +27,23 @@
 
 void gfs2_jindex_free(struct gfs2_sbd *sdp);
 
-struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid);
-int gfs2_jdesc_check(struct gfs2_jdesc *jd);
+extern int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *data);
 
-int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename,
-			      struct gfs2_inode **ipp);
+extern struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid);
+extern int gfs2_jdesc_check(struct gfs2_jdesc *jd);
 
-int gfs2_make_fs_rw(struct gfs2_sbd *sdp);
+extern int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename,
+				     struct gfs2_inode **ipp);
 
-int gfs2_statfs_init(struct gfs2_sbd *sdp);
-void gfs2_statfs_change(struct gfs2_sbd *sdp,
-			s64 total, s64 free, s64 dinodes);
-int gfs2_statfs_sync(struct gfs2_sbd *sdp);
+extern int gfs2_make_fs_rw(struct gfs2_sbd *sdp);
 
-int gfs2_freeze_fs(struct gfs2_sbd *sdp);
-void gfs2_unfreeze_fs(struct gfs2_sbd *sdp);
+extern int gfs2_statfs_init(struct gfs2_sbd *sdp);
+extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
+			       s64 dinodes);
+extern int gfs2_statfs_sync(struct gfs2_sbd *sdp);
+
+extern int gfs2_freeze_fs(struct gfs2_sbd *sdp);
+extern void gfs2_unfreeze_fs(struct gfs2_sbd *sdp);
 
 extern struct file_system_type gfs2_fs_type;
 extern struct file_system_type gfs2meta_fs_type;
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index 26c1fa7..7655f502 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -14,9 +14,8 @@
 #include <linux/buffer_head.h>
 #include <linux/module.h>
 #include <linux/kobject.h>
-#include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <asm/uaccess.h>
+#include <linux/gfs2_ondisk.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -25,6 +24,7 @@
 #include "glock.h"
 #include "quota.h"
 #include "util.h"
+#include "glops.h"
 
 static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
 {
@@ -37,6 +37,30 @@
 	return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_fsname);
 }
 
+static int gfs2_uuid_valid(const u8 *uuid)
+{
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		if (uuid[i])
+			return 1;
+	}
+	return 0;
+}
+
+static ssize_t uuid_show(struct gfs2_sbd *sdp, char *buf)
+{
+	const u8 *uuid = sdp->sd_sb.sb_uuid;
+	buf[0] = '\0';
+	if (!gfs2_uuid_valid(uuid))
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%02X%02X%02X%02X-%02X%02X-"
+			"%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
+			uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
+			uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
+			uuid[12], uuid[13], uuid[14], uuid[15]);
+}
+
 static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf)
 {
 	unsigned int count;
@@ -148,6 +172,46 @@
 	return len;
 }
 
+static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
+{
+	struct gfs2_glock *gl;
+	const struct gfs2_glock_operations *glops;
+	unsigned int glmode;
+	unsigned int gltype;
+	unsigned long long glnum;
+	char mode[16];
+	int rv;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	rv = sscanf(buf, "%u:%llu %15s", &gltype, &glnum,
+		    mode);
+	if (rv != 3)
+		return -EINVAL;
+
+	if (strcmp(mode, "EX") == 0)
+		glmode = LM_ST_UNLOCKED;
+	else if ((strcmp(mode, "CW") == 0) || (strcmp(mode, "DF") == 0))
+		glmode = LM_ST_DEFERRED;
+	else if ((strcmp(mode, "PR") == 0) || (strcmp(mode, "SH") == 0))
+		glmode = LM_ST_SHARED;
+	else
+		return -EINVAL;
+
+	if (gltype > LM_TYPE_JOURNAL)
+		return -EINVAL;
+	glops = gfs2_glops_list[gltype];
+	if (glops == NULL)
+		return -EINVAL;
+	rv = gfs2_glock_get(sdp, glnum, glops, 0, &gl);
+	if (rv)
+		return rv;
+	gfs2_glock_cb(gl, glmode);
+	gfs2_glock_put(gl);
+	return len;
+}
+
 struct gfs2_attr {
 	struct attribute attr;
 	ssize_t (*show)(struct gfs2_sbd *, char *);
@@ -159,22 +223,26 @@
 
 GFS2_ATTR(id,                  0444, id_show,       NULL);
 GFS2_ATTR(fsname,              0444, fsname_show,   NULL);
+GFS2_ATTR(uuid,                0444, uuid_show,     NULL);
 GFS2_ATTR(freeze,              0644, freeze_show,   freeze_store);
 GFS2_ATTR(withdraw,            0644, withdraw_show, withdraw_store);
 GFS2_ATTR(statfs_sync,         0200, NULL,          statfs_sync_store);
 GFS2_ATTR(quota_sync,          0200, NULL,          quota_sync_store);
 GFS2_ATTR(quota_refresh_user,  0200, NULL,          quota_refresh_user_store);
 GFS2_ATTR(quota_refresh_group, 0200, NULL,          quota_refresh_group_store);
+GFS2_ATTR(demote_rq,           0200, NULL,	    demote_rq_store);
 
 static struct attribute *gfs2_attrs[] = {
 	&gfs2_attr_id.attr,
 	&gfs2_attr_fsname.attr,
+	&gfs2_attr_uuid.attr,
 	&gfs2_attr_freeze.attr,
 	&gfs2_attr_withdraw.attr,
 	&gfs2_attr_statfs_sync.attr,
 	&gfs2_attr_quota_sync.attr,
 	&gfs2_attr_quota_refresh_user.attr,
 	&gfs2_attr_quota_refresh_group.attr,
+	&gfs2_attr_demote_rq.attr,
 	NULL,
 };
 
@@ -224,14 +292,145 @@
 
 LOCKSTRUCT_ATTR(jid,      "%u\n");
 LOCKSTRUCT_ATTR(first,    "%u\n");
-LOCKSTRUCT_ATTR(lvb_size, "%u\n");
-LOCKSTRUCT_ATTR(flags,    "%d\n");
 
 static struct attribute *lockstruct_attrs[] = {
 	&lockstruct_attr_jid.attr,
 	&lockstruct_attr_first.attr,
-	&lockstruct_attr_lvb_size.attr,
-	&lockstruct_attr_flags.attr,
+	NULL,
+};
+
+/*
+ * lock_module. Originally from lock_dlm
+ */
+
+static ssize_t proto_name_show(struct gfs2_sbd *sdp, char *buf)
+{
+	const struct lm_lockops *ops = sdp->sd_lockstruct.ls_ops;
+	return sprintf(buf, "%s\n", ops->lm_proto_name);
+}
+
+static ssize_t block_show(struct gfs2_sbd *sdp, char *buf)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	ssize_t ret;
+	int val = 0;
+
+	if (test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))
+		val = 1;
+	ret = sprintf(buf, "%d\n", val);
+	return ret;
+}
+
+static ssize_t block_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	ssize_t ret = len;
+	int val;
+
+	val = simple_strtol(buf, NULL, 0);
+
+	if (val == 1)
+		set_bit(DFL_BLOCK_LOCKS, &ls->ls_flags);
+	else if (val == 0) {
+		clear_bit(DFL_BLOCK_LOCKS, &ls->ls_flags);
+		smp_mb__after_clear_bit();
+		gfs2_glock_thaw(sdp);
+	} else {
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static ssize_t lkid_show(struct gfs2_sbd *sdp, char *buf)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	return sprintf(buf, "%u\n", ls->ls_id);
+}
+
+static ssize_t lkfirst_show(struct gfs2_sbd *sdp, char *buf)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	return sprintf(buf, "%d\n", ls->ls_first);
+}
+
+static ssize_t first_done_show(struct gfs2_sbd *sdp, char *buf)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	return sprintf(buf, "%d\n", ls->ls_first_done);
+}
+
+static ssize_t recover_show(struct gfs2_sbd *sdp, char *buf)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	return sprintf(buf, "%d\n", ls->ls_recover_jid);
+}
+
+static void gfs2_jdesc_make_dirty(struct gfs2_sbd *sdp, unsigned int jid)
+{
+	struct gfs2_jdesc *jd;
+
+	spin_lock(&sdp->sd_jindex_spin);
+	list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
+		if (jd->jd_jid != jid)
+			continue;
+		jd->jd_dirty = 1;
+		break;
+	}
+	spin_unlock(&sdp->sd_jindex_spin);
+}
+
+static ssize_t recover_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	ls->ls_recover_jid = simple_strtol(buf, NULL, 0);
+	gfs2_jdesc_make_dirty(sdp, ls->ls_recover_jid);
+	if (sdp->sd_recoverd_process)
+		wake_up_process(sdp->sd_recoverd_process);
+	return len;
+}
+
+static ssize_t recover_done_show(struct gfs2_sbd *sdp, char *buf)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	return sprintf(buf, "%d\n", ls->ls_recover_jid_done);
+}
+
+static ssize_t recover_status_show(struct gfs2_sbd *sdp, char *buf)
+{
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	return sprintf(buf, "%d\n", ls->ls_recover_jid_status);
+}
+
+struct gdlm_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct gfs2_sbd *sdp, char *);
+	ssize_t (*store)(struct gfs2_sbd *sdp, const char *, size_t);
+};
+
+#define GDLM_ATTR(_name,_mode,_show,_store) \
+static struct gdlm_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store)
+
+GDLM_ATTR(proto_name,     0444, proto_name_show,     NULL);
+GDLM_ATTR(block,          0644, block_show,          block_store);
+GDLM_ATTR(withdraw,       0644, withdraw_show,       withdraw_store);
+GDLM_ATTR(id,             0444, lkid_show,           NULL);
+GDLM_ATTR(first,          0444, lkfirst_show,        NULL);
+GDLM_ATTR(first_done,     0444, first_done_show,     NULL);
+GDLM_ATTR(recover,        0644, recover_show,        recover_store);
+GDLM_ATTR(recover_done,   0444, recover_done_show,   NULL);
+GDLM_ATTR(recover_status, 0444, recover_status_show, NULL);
+
+static struct attribute *lock_module_attrs[] = {
+	&gdlm_attr_proto_name.attr,
+	&gdlm_attr_block.attr,
+	&gdlm_attr_withdraw.attr,
+	&gdlm_attr_id.attr,
+	&lockstruct_attr_jid.attr,
+	&gdlm_attr_first.attr,
+	&gdlm_attr_first_done.attr,
+	&gdlm_attr_recover.attr,
+	&gdlm_attr_recover_done.attr,
+	&gdlm_attr_recover_status.attr,
 	NULL,
 };
 
@@ -373,7 +572,6 @@
 TUNE_ATTR(statfs_slow, 0);
 TUNE_ATTR(new_files_jdata, 0);
 TUNE_ATTR(quota_simul_sync, 1);
-TUNE_ATTR(quota_cache_secs, 1);
 TUNE_ATTR(stall_secs, 1);
 TUNE_ATTR(statfs_quantum, 1);
 TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process);
@@ -389,7 +587,6 @@
 	&tune_attr_complain_secs.attr,
 	&tune_attr_statfs_slow.attr,
 	&tune_attr_quota_simul_sync.attr,
-	&tune_attr_quota_cache_secs.attr,
 	&tune_attr_stall_secs.attr,
 	&tune_attr_statfs_quantum.attr,
 	&tune_attr_recoverd_secs.attr,
@@ -414,6 +611,11 @@
 	.attrs = tune_attrs,
 };
 
+static struct attribute_group lock_module_group = {
+	.name = "lock_module",
+	.attrs = lock_module_attrs,
+};
+
 int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
 {
 	int error;
@@ -436,9 +638,15 @@
 	if (error)
 		goto fail_args;
 
+	error = sysfs_create_group(&sdp->sd_kobj, &lock_module_group);
+	if (error)
+		goto fail_tune;
+
 	kobject_uevent(&sdp->sd_kobj, KOBJ_ADD);
 	return 0;
 
+fail_tune:
+	sysfs_remove_group(&sdp->sd_kobj, &tune_group);
 fail_args:
 	sysfs_remove_group(&sdp->sd_kobj, &args_group);
 fail_lockstruct:
@@ -455,15 +663,27 @@
 	sysfs_remove_group(&sdp->sd_kobj, &tune_group);
 	sysfs_remove_group(&sdp->sd_kobj, &args_group);
 	sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
+	sysfs_remove_group(&sdp->sd_kobj, &lock_module_group);
 	kobject_put(&sdp->sd_kobj);
 }
 
+
 static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
 		       struct kobj_uevent_env *env)
 {
 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
+	const u8 *uuid = sdp->sd_sb.sb_uuid;
+
 	add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name);
 	add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
+	if (gfs2_uuid_valid(uuid)) {
+		add_uevent_var(env, "UUID=%02X%02X%02X%02X-%02X%02X-%02X%02X-"
+			       "%02X%02X-%02X%02X%02X%02X%02X%02X",
+			       uuid[0], uuid[1], uuid[2], uuid[3], uuid[4],
+			       uuid[5], uuid[6], uuid[7], uuid[8], uuid[9],
+			       uuid[10], uuid[11], uuid[12], uuid[13],
+			       uuid[14], uuid[15]);
+	}
 	return 0;
 }
 
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index f677b8a..053752d 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -12,9 +12,8 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
-#include <linux/gfs2_ondisk.h>
 #include <linux/kallsyms.h>
-#include <linux/lm_interface.h>
+#include <linux/gfs2_ondisk.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -88,9 +87,11 @@
 
 	if (!tr->tr_touched) {
 		gfs2_log_release(sdp, tr->tr_reserved);
-		gfs2_glock_dq(&tr->tr_t_gh);
-		gfs2_holder_uninit(&tr->tr_t_gh);
-		kfree(tr);
+		if (tr->tr_t_gh.gh_gl) {
+			gfs2_glock_dq(&tr->tr_t_gh);
+			gfs2_holder_uninit(&tr->tr_t_gh);
+			kfree(tr);
+		}
 		return;
 	}
 
@@ -106,9 +107,11 @@
 	}
 
 	gfs2_log_commit(sdp, tr);
-        gfs2_glock_dq(&tr->tr_t_gh);
-        gfs2_holder_uninit(&tr->tr_t_gh);
-        kfree(tr);
+	if (tr->tr_t_gh.gh_gl) {
+		gfs2_glock_dq(&tr->tr_t_gh);
+		gfs2_holder_uninit(&tr->tr_t_gh);
+		kfree(tr);
+	}
 
 	if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS)
 		gfs2_log_flush(sdp, NULL);
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 374f50e..9d12b11 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -13,7 +13,6 @@
 #include <linux/buffer_head.h>
 #include <linux/crc32.h>
 #include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
@@ -35,6 +34,8 @@
 
 int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
 {
+	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	const struct lm_lockops *lm = ls->ls_ops;
 	va_list args;
 
 	if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
@@ -47,8 +48,12 @@
 	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);
+	kobject_uevent(&sdp->sd_kobj, KOBJ_OFFLINE);
+
+	if (lm->lm_unmount) {
+		fs_err(sdp, "telling LM to unmount\n");
+		lm->lm_unmount(sdp);
+	}
 	fs_err(sdp, "withdrawn\n");
 	dump_stack();
 
diff --git a/fs/inode.c b/fs/inode.c
index 913ab2d..643ac43 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -17,6 +17,7 @@
 #include <linux/hash.h>
 #include <linux/swap.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/pagemap.h>
 #include <linux/cdev.h>
 #include <linux/bootmem.h>
@@ -147,13 +148,13 @@
 	inode->i_cdev = NULL;
 	inode->i_rdev = 0;
 	inode->dirtied_when = 0;
-	if (security_inode_alloc(inode)) {
-		if (inode->i_sb->s_op->destroy_inode)
-			inode->i_sb->s_op->destroy_inode(inode);
-		else
-			kmem_cache_free(inode_cachep, (inode));
-		return NULL;
-	}
+
+	if (security_inode_alloc(inode))
+		goto out_free_inode;
+
+	/* allocate and initialize an i_integrity */
+	if (ima_inode_alloc(inode))
+		goto out_free_security;
 
 	spin_lock_init(&inode->i_lock);
 	lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key);
@@ -189,6 +190,15 @@
 	inode->i_mapping = mapping;
 
 	return inode;
+
+out_free_security:
+	security_inode_free(inode);
+out_free_inode:
+	if (inode->i_sb->s_op->destroy_inode)
+		inode->i_sb->s_op->destroy_inode(inode);
+	else
+		kmem_cache_free(inode_cachep, (inode));
+	return NULL;
 }
 EXPORT_SYMBOL(inode_init_always);
 
@@ -359,6 +369,7 @@
 		invalidate_inode_buffers(inode);
 		if (!atomic_read(&inode->i_count)) {
 			list_move(&inode->i_list, dispose);
+			WARN_ON(inode->i_state & I_NEW);
 			inode->i_state |= I_FREEING;
 			count++;
 			continue;
@@ -460,6 +471,7 @@
 				continue;
 		}
 		list_move(&inode->i_list, &freeable);
+		WARN_ON(inode->i_state & I_NEW);
 		inode->i_state |= I_FREEING;
 		nr_pruned++;
 	}
@@ -656,6 +668,7 @@
 	 * just created it (so there can be no old holders
 	 * that haven't tested I_LOCK).
 	 */
+	WARN_ON((inode->i_state & (I_LOCK|I_NEW)) != (I_LOCK|I_NEW));
 	inode->i_state &= ~(I_LOCK|I_NEW);
 	wake_up_inode(inode);
 }
@@ -1145,6 +1158,7 @@
 
 	list_del_init(&inode->i_list);
 	list_del_init(&inode->i_sb_list);
+	WARN_ON(inode->i_state & I_NEW);
 	inode->i_state |= I_FREEING;
 	inodes_stat.nr_inodes--;
 	spin_unlock(&inode_lock);
@@ -1186,16 +1200,19 @@
 			spin_unlock(&inode_lock);
 			return;
 		}
+		WARN_ON(inode->i_state & I_NEW);
 		inode->i_state |= I_WILL_FREE;
 		spin_unlock(&inode_lock);
 		write_inode_now(inode, 1);
 		spin_lock(&inode_lock);
+		WARN_ON(inode->i_state & I_NEW);
 		inode->i_state &= ~I_WILL_FREE;
 		inodes_stat.nr_unused--;
 		hlist_del_init(&inode->i_hash);
 	}
 	list_del_init(&inode->i_list);
 	list_del_init(&inode->i_sb_list);
+	WARN_ON(inode->i_state & I_NEW);
 	inode->i_state |= I_FREEING;
 	inodes_stat.nr_inodes--;
 	spin_unlock(&inode_lock);
@@ -1283,6 +1300,40 @@
 }
 EXPORT_SYMBOL(bmap);
 
+/*
+ * With relative atime, only update atime if the previous atime is
+ * earlier than either the ctime or mtime or if at least a day has
+ * passed since the last atime update.
+ */
+static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
+			     struct timespec now)
+{
+
+	if (!(mnt->mnt_flags & MNT_RELATIME))
+		return 1;
+	/*
+	 * Is mtime younger than atime? If yes, update atime:
+	 */
+	if (timespec_compare(&inode->i_mtime, &inode->i_atime) >= 0)
+		return 1;
+	/*
+	 * Is ctime younger than atime? If yes, update atime:
+	 */
+	if (timespec_compare(&inode->i_ctime, &inode->i_atime) >= 0)
+		return 1;
+
+	/*
+	 * Is the previous atime value older than a day? If yes,
+	 * update atime:
+	 */
+	if ((long)(now.tv_sec - inode->i_atime.tv_sec) >= 24*60*60)
+		return 1;
+	/*
+	 * Good, we can skip the atime update:
+	 */
+	return 0;
+}
+
 /**
  *	touch_atime	-	update the access time
  *	@mnt: mount the inode is accessed on
@@ -1310,17 +1361,12 @@
 		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 (!relatime_need_update(mnt, inode, now))
+		goto out;
+
 	if (timespec_equal(&inode->i_atime, &now))
 		goto out;
 
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 1f3b0fc..aedc47a 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -139,6 +139,55 @@
 	return 0;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static const struct in6_addr *nlmclnt_map_v4addr(const struct sockaddr *sap,
+						 struct in6_addr *addr_mapped)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+
+	switch (sap->sa_family) {
+	case AF_INET6:
+		return &((const struct sockaddr_in6 *)sap)->sin6_addr;
+	case AF_INET:
+		ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, addr_mapped);
+		return addr_mapped;
+	}
+
+	return NULL;
+}
+
+/*
+ * If lockd is using a PF_INET6 listener, all incoming requests appear
+ * to come from AF_INET6 remotes.  The address of AF_INET remotes are
+ * mapped to AF_INET6 automatically by the network layer.  In case the
+ * user passed an AF_INET server address at mount time, ensure both
+ * addresses are AF_INET6 before comparing them.
+ */
+static int nlmclnt_cmp_addr(const struct nlm_host *host,
+			    const struct sockaddr *sap)
+{
+	const struct in6_addr *addr1;
+	const struct in6_addr *addr2;
+	struct in6_addr addr1_mapped;
+	struct in6_addr addr2_mapped;
+
+	addr1 = nlmclnt_map_v4addr(nlm_addr(host), &addr1_mapped);
+	if (likely(addr1 != NULL)) {
+		addr2 = nlmclnt_map_v4addr(sap, &addr2_mapped);
+		if (likely(addr2 != NULL))
+			return ipv6_addr_equal(addr1, addr2);
+	}
+
+	return 0;
+}
+#else	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
+static int nlmclnt_cmp_addr(const struct nlm_host *host,
+			    const struct sockaddr *sap)
+{
+	return nlm_cmp_addr(nlm_addr(host), sap);
+}
+#endif	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
+
 /*
  * The server lockd has called us back to tell us the lock was granted
  */
@@ -166,7 +215,7 @@
 		 */
 		if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
 			continue;
-		if (!nlm_cmp_addr(nlm_addr(block->b_host), addr))
+		if (!nlmclnt_cmp_addr(block->b_host, addr))
 			continue;
 		if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
 			continue;
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index d1d1eb8..618865b 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
- *  Copyright (C) 1996  Gertjan van Wingerde    (gertjan@cs.vu.nl)
+ *  Copyright (C) 1996  Gertjan van Wingerde
  *	Minix V2 fs support.
  *
  *  Modified for 680x0 by Andreas Schwab
diff --git a/fs/namei.c b/fs/namei.c
index bbc15c2..1993176 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -24,6 +24,7 @@
 #include <linux/fsnotify.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/syscalls.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
@@ -850,6 +851,8 @@
 		if (err == -EAGAIN)
 			err = inode_permission(nd->path.dentry->d_inode,
 					       MAY_EXEC);
+		if (!err)
+			err = ima_path_check(&nd->path, MAY_EXEC);
  		if (err)
 			break;
 
@@ -1509,6 +1512,11 @@
 	error = inode_permission(inode, acc_mode);
 	if (error)
 		return error;
+
+	error = ima_path_check(path,
+			       acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
+	if (error)
+		return error;
 	/*
 	 * An append-only file must be opened in append mode for writing.
 	 */
diff --git a/fs/namespace.c b/fs/namespace.c
index 06f8e63..f0e7530 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -780,6 +780,7 @@
 		{ MNT_NOATIME, ",noatime" },
 		{ MNT_NODIRATIME, ",nodiratime" },
 		{ MNT_RELATIME, ",relatime" },
+		{ MNT_STRICTATIME, ",strictatime" },
 		{ 0, NULL }
 	};
 	const struct proc_fs_info *fs_infop;
@@ -1919,6 +1920,9 @@
 	if (data_page)
 		((char *)data_page)[PAGE_SIZE - 1] = 0;
 
+	/* Default to relatime */
+	mnt_flags |= MNT_RELATIME;
+
 	/* Separate the per-mountpoint flags */
 	if (flags & MS_NOSUID)
 		mnt_flags |= MNT_NOSUID;
@@ -1930,13 +1934,14 @@
 		mnt_flags |= MNT_NOATIME;
 	if (flags & MS_NODIRATIME)
 		mnt_flags |= MNT_NODIRATIME;
-	if (flags & MS_RELATIME)
-		mnt_flags |= MNT_RELATIME;
+	if (flags & MS_STRICTATIME)
+		mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
 	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);
+		   MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
+		   MS_STRICTATIME);
 
 	/* ... and get the mountpoint */
 	retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 9b728f3..574158a 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -255,6 +255,32 @@
 	}
 	return 0;
 }
+
+/*
+ * Test if two ip6 socket addresses refer to the same socket by
+ * comparing relevant fields. The padding bytes specifically, are not
+ * compared. sin6_flowinfo is not compared because it only affects QoS
+ * and sin6_scope_id is only compared if the address is "link local"
+ * because "link local" addresses need only be unique to a specific
+ * link. Conversely, ordinary unicast addresses might have different
+ * sin6_scope_id.
+ *
+ * The caller should ensure both socket addresses are AF_INET6.
+ */
+static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1,
+				const struct sockaddr *sa2)
+{
+	const struct sockaddr_in6 *saddr1 = (const struct sockaddr_in6 *)sa1;
+	const struct sockaddr_in6 *saddr2 = (const struct sockaddr_in6 *)sa2;
+
+	if (!ipv6_addr_equal(&saddr1->sin6_addr,
+			     &saddr1->sin6_addr))
+		return 0;
+	if (ipv6_addr_scope(&saddr1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL &&
+	    saddr1->sin6_scope_id != saddr2->sin6_scope_id)
+		return 0;
+	return saddr1->sin6_port == saddr2->sin6_port;
+}
 #else
 static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
 				 const struct sockaddr_in *sa2)
@@ -270,9 +296,52 @@
 	return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
 			(const struct sockaddr_in *)sa2);
 }
+
+static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1,
+				const struct sockaddr * sa2)
+{
+	return 0;
+}
 #endif
 
 /*
+ * Test if two ip4 socket addresses refer to the same socket, by
+ * comparing relevant fields. The padding bytes specifically, are
+ * not compared.
+ *
+ * The caller should ensure both socket addresses are AF_INET.
+ */
+static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1,
+				const struct sockaddr *sa2)
+{
+	const struct sockaddr_in *saddr1 = (const struct sockaddr_in *)sa1;
+	const struct sockaddr_in *saddr2 = (const struct sockaddr_in *)sa2;
+
+	if (saddr1->sin_addr.s_addr != saddr2->sin_addr.s_addr)
+		return 0;
+	return saddr1->sin_port == saddr2->sin_port;
+}
+
+/*
+ * Test if two socket addresses represent the same actual socket,
+ * by comparing (only) relevant fields.
+ */
+static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
+			    const struct sockaddr *sa2)
+{
+	if (sa1->sa_family != sa2->sa_family)
+		return 0;
+
+	switch (sa1->sa_family) {
+	case AF_INET:
+		return nfs_sockaddr_cmp_ip4(sa1, sa2);
+	case AF_INET6:
+		return nfs_sockaddr_cmp_ip6(sa1, sa2);
+	}
+	return 0;
+}
+
+/*
  * Find a client by IP address and protocol version
  * - returns NULL if no such client
  */
@@ -344,8 +413,10 @@
 static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data)
 {
 	struct nfs_client *clp;
+	const struct sockaddr *sap = data->addr;
 
 	list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
+	        const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
 		/* Don't match clients that failed to initialise properly */
 		if (clp->cl_cons_state < 0)
 			continue;
@@ -358,7 +429,7 @@
 			continue;
 
 		/* Match the full socket address */
-		if (memcmp(&clp->cl_addr, data->addr, sizeof(clp->cl_addr)) != 0)
+		if (!nfs_sockaddr_cmp(sap, clap))
 			continue;
 
 		atomic_inc(&clp->cl_count);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e35c819..672368f 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1892,8 +1892,14 @@
 	cache.cred = cred;
 	cache.jiffies = jiffies;
 	status = NFS_PROTO(inode)->access(inode, &cache);
-	if (status != 0)
+	if (status != 0) {
+		if (status == -ESTALE) {
+			nfs_zap_caches(inode);
+			if (!S_ISDIR(inode->i_mode))
+				set_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
+		}
 		return status;
+	}
 	nfs_access_add_cache(inode, &cache);
 out:
 	if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index cef6255..6bbf0e6 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -292,7 +292,7 @@
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs_fattr fattr;
-	struct page *pages[NFSACL_MAXPAGES] = { };
+	struct page *pages[NFSACL_MAXPAGES];
 	struct nfs3_setaclargs args = {
 		.inode = inode,
 		.mask = NFS_ACL,
@@ -303,7 +303,7 @@
 		.rpc_argp	= &args,
 		.rpc_resp	= &fattr,
 	};
-	int status, count;
+	int status;
 
 	status = -EOPNOTSUPP;
 	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
@@ -319,6 +319,20 @@
 	if (S_ISDIR(inode->i_mode)) {
 		args.mask |= NFS_DFACL;
 		args.acl_default = dfacl;
+		args.len = nfsacl_size(acl, dfacl);
+	} else
+		args.len = nfsacl_size(acl, NULL);
+
+	if (args.len > NFS_ACL_INLINE_BUFSIZE) {
+		unsigned int npages = 1 + ((args.len - 1) >> PAGE_SHIFT);
+
+		status = -ENOMEM;
+		do {
+			args.pages[args.npages] = alloc_page(GFP_KERNEL);
+			if (args.pages[args.npages] == NULL)
+				goto out_freepages;
+			args.npages++;
+		} while (args.npages < npages);
 	}
 
 	dprintk("NFS call setacl\n");
@@ -329,10 +343,6 @@
 	nfs_zap_acl_cache(inode);
 	dprintk("NFS reply setacl: %d\n", status);
 
-	/* pages may have been allocated at the xdr layer. */
-	for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
-		__free_page(args.pages[count]);
-
 	switch (status) {
 		case 0:
 			status = nfs_refresh_inode(inode, &fattr);
@@ -346,6 +356,11 @@
 		case -ENOTSUPP:
 			status = -EOPNOTSUPP;
 	}
+out_freepages:
+	while (args.npages != 0) {
+		args.npages--;
+		__free_page(args.pages[args.npages]);
+	}
 out:
 	return status;
 }
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 11cddde..6cdeacf 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -82,8 +82,10 @@
 #define NFS3_commitres_sz	(1+NFS3_wcc_data_sz+2)
 
 #define ACL3_getaclargs_sz	(NFS3_fh_sz+1)
-#define ACL3_setaclargs_sz	(NFS3_fh_sz+1+2*(2+5*3))
-#define ACL3_getaclres_sz	(1+NFS3_post_op_attr_sz+1+2*(2+5*3))
+#define ACL3_setaclargs_sz	(NFS3_fh_sz+1+ \
+				XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
+#define ACL3_getaclres_sz	(1+NFS3_post_op_attr_sz+1+ \
+				XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
 #define ACL3_setaclres_sz	(1+NFS3_post_op_attr_sz)
 
 /*
@@ -703,28 +705,18 @@
                    struct nfs3_setaclargs *args)
 {
 	struct xdr_buf *buf = &req->rq_snd_buf;
-	unsigned int base, len_in_head, len = nfsacl_size(
-		(args->mask & NFS_ACL)   ? args->acl_access  : NULL,
-		(args->mask & NFS_DFACL) ? args->acl_default : NULL);
-	int count, err;
+	unsigned int base;
+	int err;
 
 	p = xdr_encode_fhandle(p, NFS_FH(args->inode));
 	*p++ = htonl(args->mask);
-	base = (char *)p - (char *)buf->head->iov_base;
-	/* put as much of the acls into head as possible. */
-	len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
-	len -= len_in_head;
-	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
+	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+	base = req->rq_slen;
 
-	for (count = 0; (count << PAGE_SHIFT) < len; count++) {
-		args->pages[count] = alloc_page(GFP_KERNEL);
-		if (!args->pages[count]) {
-			while (count)
-				__free_page(args->pages[--count]);
-			return -ENOMEM;
-		}
-	}
-	xdr_encode_pages(buf, args->pages, 0, len);
+	if (args->npages != 0)
+		xdr_encode_pages(buf, args->pages, 0, args->len);
+	else
+		req->rq_slen += args->len;
 
 	err = nfsacl_encode(buf, base, args->inode,
 			    (args->mask & NFS_ACL) ?
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 30befc3..2a2a0a7 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -21,7 +21,9 @@
 #define NFSDBG_FACILITY		NFSDBG_VFS
 
 /*
- * Check if fs_root is valid
+ * Convert the NFSv4 pathname components into a standard posix path.
+ *
+ * Note that the resulting string will be placed at the end of the buffer
  */
 static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname,
 					 char *buffer, ssize_t buflen)
@@ -99,21 +101,20 @@
 {
 	struct vfsmount *mnt = ERR_PTR(-ENOENT);
 	char *mnt_path;
-	int page2len;
+	unsigned int maxbuflen;
 	unsigned int s;
 
 	mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
 	if (IS_ERR(mnt_path))
 		return mnt;
 	mountdata->mnt_path = mnt_path;
-	page2 += strlen(mnt_path) + 1;
-	page2len = PAGE_SIZE - strlen(mnt_path) - 1;
+	maxbuflen = mnt_path - 1 - page2;
 
 	for (s = 0; s < location->nservers; s++) {
 		const struct nfs4_string *buf = &location->servers[s];
 		struct sockaddr_storage addr;
 
-		if (buf->len <= 0 || buf->len >= PAGE_SIZE)
+		if (buf->len <= 0 || buf->len >= maxbuflen)
 			continue;
 
 		mountdata->addr = (struct sockaddr *)&addr;
@@ -126,8 +127,8 @@
 			continue;
 		nfs_set_port(mountdata->addr, NFS_PORT);
 
-		strncpy(page2, buf->data, page2len);
-		page2[page2len] = '\0';
+		memcpy(page2, buf->data, buf->len);
+		page2[buf->len] = '\0';
 		mountdata->hostname = page2;
 
 		snprintf(page, PAGE_SIZE, "%s:%s",
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f65953be..9250067 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2596,6 +2596,7 @@
 	[OP_LOOKUPP]		= (nfsd4_enc)nfsd4_encode_noop,
 	[OP_NVERIFY]		= (nfsd4_enc)nfsd4_encode_noop,
 	[OP_OPEN]		= (nfsd4_enc)nfsd4_encode_open,
+	[OP_OPENATTR]		= (nfsd4_enc)nfsd4_encode_noop,
 	[OP_OPEN_CONFIRM]	= (nfsd4_enc)nfsd4_encode_open_confirm,
 	[OP_OPEN_DOWNGRADE]	= (nfsd4_enc)nfsd4_encode_open_downgrade,
 	[OP_PUTFH]		= (nfsd4_enc)nfsd4_encode_noop,
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 3a9e5de..19e3a96 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -176,7 +176,8 @@
 
 	BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL);
 	mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) &&
-			(OCFS2_I(inode)->ip_clusters != rec->e_cpos),
+			(OCFS2_I(inode)->ip_clusters !=
+			 le32_to_cpu(rec->e_cpos)),
 			"Device %s, asking for sparse allocation: inode %llu, "
 			"cpos %u, clusters %u\n",
 			osb->dev_str,
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index a067a6c..8e1709a 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -227,7 +227,7 @@
 	size = i_size_read(inode);
 
 	if (size > PAGE_CACHE_SIZE ||
-	    size > ocfs2_max_inline_data(inode->i_sb)) {
+	    size > ocfs2_max_inline_data_with_xattr(inode->i_sb, di)) {
 		ocfs2_error(inode->i_sb,
 			    "Inode %llu has with inline data has bad size: %Lu",
 			    (unsigned long long)OCFS2_I(inode)->ip_blkno,
@@ -1555,6 +1555,7 @@
 	int ret, written = 0;
 	loff_t end = pos + len;
 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
+	struct ocfs2_dinode *di = NULL;
 
 	mlog(0, "Inode %llu, write of %u bytes at off %llu. features: 0x%x\n",
 	     (unsigned long long)oi->ip_blkno, len, (unsigned long long)pos,
@@ -1587,7 +1588,9 @@
 	/*
 	 * Check whether the write can fit.
 	 */
-	if (mmap_page || end > ocfs2_max_inline_data(inode->i_sb))
+	di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
+	if (mmap_page ||
+	    end > ocfs2_max_inline_data_with_xattr(inode->i_sb, di))
 		return 0;
 
 do_inline_write:
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 084aba8..4b11762 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -532,7 +532,8 @@
 
 		fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL);
 
-		fe->id2.i_data.id_count = cpu_to_le16(ocfs2_max_inline_data(osb->sb));
+		fe->id2.i_data.id_count = cpu_to_le16(
+				ocfs2_max_inline_data_with_xattr(osb->sb, fe));
 	} else {
 		fel = &fe->id2.i_list;
 		fel->l_tree_depth = 0;
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index c7ae45a..2332ef7 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -1070,12 +1070,6 @@
 		 offsetof(struct ocfs2_dinode, id2.i_symlink);
 }
 
-static inline int ocfs2_max_inline_data(struct super_block *sb)
-{
-	return sb->s_blocksize -
-		offsetof(struct ocfs2_dinode, id2.i_data.id_data);
-}
-
 static inline int ocfs2_max_inline_data_with_xattr(struct super_block *sb,
 						   struct ocfs2_dinode *di)
 {
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 4ddd788..2563df8 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -547,8 +547,12 @@
 	 * when blocksize = 512, may reserve one more cluser for
 	 * xattr bucket, otherwise reserve one metadata block
 	 * for them is ok.
+	 * If this is a new directory with inline data,
+	 * we choose to reserve the entire inline area for
+	 * directory contents and force an external xattr block.
 	 */
 	if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE ||
+	    (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) ||
 	    (s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) {
 		ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac);
 		if (ret) {
@@ -4791,19 +4795,33 @@
 						char *val,
 						int value_len)
 {
-	int offset;
+	int ret, offset, block_off;
 	struct ocfs2_xattr_value_root *xv;
 	struct ocfs2_xattr_entry *xe = xs->here;
+	struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket);
+	void *base;
 
 	BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe));
 
-	offset = le16_to_cpu(xe->xe_name_offset) +
-		 OCFS2_XATTR_SIZE(xe->xe_name_len);
+	ret = ocfs2_xattr_bucket_get_name_value(inode, xh,
+						xe - xh->xh_entries,
+						&block_off,
+						&offset);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
 
-	xv = (struct ocfs2_xattr_value_root *)(xs->base + offset);
+	base = bucket_block(xs->bucket, block_off);
+	xv = (struct ocfs2_xattr_value_root *)(base + offset +
+		 OCFS2_XATTR_SIZE(xe->xe_name_len));
 
-	return __ocfs2_xattr_set_value_outside(inode, handle,
-					       xv, val, value_len);
+	ret = __ocfs2_xattr_set_value_outside(inode, handle,
+					      xv, val, value_len);
+	if (ret)
+		mlog_errno(ret);
+out:
+	return ret;
 }
 
 static int ocfs2_rm_xattr_cluster(struct inode *inode,
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 6d72024..38e337d 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -400,7 +400,7 @@
 	pdev->devt = devt;
 
 	/* delay uevent until 'holders' subdir is created */
-	pdev->uevent_suppress = 1;
+	dev_set_uevent_suppress(pdev, 1);
 	err = device_add(pdev);
 	if (err)
 		goto out_put;
@@ -410,7 +410,7 @@
 	if (!p->holder_dir)
 		goto out_del;
 
-	pdev->uevent_suppress = 0;
+	dev_set_uevent_suppress(pdev, 0);
 	if (flags & ADDPART_FLAG_WHOLEDISK) {
 		err = device_create_file(pdev, &dev_attr_whole_disk);
 		if (err)
@@ -422,7 +422,7 @@
 	rcu_assign_pointer(ptbl->part[partno], p);
 
 	/* suppress uevent if the disk supresses it */
-	if (!ddev->uevent_suppress)
+	if (!dev_get_uevent_suppress(pdev))
 		kobject_uevent(&pdev->kobj, KOBJ_ADD);
 
 	return p;
@@ -455,7 +455,7 @@
 	dev_set_name(ddev, disk->disk_name);
 
 	/* delay uevents, until we scanned partition table */
-	ddev->uevent_suppress = 1;
+	dev_set_uevent_suppress(ddev, 1);
 
 	if (device_add(ddev))
 		return;
@@ -490,7 +490,7 @@
 
 exit:
 	/* announce disk after possible partitions are created */
-	ddev->uevent_suppress = 0;
+	dev_set_uevent_suppress(ddev, 0);
 	kobject_uevent(&ddev->kobj, KOBJ_ADD);
 
 	/* announce possible partitions */
diff --git a/fs/pipe.c b/fs/pipe.c
index 3a48ba5..14f502b 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -699,12 +699,12 @@
 	int retval;
 
 	mutex_lock(&inode->i_mutex);
-
 	retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
-
-	if (retval >= 0)
+	if (retval >= 0) {
 		retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
-
+		if (retval < 0) /* this can happen only if on == T */
+			fasync_helper(-1, filp, 0, &pipe->fasync_readers);
+	}
 	mutex_unlock(&inode->i_mutex);
 
 	if (retval < 0)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 0c9de19..beaa0ce 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -3066,7 +3066,6 @@
 	int retval = -ENOENT;
 	ino_t ino;
 	int tid;
-	unsigned long pos = filp->f_pos;  /* avoiding "long long" filp->f_pos */
 	struct pid_namespace *ns;
 
 	task = get_proc_task(inode);
@@ -3083,18 +3082,18 @@
 		goto out_no_task;
 	retval = 0;
 
-	switch (pos) {
+	switch ((unsigned long)filp->f_pos) {
 	case 0:
 		ino = inode->i_ino;
-		if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
+		if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0)
 			goto out;
-		pos++;
+		filp->f_pos++;
 		/* fall through */
 	case 1:
 		ino = parent_ino(dentry);
-		if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
+		if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) < 0)
 			goto out;
-		pos++;
+		filp->f_pos++;
 		/* fall through */
 	}
 
@@ -3104,9 +3103,9 @@
 	ns = filp->f_dentry->d_sb->s_fs_info;
 	tid = (int)filp->f_version;
 	filp->f_version = 0;
-	for (task = first_tid(leader, tid, pos - 2, ns);
+	for (task = first_tid(leader, tid, filp->f_pos - 2, ns);
 	     task;
-	     task = next_tid(task), pos++) {
+	     task = next_tid(task), filp->f_pos++) {
 		tid = task_pid_nr_ns(task, ns);
 		if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) {
 			/* returning this tgid failed, save it as the first
@@ -3117,7 +3116,6 @@
 		}
 	}
 out:
-	filp->f_pos = pos;
 	put_task_struct(leader);
 out_no_task:
 	return retval;
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 2d13451..e998383 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -80,7 +80,7 @@
 #define KPF_RECLAIM    9
 #define KPF_BUDDY     10
 
-#define kpf_copy_bit(flags, srcpos, dstpos) (((flags >> srcpos) & 1) << dstpos)
+#define kpf_copy_bit(flags, dstpos, srcpos) (((flags >> srcpos) & 1) << dstpos)
 
 static ssize_t kpageflags_read(struct file *file, char __user *buf,
 			     size_t count, loff_t *ppos)
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index b9b567a..5d7c7ec 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -114,6 +114,9 @@
 		if (!pagevec_add(&lru_pvec, page))
 			__pagevec_lru_add_file(&lru_pvec);
 
+		/* prevent the page from being discarded on memory pressure */
+		SetPageDirty(page);
+
 		unlock_page(page);
 	}
 
@@ -126,6 +129,7 @@
 	return -EFBIG;
 
  add_error:
+	pagevec_lru_add_file(&lru_pvec);
 	page_cache_release(pages + loop);
 	for (loop++; loop < npages; loop++)
 		__free_page(pages + loop);
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index c837dfc..2a79603 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -80,7 +80,7 @@
  * generated a larger block - this does occasionally happen with zlib).
  */
 int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
-			int length, u64 *next_index, int srclength)
+			int length, u64 *next_index, int srclength, int pages)
 {
 	struct squashfs_sb_info *msblk = sb->s_fs_info;
 	struct buffer_head **bh;
@@ -184,7 +184,7 @@
 				offset = 0;
 			}
 
-			if (msblk->stream.avail_out == 0) {
+			if (msblk->stream.avail_out == 0 && page < pages) {
 				msblk->stream.next_out = buffer[page++];
 				msblk->stream.avail_out = PAGE_CACHE_SIZE;
 			}
@@ -201,25 +201,20 @@
 				zlib_init = 1;
 			}
 
-			zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH);
+			zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
 
 			if (msblk->stream.avail_in == 0 && k < b)
 				put_bh(bh[k++]);
 		} while (zlib_err == Z_OK);
 
 		if (zlib_err != Z_STREAM_END) {
-			ERROR("zlib_inflate returned unexpected result"
-				" 0x%x, srclength %d, avail_in %d,"
-				" avail_out %d\n", zlib_err, srclength,
-				msblk->stream.avail_in,
-				msblk->stream.avail_out);
+			ERROR("zlib_inflate error, data probably corrupt\n");
 			goto release_mutex;
 		}
 
 		zlib_err = zlib_inflateEnd(&msblk->stream);
 		if (zlib_err != Z_OK) {
-			ERROR("zlib_inflateEnd returned unexpected result 0x%x,"
-				" srclength %d\n", zlib_err, srclength);
+			ERROR("zlib_inflate error, data probably corrupt\n");
 			goto release_mutex;
 		}
 		length = msblk->stream.total_out;
@@ -268,7 +263,8 @@
 		put_bh(bh[k]);
 
 read_failure:
-	ERROR("sb_bread failed reading block 0x%llx\n", cur_index);
+	ERROR("squashfs_read_data failed to read block 0x%llx\n",
+					(unsigned long long) index);
 	kfree(bh);
 	return -EIO;
 }
diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
index f29eda1..1c4739e 100644
--- a/fs/squashfs/cache.c
+++ b/fs/squashfs/cache.c
@@ -119,7 +119,7 @@
 
 			entry->length = squashfs_read_data(sb, entry->data,
 				block, length, &entry->next_index,
-				cache->block_size);
+				cache->block_size, cache->pages);
 
 			spin_lock(&cache->lock);
 
@@ -406,7 +406,7 @@
 	for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE)
 		data[i] = buffer;
 	res = squashfs_read_data(sb, data, block, length |
-		SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length);
+		SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length, pages);
 	kfree(data);
 	return res;
 }
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index 7a63398..9101dbd 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -133,7 +133,8 @@
 	type = le16_to_cpu(sqshb_ino->inode_type);
 	switch (type) {
 	case SQUASHFS_REG_TYPE: {
-		unsigned int frag_offset, frag_size, frag;
+		unsigned int frag_offset, frag;
+		int frag_size;
 		u64 frag_blk;
 		struct squashfs_reg_inode *sqsh_ino = &squashfs_ino.reg;
 
@@ -175,7 +176,8 @@
 		break;
 	}
 	case SQUASHFS_LREG_TYPE: {
-		unsigned int frag_offset, frag_size, frag;
+		unsigned int frag_offset, frag;
+		int frag_size;
 		u64 frag_blk;
 		struct squashfs_lreg_inode *sqsh_ino = &squashfs_ino.lreg;
 
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 6b2515d..0e9feb6 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -34,7 +34,7 @@
 
 /* block.c */
 extern int squashfs_read_data(struct super_block *, void **, u64, int, u64 *,
-				int);
+				int, int);
 
 /* cache.c */
 extern struct squashfs_cache *squashfs_cache_init(char *, int, int);
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 071df5b..681ec0d 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -389,7 +389,7 @@
 		return err;
 	}
 
-	printk(KERN_INFO "squashfs: version 4.0 (2009/01/03) "
+	printk(KERN_INFO "squashfs: version 4.0 (2009/01/31) "
 		"Phillip Lougher\n");
 
 	return 0;
diff --git a/fs/super.c b/fs/super.c
index 8349ed6..6ce5014 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -371,8 +371,10 @@
 				continue;
 			if (!grab_super(old))
 				goto retry;
-			if (s)
+			if (s) {
+				up_write(&s->s_umount);
 				destroy_super(s);
+			}
 			return old;
 		}
 	}
@@ -387,6 +389,7 @@
 	err = set(s, data);
 	if (err) {
 		spin_unlock(&sb_lock);
+		up_write(&s->s_umount);
 		destroy_super(s);
 		return ERR_PTR(err);
 	}
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index f2c478c..07703d3 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -21,15 +21,28 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
+#include <linux/mm.h>
 
 #include <asm/uaccess.h>
 
 #include "sysfs.h"
 
+/*
+ * There's one bin_buffer for each open file.
+ *
+ * filp->private_data points to bin_buffer and
+ * sysfs_dirent->s_bin_attr.buffers points to a the bin_buffer s
+ * sysfs_dirent->s_bin_attr.buffers is protected by sysfs_bin_lock
+ */
+static DEFINE_MUTEX(sysfs_bin_lock);
+
 struct bin_buffer {
-	struct mutex	mutex;
-	void		*buffer;
-	int		mmapped;
+	struct mutex			mutex;
+	void				*buffer;
+	int				mmapped;
+	struct vm_operations_struct 	*vm_ops;
+	struct file			*file;
+	struct hlist_node		list;
 };
 
 static int
@@ -168,6 +181,175 @@
 	return count;
 }
 
+static void bin_vma_open(struct vm_area_struct *vma)
+{
+	struct file *file = vma->vm_file;
+	struct bin_buffer *bb = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+
+	if (!bb->vm_ops || !bb->vm_ops->open)
+		return;
+
+	if (!sysfs_get_active_two(attr_sd))
+		return;
+
+	bb->vm_ops->open(vma);
+
+	sysfs_put_active_two(attr_sd);
+}
+
+static void bin_vma_close(struct vm_area_struct *vma)
+{
+	struct file *file = vma->vm_file;
+	struct bin_buffer *bb = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+
+	if (!bb->vm_ops || !bb->vm_ops->close)
+		return;
+
+	if (!sysfs_get_active_two(attr_sd))
+		return;
+
+	bb->vm_ops->close(vma);
+
+	sysfs_put_active_two(attr_sd);
+}
+
+static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct file *file = vma->vm_file;
+	struct bin_buffer *bb = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	int ret;
+
+	if (!bb->vm_ops || !bb->vm_ops->fault)
+		return VM_FAULT_SIGBUS;
+
+	if (!sysfs_get_active_two(attr_sd))
+		return VM_FAULT_SIGBUS;
+
+	ret = bb->vm_ops->fault(vma, vmf);
+
+	sysfs_put_active_two(attr_sd);
+	return ret;
+}
+
+static int bin_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+	struct file *file = vma->vm_file;
+	struct bin_buffer *bb = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	int ret;
+
+	if (!bb->vm_ops)
+		return -EINVAL;
+
+	if (!bb->vm_ops->page_mkwrite)
+		return 0;
+
+	if (!sysfs_get_active_two(attr_sd))
+		return -EINVAL;
+
+	ret = bb->vm_ops->page_mkwrite(vma, page);
+
+	sysfs_put_active_two(attr_sd);
+	return ret;
+}
+
+static int bin_access(struct vm_area_struct *vma, unsigned long addr,
+		  void *buf, int len, int write)
+{
+	struct file *file = vma->vm_file;
+	struct bin_buffer *bb = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	int ret;
+
+	if (!bb->vm_ops || !bb->vm_ops->access)
+		return -EINVAL;
+
+	if (!sysfs_get_active_two(attr_sd))
+		return -EINVAL;
+
+	ret = bb->vm_ops->access(vma, addr, buf, len, write);
+
+	sysfs_put_active_two(attr_sd);
+	return ret;
+}
+
+#ifdef CONFIG_NUMA
+static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+{
+	struct file *file = vma->vm_file;
+	struct bin_buffer *bb = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	int ret;
+
+	if (!bb->vm_ops || !bb->vm_ops->set_policy)
+		return 0;
+
+	if (!sysfs_get_active_two(attr_sd))
+		return -EINVAL;
+
+	ret = bb->vm_ops->set_policy(vma, new);
+
+	sysfs_put_active_two(attr_sd);
+	return ret;
+}
+
+static struct mempolicy *bin_get_policy(struct vm_area_struct *vma,
+					unsigned long addr)
+{
+	struct file *file = vma->vm_file;
+	struct bin_buffer *bb = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	struct mempolicy *pol;
+
+	if (!bb->vm_ops || !bb->vm_ops->get_policy)
+		return vma->vm_policy;
+
+	if (!sysfs_get_active_two(attr_sd))
+		return vma->vm_policy;
+
+	pol = bb->vm_ops->get_policy(vma, addr);
+
+	sysfs_put_active_two(attr_sd);
+	return pol;
+}
+
+static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
+			const nodemask_t *to, unsigned long flags)
+{
+	struct file *file = vma->vm_file;
+	struct bin_buffer *bb = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	int ret;
+
+	if (!bb->vm_ops || !bb->vm_ops->migrate)
+		return 0;
+
+	if (!sysfs_get_active_two(attr_sd))
+		return 0;
+
+	ret = bb->vm_ops->migrate(vma, from, to, flags);
+
+	sysfs_put_active_two(attr_sd);
+	return ret;
+}
+#endif
+
+static struct vm_operations_struct bin_vm_ops = {
+	.open		= bin_vma_open,
+	.close		= bin_vma_close,
+	.fault		= bin_fault,
+	.page_mkwrite	= bin_page_mkwrite,
+	.access		= bin_access,
+#ifdef CONFIG_NUMA
+	.set_policy	= bin_set_policy,
+	.get_policy	= bin_get_policy,
+	.migrate	= bin_migrate,
+#endif
+};
+
 static int mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct bin_buffer *bb = file->private_data;
@@ -179,18 +361,37 @@
 	mutex_lock(&bb->mutex);
 
 	/* need attr_sd for attr, its parent for kobj */
+	rc = -ENODEV;
 	if (!sysfs_get_active_two(attr_sd))
-		return -ENODEV;
+		goto out_unlock;
 
 	rc = -EINVAL;
-	if (attr->mmap)
-		rc = attr->mmap(kobj, attr, vma);
+	if (!attr->mmap)
+		goto out_put;
 
-	if (rc == 0 && !bb->mmapped)
-		bb->mmapped = 1;
-	else
-		sysfs_put_active_two(attr_sd);
+	rc = attr->mmap(kobj, attr, vma);
+	if (rc)
+		goto out_put;
 
+	/*
+	 * PowerPC's pci_mmap of legacy_mem uses shmem_zero_setup()
+	 * to satisfy versions of X which crash if the mmap fails: that
+	 * substitutes a new vm_file, and we don't then want bin_vm_ops.
+	 */
+	if (vma->vm_file != file)
+		goto out_put;
+
+	rc = -EINVAL;
+	if (bb->mmapped && bb->vm_ops != vma->vm_ops)
+		goto out_put;
+
+	rc = 0;
+	bb->mmapped = 1;
+	bb->vm_ops = vma->vm_ops;
+	vma->vm_ops = &bin_vm_ops;
+out_put:
+	sysfs_put_active_two(attr_sd);
+out_unlock:
 	mutex_unlock(&bb->mutex);
 
 	return rc;
@@ -223,8 +424,13 @@
 		goto err_out;
 
 	mutex_init(&bb->mutex);
+	bb->file = file;
 	file->private_data = bb;
 
+	mutex_lock(&sysfs_bin_lock);
+	hlist_add_head(&bb->list, &attr_sd->s_bin_attr.buffers);
+	mutex_unlock(&sysfs_bin_lock);
+
 	/* open succeeded, put active references */
 	sysfs_put_active_two(attr_sd);
 	return 0;
@@ -237,11 +443,12 @@
 
 static int release(struct inode * inode, struct file * file)
 {
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	struct bin_buffer *bb = file->private_data;
 
-	if (bb->mmapped)
-		sysfs_put_active_two(attr_sd);
+	mutex_lock(&sysfs_bin_lock);
+	hlist_del(&bb->list);
+	mutex_unlock(&sysfs_bin_lock);
+
 	kfree(bb->buffer);
 	kfree(bb);
 	return 0;
@@ -256,6 +463,26 @@
 	.release	= release,
 };
 
+
+void unmap_bin_file(struct sysfs_dirent *attr_sd)
+{
+	struct bin_buffer *bb;
+	struct hlist_node *tmp;
+
+	if (sysfs_type(attr_sd) != SYSFS_KOBJ_BIN_ATTR)
+		return;
+
+	mutex_lock(&sysfs_bin_lock);
+
+	hlist_for_each_entry(bb, tmp, &attr_sd->s_bin_attr.buffers, list) {
+		struct inode *inode = bb->file->f_path.dentry->d_inode;
+
+		unmap_mapping_range(inode->i_mapping, 0, 0, 1);
+	}
+
+	mutex_unlock(&sysfs_bin_lock);
+}
+
 /**
  *	sysfs_create_bin_file - create binary file for object.
  *	@kobj:	object.
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 82d3b79..66aeb4f 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -434,6 +434,26 @@
 }
 
 /**
+ *	sysfs_pathname - return full path to sysfs dirent
+ *	@sd: sysfs_dirent whose path we want
+ *	@path: caller allocated buffer
+ *
+ *	Gives the name "/" to the sysfs_root entry; any path returned
+ *	is relative to wherever sysfs is mounted.
+ *
+ *	XXX: does no error checking on @path size
+ */
+static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
+{
+	if (sd->s_parent) {
+		sysfs_pathname(sd->s_parent, path);
+		strcat(path, "/");
+	}
+	strcat(path, sd->s_name);
+	return path;
+}
+
+/**
  *	sysfs_add_one - add sysfs_dirent to parent
  *	@acxt: addrm context to use
  *	@sd: sysfs_dirent to be added
@@ -458,8 +478,16 @@
 	int ret;
 
 	ret = __sysfs_add_one(acxt, sd);
-	WARN(ret == -EEXIST, KERN_WARNING "sysfs: duplicate filename '%s' "
-		       "can not be created\n", sd->s_name);
+	if (ret == -EEXIST) {
+		char *path = kzalloc(PATH_MAX, GFP_KERNEL);
+		WARN(1, KERN_WARNING
+		     "sysfs: cannot create duplicate filename '%s'\n",
+		     (path == NULL) ? sd->s_name :
+		     strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"),
+		            sd->s_name));
+		kfree(path);
+	}
+
 	return ret;
 }
 
@@ -581,6 +609,7 @@
 
 		sysfs_drop_dentry(sd);
 		sysfs_deactivate(sd);
+		unmap_bin_file(sd);
 		sysfs_put(sd);
 	}
 }
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 1f4a3f8..289c43a 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -659,13 +659,16 @@
 EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
 
 struct sysfs_schedule_callback_struct {
-	struct kobject 		*kobj;
+	struct list_head	workq_list;
+	struct kobject		*kobj;
 	void			(*func)(void *);
 	void			*data;
 	struct module		*owner;
 	struct work_struct	work;
 };
 
+static DEFINE_MUTEX(sysfs_workq_mutex);
+static LIST_HEAD(sysfs_workq);
 static void sysfs_schedule_callback_work(struct work_struct *work)
 {
 	struct sysfs_schedule_callback_struct *ss = container_of(work,
@@ -674,6 +677,9 @@
 	(ss->func)(ss->data);
 	kobject_put(ss->kobj);
 	module_put(ss->owner);
+	mutex_lock(&sysfs_workq_mutex);
+	list_del(&ss->workq_list);
+	mutex_unlock(&sysfs_workq_mutex);
 	kfree(ss);
 }
 
@@ -695,15 +701,25 @@
  * until @func returns.
  *
  * Returns 0 if the request was submitted, -ENOMEM if storage could not
- * be allocated, -ENODEV if a reference to @owner isn't available.
+ * be allocated, -ENODEV if a reference to @owner isn't available,
+ * -EAGAIN if a callback has already been scheduled for @kobj.
  */
 int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
 		void *data, struct module *owner)
 {
-	struct sysfs_schedule_callback_struct *ss;
+	struct sysfs_schedule_callback_struct *ss, *tmp;
 
 	if (!try_module_get(owner))
 		return -ENODEV;
+
+	mutex_lock(&sysfs_workq_mutex);
+	list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list)
+		if (ss->kobj == kobj) {
+			mutex_unlock(&sysfs_workq_mutex);
+			return -EAGAIN;
+		}
+	mutex_unlock(&sysfs_workq_mutex);
+
 	ss = kmalloc(sizeof(*ss), GFP_KERNEL);
 	if (!ss) {
 		module_put(owner);
@@ -715,6 +731,10 @@
 	ss->data = data;
 	ss->owner = owner;
 	INIT_WORK(&ss->work, sysfs_schedule_callback_work);
+	INIT_LIST_HEAD(&ss->workq_list);
+	mutex_lock(&sysfs_workq_mutex);
+	list_add_tail(&ss->workq_list, &sysfs_workq);
+	mutex_unlock(&sysfs_workq_mutex);
 	schedule_work(&ss->work);
 	return 0;
 }
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index dfa3d94..555f0ff 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -147,6 +147,7 @@
 {
 	struct bin_attribute *bin_attr;
 
+	inode->i_private = sysfs_get(sd);
 	inode->i_mapping->a_ops = &sysfs_aops;
 	inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
 	inode->i_op = &sysfs_inode_operations;
@@ -214,6 +215,22 @@
 	return inode;
 }
 
+/*
+ * The sysfs_dirent serves as both an inode and a directory entry for sysfs.
+ * To prevent the sysfs inode numbers from being freed prematurely we take a
+ * reference to sysfs_dirent from the sysfs inode.  A
+ * super_operations.delete_inode() implementation is needed to drop that
+ * reference upon inode destruction.
+ */
+void sysfs_delete_inode(struct inode *inode)
+{
+	struct sysfs_dirent *sd  = inode->i_private;
+
+	truncate_inode_pages(&inode->i_data, 0);
+	clear_inode(inode);
+	sysfs_put(sd);
+}
+
 int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
 {
 	struct sysfs_addrm_cxt acxt;
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index ab343e3..4974995 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -17,11 +17,10 @@
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/magic.h>
 
 #include "sysfs.h"
 
-/* Random magic number */
-#define SYSFS_MAGIC 0x62656572
 
 static struct vfsmount *sysfs_mount;
 struct super_block * sysfs_sb = NULL;
@@ -30,6 +29,7 @@
 static const struct super_operations sysfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
+	.delete_inode	= sysfs_delete_inode,
 };
 
 struct sysfs_dirent sysfs_root = {
@@ -53,7 +53,9 @@
 	sysfs_sb = sb;
 
 	/* get root inode, initialize and unlock it */
+	mutex_lock(&sysfs_mutex);
 	inode = sysfs_get_inode(&sysfs_root);
+	mutex_unlock(&sysfs_mutex);
 	if (!inode) {
 		pr_debug("sysfs: could not get root inode\n");
 		return -ENOMEM;
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 93c6d6b..3fa0d984 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -28,6 +28,7 @@
 
 struct sysfs_elem_bin_attr {
 	struct bin_attribute	*bin_attr;
+	struct hlist_head	buffers;
 };
 
 /*
@@ -145,6 +146,7 @@
  * inode.c
  */
 struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
+void sysfs_delete_inode(struct inode *inode);
 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
 int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
 int sysfs_inode_init(void);
@@ -163,6 +165,7 @@
  * bin.c
  */
 extern const struct file_operations bin_fops;
+void unmap_bin_file(struct sysfs_dirent *attr_sd);
 
 /*
  * symlink.c
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index e65212d..261a1c2 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -41,7 +41,7 @@
  * Stefan Reinauer <stepan@home.culture.mipt.ru>
  *
  * Module usage counts added on 96/04/29 by
- * Gertjan van Wingerde <gertjan@cs.vu.nl>
+ * Gertjan van Wingerde <gwingerde@gmail.com>
  *
  * Clean swab support on 19970406 by
  * Francois-Rene Rideau <fare@tunes.org>
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index cb329ed..aa1016b 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -34,6 +34,12 @@
 #include <linux/backing-dev.h>
 #include <linux/freezer.h>
 
+#include "xfs_sb.h"
+#include "xfs_inum.h"
+#include "xfs_ag.h"
+#include "xfs_dmapi.h"
+#include "xfs_mount.h"
+
 static kmem_zone_t *xfs_buf_zone;
 STATIC int xfsbufd(void *);
 STATIC int xfsbufd_wakeup(int, gfp_t);
@@ -1435,10 +1441,12 @@
 
 void
 xfs_free_buftarg(
-	xfs_buftarg_t		*btp)
+	struct xfs_mount	*mp,
+	struct xfs_buftarg	*btp)
 {
 	xfs_flush_buftarg(btp, 1);
-	xfs_blkdev_issue_flush(btp);
+	if (mp->m_flags & XFS_MOUNT_BARRIER)
+		xfs_blkdev_issue_flush(btp);
 	xfs_free_bufhash(btp);
 	iput(btp->bt_mapping->host);
 
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 288ae7c..9b4d666 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -413,7 +413,7 @@
  *	Handling of buftargs.
  */
 extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int);
-extern void xfs_free_buftarg(xfs_buftarg_t *);
+extern void xfs_free_buftarg(struct xfs_mount *, struct xfs_buftarg *);
 extern void xfs_wait_buftarg(xfs_buftarg_t *);
 extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
 extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index c71e226..32ae502 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -734,15 +734,15 @@
 {
 	if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
 		struct block_device *logdev = mp->m_logdev_targp->bt_bdev;
-		xfs_free_buftarg(mp->m_logdev_targp);
+		xfs_free_buftarg(mp, mp->m_logdev_targp);
 		xfs_blkdev_put(logdev);
 	}
 	if (mp->m_rtdev_targp) {
 		struct block_device *rtdev = mp->m_rtdev_targp->bt_bdev;
-		xfs_free_buftarg(mp->m_rtdev_targp);
+		xfs_free_buftarg(mp, mp->m_rtdev_targp);
 		xfs_blkdev_put(rtdev);
 	}
-	xfs_free_buftarg(mp->m_ddev_targp);
+	xfs_free_buftarg(mp, mp->m_ddev_targp);
 }
 
 /*
@@ -811,9 +811,9 @@
 
  out_free_rtdev_targ:
 	if (mp->m_rtdev_targp)
-		xfs_free_buftarg(mp->m_rtdev_targp);
+		xfs_free_buftarg(mp, mp->m_rtdev_targp);
  out_free_ddev_targ:
-	xfs_free_buftarg(mp->m_ddev_targp);
+	xfs_free_buftarg(mp, mp->m_ddev_targp);
  out_close_rtdev:
 	if (rtdev)
 		xfs_blkdev_put(rtdev);
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index e2fb621..478e587 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -246,9 +246,6 @@
 		goto out_destroy;
 	}
 
-	if (lock_flags)
-		xfs_ilock(ip, lock_flags);
-
 	/*
 	 * Preload the radix tree so we can insert safely under the
 	 * write spinlock. Note that we cannot sleep inside the preload
@@ -256,7 +253,16 @@
 	 */
 	if (radix_tree_preload(GFP_KERNEL)) {
 		error = EAGAIN;
-		goto out_unlock;
+		goto out_destroy;
+	}
+
+	/*
+	 * Because the inode hasn't been added to the radix-tree yet it can't
+	 * be found by another thread, so we can do the non-sleeping lock here.
+	 */
+	if (lock_flags) {
+		if (!xfs_ilock_nowait(ip, lock_flags))
+			BUG();
 	}
 
 	mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
@@ -284,7 +290,6 @@
 out_preload_end:
 	write_unlock(&pag->pag_ici_lock);
 	radix_tree_preload_end();
-out_unlock:
 	if (lock_flags)
 		xfs_iunlock(ip, lock_flags);
 out_destroy:
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index b1047de..61af610 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1455,10 +1455,19 @@
 	item = item->ri_prev;
 
 	if (item->ri_total == 0) {		/* first region to be added */
-		item->ri_total	= in_f->ilf_size;
-		ASSERT(item->ri_total <= XLOG_MAX_REGIONS_IN_ITEM);
-		item->ri_buf = kmem_zalloc((item->ri_total *
-					    sizeof(xfs_log_iovec_t)), KM_SLEEP);
+		if (in_f->ilf_size == 0 ||
+		    in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) {
+			xlog_warn(
+	"XFS: bad number of regions (%d) in inode log format",
+				  in_f->ilf_size);
+			ASSERT(0);
+			return XFS_ERROR(EIO);
+		}
+
+		item->ri_total = in_f->ilf_size;
+		item->ri_buf =
+			kmem_zalloc(item->ri_total * sizeof(xfs_log_iovec_t),
+				    KM_SLEEP);
 	}
 	ASSERT(item->ri_total > item->ri_cnt);
 	/* Description region is ri_buf[0] */
diff --git a/include/asm-frv/ide.h b/include/asm-frv/ide.h
deleted file mode 100644
index 3610766..0000000
--- a/include/asm-frv/ide.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* ide.h: FRV IDE declarations
- *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef _ASM_IDE_H
-#define _ASM_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/setup.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_IDE_H */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index c61fab1..aca40b9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -80,6 +80,11 @@
 	VMLINUX_SYMBOL(__start___tracepoints) = .;			\
 	*(__tracepoints)						\
 	VMLINUX_SYMBOL(__stop___tracepoints) = .;			\
+	/* implement dynamic printk debug */				\
+	. = ALIGN(8);							\
+	VMLINUX_SYMBOL(__start___verbose) = .;                          \
+	*(__verbose)                                                    \
+	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()
 
@@ -309,15 +314,7 @@
 	CPU_DISCARD(init.data)						\
 	CPU_DISCARD(init.rodata)					\
 	MEM_DISCARD(init.data)						\
-	MEM_DISCARD(init.rodata)					\
-	/* implement dynamic printk debug */				\
-	VMLINUX_SYMBOL(__start___verbose_strings) = .;                  \
-	*(__verbose_strings)                                            \
-	VMLINUX_SYMBOL(__stop___verbose_strings) = .;                   \
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	*(__verbose)                                                    \
-	VMLINUX_SYMBOL(__stop___verbose) = .;
+	MEM_DISCARD(init.rodata)
 
 #define INIT_TEXT							\
 	*(.init.text)							\
diff --git a/include/asm-mn10300/ide.h b/include/asm-mn10300/ide.h
deleted file mode 100644
index 6adcdd9..0000000
--- a/include/asm-mn10300/ide.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* MN10300 Arch-specific IDE code
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- * - Derived from include/asm-i386/ide.h
- *
- * 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_IDE_H
-#define _ASM_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/intctl-regs.h>
-
-#undef SUPPORT_SLOW_DATA_PORTS
-#define SUPPORT_SLOW_DATA_PORTS 0
-
-#undef SUPPORT_VLB_SYNC
-#define SUPPORT_VLB_SYNC 0
-
-/*
- * some bits needed for parts of the IDE subsystem to compile
- */
-#define __ide_mm_insw(port, addr, n) \
-	insw((unsigned long) (port), (addr), (n))
-#define __ide_mm_insl(port, addr, n) \
-	insl((unsigned long) (port), (addr), (n))
-#define __ide_mm_outsw(port, addr, n) \
-	outsw((unsigned long) (port), (addr), (n))
-#define __ide_mm_outsl(port, addr, n) \
-	outsl((unsigned long) (port), (addr), (n))
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_IDE_H */
diff --git a/include/asm-mn10300/pci.h b/include/asm-mn10300/pci.h
index cd9cc5c..0517b45 100644
--- a/include/asm-mn10300/pci.h
+++ b/include/asm-mn10300/pci.h
@@ -121,4 +121,9 @@
 
 #define pcibios_scan_all_fns(a, b)	0
 
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+	return channel ? 15 : 14;
+}
+
 #endif /* _ASM_PCI_H */
diff --git a/include/crypto/aes.h b/include/crypto/aes.h
index 656a4c6..7524ba3 100644
--- a/include/crypto/aes.h
+++ b/include/crypto/aes.h
@@ -17,10 +17,14 @@
 #define AES_MAX_KEYLENGTH	(15 * 16)
 #define AES_MAX_KEYLENGTH_U32	(AES_MAX_KEYLENGTH / sizeof(u32))
 
+/*
+ * Please ensure that the first two fields are 16-byte aligned
+ * relative to the start of the structure, i.e., don't move them!
+ */
 struct crypto_aes_ctx {
-	u32 key_length;
 	u32 key_enc[AES_MAX_KEYLENGTH_U32];
 	u32 key_dec[AES_MAX_KEYLENGTH_U32];
+	u32 key_length;
 };
 
 extern const u32 crypto_ft_tab[4][256];
diff --git a/include/crypto/compress.h b/include/crypto/compress.h
new file mode 100644
index 0000000..86163ef
--- /dev/null
+++ b/include/crypto/compress.h
@@ -0,0 +1,145 @@
+/*
+ * Compress: Compression algorithms under the cryptographic API.
+ *
+ * Copyright 2008 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CRYPTO_COMPRESS_H
+#define _CRYPTO_COMPRESS_H
+
+#include <linux/crypto.h>
+
+
+struct comp_request {
+	const void *next_in;		/* next input byte */
+	void *next_out;			/* next output byte */
+	unsigned int avail_in;		/* bytes available at next_in */
+	unsigned int avail_out;		/* bytes available at next_out */
+};
+
+enum zlib_comp_params {
+	ZLIB_COMP_LEVEL = 1,		/* e.g. Z_DEFAULT_COMPRESSION */
+	ZLIB_COMP_METHOD,		/* e.g. Z_DEFLATED */
+	ZLIB_COMP_WINDOWBITS,		/* e.g. MAX_WBITS */
+	ZLIB_COMP_MEMLEVEL,		/* e.g. DEF_MEM_LEVEL */
+	ZLIB_COMP_STRATEGY,		/* e.g. Z_DEFAULT_STRATEGY */
+	__ZLIB_COMP_MAX,
+};
+
+#define ZLIB_COMP_MAX	(__ZLIB_COMP_MAX - 1)
+
+
+enum zlib_decomp_params {
+	ZLIB_DECOMP_WINDOWBITS = 1,	/* e.g. DEF_WBITS */
+	__ZLIB_DECOMP_MAX,
+};
+
+#define ZLIB_DECOMP_MAX	(__ZLIB_DECOMP_MAX - 1)
+
+
+struct crypto_pcomp {
+	struct crypto_tfm base;
+};
+
+struct pcomp_alg {
+	int (*compress_setup)(struct crypto_pcomp *tfm, void *params,
+			      unsigned int len);
+	int (*compress_init)(struct crypto_pcomp *tfm);
+	int (*compress_update)(struct crypto_pcomp *tfm,
+			       struct comp_request *req);
+	int (*compress_final)(struct crypto_pcomp *tfm,
+			      struct comp_request *req);
+	int (*decompress_setup)(struct crypto_pcomp *tfm, void *params,
+				unsigned int len);
+	int (*decompress_init)(struct crypto_pcomp *tfm);
+	int (*decompress_update)(struct crypto_pcomp *tfm,
+				 struct comp_request *req);
+	int (*decompress_final)(struct crypto_pcomp *tfm,
+				struct comp_request *req);
+
+	struct crypto_alg base;
+};
+
+extern struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name, u32 type,
+					       u32 mask);
+
+static inline struct crypto_tfm *crypto_pcomp_tfm(struct crypto_pcomp *tfm)
+{
+	return &tfm->base;
+}
+
+static inline void crypto_free_pcomp(struct crypto_pcomp *tfm)
+{
+	crypto_destroy_tfm(tfm, crypto_pcomp_tfm(tfm));
+}
+
+static inline struct pcomp_alg *__crypto_pcomp_alg(struct crypto_alg *alg)
+{
+	return container_of(alg, struct pcomp_alg, base);
+}
+
+static inline struct pcomp_alg *crypto_pcomp_alg(struct crypto_pcomp *tfm)
+{
+	return __crypto_pcomp_alg(crypto_pcomp_tfm(tfm)->__crt_alg);
+}
+
+static inline int crypto_compress_setup(struct crypto_pcomp *tfm,
+					void *params, unsigned int len)
+{
+	return crypto_pcomp_alg(tfm)->compress_setup(tfm, params, len);
+}
+
+static inline int crypto_compress_init(struct crypto_pcomp *tfm)
+{
+	return crypto_pcomp_alg(tfm)->compress_init(tfm);
+}
+
+static inline int crypto_compress_update(struct crypto_pcomp *tfm,
+					 struct comp_request *req)
+{
+	return crypto_pcomp_alg(tfm)->compress_update(tfm, req);
+}
+
+static inline int crypto_compress_final(struct crypto_pcomp *tfm,
+					struct comp_request *req)
+{
+	return crypto_pcomp_alg(tfm)->compress_final(tfm, req);
+}
+
+static inline int crypto_decompress_setup(struct crypto_pcomp *tfm,
+					  void *params, unsigned int len)
+{
+	return crypto_pcomp_alg(tfm)->decompress_setup(tfm, params, len);
+}
+
+static inline int crypto_decompress_init(struct crypto_pcomp *tfm)
+{
+	return crypto_pcomp_alg(tfm)->decompress_init(tfm);
+}
+
+static inline int crypto_decompress_update(struct crypto_pcomp *tfm,
+					   struct comp_request *req)
+{
+	return crypto_pcomp_alg(tfm)->decompress_update(tfm, req);
+}
+
+static inline int crypto_decompress_final(struct crypto_pcomp *tfm,
+					  struct comp_request *req)
+{
+	return crypto_pcomp_alg(tfm)->decompress_final(tfm, req);
+}
+
+#endif	/* _CRYPTO_COMPRESS_H */
diff --git a/include/crypto/cryptd.h b/include/crypto/cryptd.h
new file mode 100644
index 0000000..55fa7bb
--- /dev/null
+++ b/include/crypto/cryptd.h
@@ -0,0 +1,27 @@
+/*
+ * Software async crypto daemon
+ */
+
+#ifndef _CRYPTO_CRYPT_H
+#define _CRYPTO_CRYPT_H
+
+#include <linux/crypto.h>
+#include <linux/kernel.h>
+
+struct cryptd_ablkcipher {
+	struct crypto_ablkcipher base;
+};
+
+static inline struct cryptd_ablkcipher *__cryptd_ablkcipher_cast(
+	struct crypto_ablkcipher *tfm)
+{
+	return (struct cryptd_ablkcipher *)tfm;
+}
+
+/* alg_name should be algorithm to be cryptd-ed */
+struct cryptd_ablkcipher *cryptd_alloc_ablkcipher(const char *alg_name,
+						  u32 type, u32 mask);
+struct crypto_blkcipher *cryptd_ablkcipher_child(struct cryptd_ablkcipher *tfm);
+void cryptd_free_ablkcipher(struct cryptd_ablkcipher *tfm);
+
+#endif
diff --git a/include/crypto/crypto_wq.h b/include/crypto/crypto_wq.h
new file mode 100644
index 0000000..a7d252d
--- /dev/null
+++ b/include/crypto/crypto_wq.h
@@ -0,0 +1,7 @@
+#ifndef CRYPTO_WQ_H
+#define CRYPTO_WQ_H
+
+#include <linux/workqueue.h>
+
+extern struct workqueue_struct *kcrypto_wq;
+#endif
diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index d797e11..d56bb71 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -231,6 +231,11 @@
 	return crypto_tfm_alg_alignmask(crypto_shash_tfm(tfm));
 }
 
+static inline unsigned int crypto_shash_blocksize(struct crypto_shash *tfm)
+{
+	return crypto_tfm_alg_blocksize(crypto_shash_tfm(tfm));
+}
+
 static inline struct shash_alg *__crypto_shash_alg(struct crypto_alg *alg)
 {
 	return container_of(alg, struct shash_alg, base);
diff --git a/include/crypto/internal/compress.h b/include/crypto/internal/compress.h
new file mode 100644
index 0000000..178a888
--- /dev/null
+++ b/include/crypto/internal/compress.h
@@ -0,0 +1,28 @@
+/*
+ * Compress: Compression algorithms under the cryptographic API.
+ *
+ * Copyright 2008 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CRYPTO_INTERNAL_COMPRESS_H
+#define _CRYPTO_INTERNAL_COMPRESS_H
+
+#include <crypto/compress.h>
+
+extern int crypto_register_pcomp(struct pcomp_alg *alg);
+extern int crypto_unregister_pcomp(struct pcomp_alg *alg);
+
+#endif	/* _CRYPTO_INTERNAL_COMPRESS_H */
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index ff8d27a..a11cc9d 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -69,8 +69,8 @@
 	u8 hborder;
 	u8 vborder;
 	u8 unknown0:1;
-	u8 vsync_positive:1;
 	u8 hsync_positive:1;
+	u8 vsync_positive:1;
 	u8 separate_sync:2;
 	u8 stereo:1;
 	u8 unknown6:1;
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 08a86d5..6617c9f 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -89,6 +89,8 @@
 	ATA_ID_DLF		= 128,
 	ATA_ID_CSFO		= 129,
 	ATA_ID_CFA_POWER	= 160,
+	ATA_ID_CFA_KEY_MGMT	= 162,
+	ATA_ID_CFA_MODES	= 163,
 	ATA_ID_ROT_SPEED	= 217,
 	ATA_ID_PIO4		= (1 << 1),
 
@@ -106,6 +108,8 @@
 	ATA_PIO5		= ATA_PIO4 | (1 << 5),
 	ATA_PIO6		= ATA_PIO5 | (1 << 6),
 
+	ATA_PIO4_ONLY		= (1 << 4),
+
 	ATA_SWDMA0		= (1 << 0),
 	ATA_SWDMA1		= ATA_SWDMA0 | (1 << 1),
 	ATA_SWDMA2		= ATA_SWDMA1 | (1 << 2),
@@ -115,6 +119,8 @@
 	ATA_MWDMA0		= (1 << 0),
 	ATA_MWDMA1		= ATA_MWDMA0 | (1 << 1),
 	ATA_MWDMA2		= ATA_MWDMA1 | (1 << 2),
+	ATA_MWDMA3		= ATA_MWDMA2 | (1 << 3),
+	ATA_MWDMA4		= ATA_MWDMA3 | (1 << 4),
 
 	ATA_MWDMA12_ONLY	= (1 << 1) | (1 << 2),
 	ATA_MWDMA2_ONLY		= (1 << 2),
@@ -129,6 +135,8 @@
 	ATA_UDMA7		= ATA_UDMA6 | (1 << 7),
 	/* ATA_UDMA7 is just for completeness... doesn't exist (yet?).  */
 
+	ATA_UDMA24_ONLY		= (1 << 2) | (1 << 4),
+
 	ATA_UDMA_MASK_40C	= ATA_UDMA2,	/* udma0-2 */
 
 	/* DMA-related */
@@ -242,8 +250,6 @@
 	ATA_CMD_MEDIA_UNLOCK	= 0xDF,
 	/* marked obsolete in the ATA/ATAPI-7 spec */
 	ATA_CMD_RESTORE		= 0x10,
-	/* EXABYTE specific */
-	ATA_EXABYTE_ENABLE_NEST	= 0xF0,
 
 	/* READ_LOG_EXT pages */
 	ATA_LOG_SATA_NCQ	= 0x10,
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 67e5dbf..4fa2810 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -36,7 +36,8 @@
  * 1500 - 1599 kernel LSPP events
  * 1600 - 1699 kernel crypto events
  * 1700 - 1799 kernel anomaly records
- * 1800 - 1999 future kernel use (maybe integrity labels and related events)
+ * 1800 - 1899 kernel integrity events
+ * 1900 - 1999 future kernel use
  * 2000 is for otherwise unclassified kernel audit messages (legacy)
  * 2001 - 2099 unused (kernel)
  * 2100 - 2199 user space anomaly records
@@ -125,6 +126,12 @@
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
 #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
 #define AUDIT_ANOM_ABEND            1701 /* Process ended abnormally */
+#define AUDIT_INTEGRITY_DATA	    1800 /* Data integrity verification */
+#define AUDIT_INTEGRITY_METADATA    1801 /* Metadata integrity verification */
+#define AUDIT_INTEGRITY_STATUS	    1802 /* Integrity enable status */
+#define AUDIT_INTEGRITY_HASH	    1803 /* Integrity HASH type */
+#define AUDIT_INTEGRITY_PCR	    1804 /* PCR invalidation msgs */
+#define AUDIT_INTEGRITY_RULE	    1805 /* policy rule */
 
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 1b16108..d8bd43b 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -531,7 +531,7 @@
 extern void bio_integrity_advance(struct bio *, unsigned int);
 extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
 extern void bio_integrity_split(struct bio *, struct bio_pair *, int);
-extern int bio_integrity_clone(struct bio *, struct bio *, struct bio_set *);
+extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t, struct bio_set *);
 extern int bioset_integrity_create(struct bio_set *, int);
 extern void bioset_integrity_free(struct bio_set *);
 extern void bio_integrity_init_slab(void);
@@ -542,7 +542,7 @@
 #define bioset_integrity_create(a, b)	(0)
 #define bio_integrity_prep(a)		(0)
 #define bio_integrity_enabled(a)	(0)
-#define bio_integrity_clone(a, b, c)	(0)
+#define bio_integrity_clone(a, b, c,d )	(0)
 #define bioset_integrity_free(a)	do { } while (0)
 #define bio_integrity_free(a, b)	do { } while (0)
 #define bio_integrity_endio(a, b)	do { } while (0)
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 1b98725..4864a43 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -393,8 +393,10 @@
 # define CAP_FULL_SET     ((kernel_cap_t){{ ~0, ~0 }})
 # define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }})
 # define CAP_FS_SET       ((kernel_cap_t){{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } })
-# define CAP_NFSD_SET     ((kernel_cap_t){{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \
-					CAP_FS_MASK_B1 } })
+# define CAP_NFSD_SET     ((kernel_cap_t){{ CAP_FS_MASK_B0 \
+					    | CAP_TO_MASK(CAP_SYS_RESOURCE) \
+					    | CAP_TO_MASK(CAP_MKNOD), \
+					    CAP_FS_MASK_B1 } })
 
 #endif /* _KERNEL_CAPABILITY_U32S != 2 */
 
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 1514d53..a3ed7cb 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -52,7 +52,15 @@
 #define __deprecated			__attribute__((deprecated))
 #define __packed			__attribute__((packed))
 #define __weak				__attribute__((weak))
-#define __naked				__attribute__((naked))
+
+/*
+ * it doesn't make sense on ARM (currently the only user of __naked) to trace
+ * naked functions because then mcount is called without stack and frame pointer
+ * being set up and there is no chance to restore the lr register to the value
+ * before mcount was called.
+ */
+#define __naked				__attribute__((naked)) notrace
+
 #define __noreturn			__attribute__((noreturn))
 
 /*
diff --git a/include/linux/console.h b/include/linux/console.h
index a67a90c..dcca533 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -137,8 +137,8 @@
 int mda_console_init(void);
 void prom_con_init(void);
 
-void vcs_make_sysfs(struct tty_struct *tty);
-void vcs_remove_sysfs(struct tty_struct *tty);
+void vcs_make_sysfs(int index);
+void vcs_remove_sysfs(int index);
 
 /* Some debug stub to catch some of the obvious races in the VT code */
 #if 1
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 384b38d..1610427 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -234,7 +234,6 @@
 	int	(*suspend)	(struct cpufreq_policy *policy, pm_message_t pmsg);
 	int	(*resume)	(struct cpufreq_policy *policy);
 	struct freq_attr	**attr;
-	bool			hide_interface;
 };
 
 /* flags */
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 1f2e902..ec29fa2 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -40,6 +40,7 @@
 #define CRYPTO_ALG_TYPE_SHASH		0x00000009
 #define CRYPTO_ALG_TYPE_AHASH		0x0000000a
 #define CRYPTO_ALG_TYPE_RNG		0x0000000c
+#define CRYPTO_ALG_TYPE_PCOMPRESS	0x0000000f
 
 #define CRYPTO_ALG_TYPE_HASH_MASK	0x0000000e
 #define CRYPTO_ALG_TYPE_AHASH_MASK	0x0000000c
@@ -548,9 +549,6 @@
  * Transform user interface.
  */
  
-struct crypto_tfm *crypto_alloc_tfm(const char *alg_name,
-				    const struct crypto_type *frontend,
-				    u32 type, u32 mask);
 struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask);
 void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm);
 
diff --git a/include/linux/device.h b/include/linux/device.h
index 47f343c..2918c0e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -28,6 +28,7 @@
 #define BUS_ID_SIZE		20
 
 struct device;
+struct device_private;
 struct device_driver;
 struct driver_private;
 struct class;
@@ -147,7 +148,7 @@
 extern struct device_driver *driver_find(const char *name,
 					 struct bus_type *bus);
 extern int driver_probe_done(void);
-extern int wait_for_device_probe(void);
+extern void wait_for_device_probe(void);
 
 
 /* sysfs interface for exporting driver attributes */
@@ -367,15 +368,11 @@
 };
 
 struct device {
-	struct klist		klist_children;
-	struct klist_node	knode_parent;	/* node in sibling list */
-	struct klist_node	knode_driver;
-	struct klist_node	knode_bus;
 	struct device		*parent;
 
+	struct device_private	*p;
+
 	struct kobject kobj;
-	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */
-	unsigned		uevent_suppress:1;
 	const char		*init_name; /* initial name of the device */
 	struct device_type	*type;
 
@@ -387,8 +384,13 @@
 	struct device_driver *driver;	/* which driver has allocated this
 					   device */
 	void		*driver_data;	/* data private to the driver */
-	void		*platform_data;	/* Platform specific data, device
-					   core doesn't touch it */
+
+	void		*platform_data;	/* We will remove platform_data
+					   field if all platform devices
+					   pass its platform specific data
+					   from platform_device->platform_data,
+					   other kind of devices should not
+					   use platform_data. */
 	struct dev_pm_info	power;
 
 #ifdef CONFIG_NUMA
@@ -427,8 +429,7 @@
 
 static inline const char *dev_name(const struct device *dev)
 {
-	/* will be changed into kobject_name(&dev->kobj) in the near future */
-	return dev->bus_id;
+	return kobject_name(&dev->kobj);
 }
 
 extern int dev_set_name(struct device *dev, const char *name, ...)
@@ -463,6 +464,16 @@
 	dev->driver_data = data;
 }
 
+static inline unsigned int dev_get_uevent_suppress(const struct device *dev)
+{
+	return dev->kobj.uevent_suppress;
+}
+
+static inline void dev_set_uevent_suppress(struct device *dev, int val)
+{
+	dev->kobj.uevent_suppress = val;
+}
+
 static inline int device_is_registered(struct device *dev)
 {
 	return dev->kobj.state_in_sysfs;
@@ -483,7 +494,8 @@
 extern struct device *device_find_child(struct device *dev, void *data,
 				int (*match)(struct device *dev, void *data));
 extern int device_rename(struct device *dev, char *new_name);
-extern int device_move(struct device *dev, struct device *new_parent);
+extern int device_move(struct device *dev, struct device *new_parent,
+		       enum dpm_order dpm_order);
 
 /*
  * Root device objects for grouping under /sys/devices
@@ -570,7 +582,7 @@
 #if defined(DEBUG)
 #define dev_dbg(dev, format, arg...)		\
 	dev_printk(KERN_DEBUG , dev , format , ## arg)
-#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#elif defined(CONFIG_DYNAMIC_DEBUG)
 #define dev_dbg(dev, format, ...) do { \
 	dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
 	} while (0)
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index f041384..1956c8d 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -97,7 +97,6 @@
 
 /**
  * struct dma_chan_percpu - the per-CPU part of struct dma_chan
- * @refcount: local_t used for open-coded "bigref" counting
  * @memcpy_count: transaction counter
  * @bytes_transferred: byte counter
  */
@@ -114,9 +113,6 @@
  * @cookie: last cookie value returned to client
  * @chan_id: channel ID for sysfs
  * @dev: class device for sysfs
- * @refcount: kref, used in "bigref" slow-mode
- * @slow_ref: indicates that the DMA channel is free
- * @rcu: the DMA channel's RCU head
  * @device_node: used to add this to the device chan list
  * @local: per-cpu pointer to a struct dma_chan_percpu
  * @client-count: how many clients are using this channel
@@ -213,8 +209,6 @@
  * @global_node: list_head for global dma_device_list
  * @cap_mask: one or more dma_capability flags
  * @max_xor: maximum number of xor sources, 0 if no capability
- * @refcount: reference count
- * @done: IO completion struct
  * @dev_id: unique device ID
  * @dev: struct device reference for dma mapping api
  * @device_alloc_chan_resources: allocate resources and return the
@@ -227,6 +221,7 @@
  * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
  * @device_prep_slave_sg: prepares a slave dma operation
  * @device_terminate_all: terminate all pending operations
+ * @device_is_tx_complete: poll for transaction completion
  * @device_issue_pending: push pending transactions to hardware
  */
 struct dma_device {
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
new file mode 100644
index 0000000..baabf33
--- /dev/null
+++ b/include/linux/dynamic_debug.h
@@ -0,0 +1,88 @@
+#ifndef _DYNAMIC_DEBUG_H
+#define _DYNAMIC_DEBUG_H
+
+/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
+ * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
+ * use independent hash functions, to reduce the chance of false positives.
+ */
+extern long long dynamic_debug_enabled;
+extern long long dynamic_debug_enabled2;
+
+/*
+ * An instance of this structure is created in a special
+ * ELF section at every dynamic debug callsite.  At runtime,
+ * the special section is treated as an array of these.
+ */
+struct _ddebug {
+	/*
+	 * These fields are used to drive the user interface
+	 * for selecting and displaying debug callsites.
+	 */
+	const char *modname;
+	const char *function;
+	const char *filename;
+	const char *format;
+	char primary_hash;
+	char secondary_hash;
+	unsigned int lineno:24;
+	/*
+ 	 * The flags field controls the behaviour at the callsite.
+ 	 * The bits here are changed dynamically when the user
+ 	 * writes commands to <debugfs>/dynamic_debug/ddebug
+	 */
+#define _DPRINTK_FLAGS_PRINT   (1<<0)  /* printk() a message using the format */
+#define _DPRINTK_FLAGS_DEFAULT 0
+	unsigned int flags:8;
+} __attribute__((aligned(8)));
+
+
+int ddebug_add_module(struct _ddebug *tab, unsigned int n,
+				const char *modname);
+
+#if defined(CONFIG_DYNAMIC_DEBUG)
+extern int ddebug_remove_module(char *mod_name);
+
+#define __dynamic_dbg_enabled(dd)  ({	     \
+	int __ret = 0;							     \
+	if (unlikely((dynamic_debug_enabled & (1LL << DEBUG_HASH)) &&	     \
+			(dynamic_debug_enabled2 & (1LL << DEBUG_HASH2))))   \
+				if (unlikely(dd.flags))			     \
+					__ret = 1;			     \
+	__ret; })
+
+#define dynamic_pr_debug(fmt, ...) do {					\
+	static struct _ddebug descriptor				\
+	__used								\
+	__attribute__((section("__verbose"), aligned(8))) =		\
+	{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,	\
+		DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };	\
+	if (__dynamic_dbg_enabled(descriptor))				\
+		printk(KERN_DEBUG KBUILD_MODNAME ":" pr_fmt(fmt),	\
+				##__VA_ARGS__);				\
+	} while (0)
+
+
+#define dynamic_dev_dbg(dev, fmt, ...) do {				\
+	static struct _ddebug descriptor				\
+	__used								\
+	__attribute__((section("__verbose"), aligned(8))) =		\
+	{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,	\
+		DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };	\
+	if (__dynamic_dbg_enabled(descriptor))				\
+			dev_printk(KERN_DEBUG, dev,			\
+					KBUILD_MODNAME ": " pr_fmt(fmt),\
+					##__VA_ARGS__);			\
+	} while (0)
+
+#else
+
+static inline int ddebug_remove_module(char *mod)
+{
+	return 0;
+}
+
+#define dynamic_pr_debug(fmt, ...)  do { } while (0)
+#define dynamic_dev_dbg(dev, format, ...)  do { } while (0)
+#endif
+
+#endif
diff --git a/include/linux/dynamic_printk.h b/include/linux/dynamic_printk.h
deleted file mode 100644
index 2d528d0..0000000
--- a/include/linux/dynamic_printk.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef _DYNAMIC_PRINTK_H
-#define _DYNAMIC_PRINTK_H
-
-#define DYNAMIC_DEBUG_HASH_BITS 6
-#define DEBUG_HASH_TABLE_SIZE (1 << DYNAMIC_DEBUG_HASH_BITS)
-
-#define TYPE_BOOLEAN 1
-
-#define DYNAMIC_ENABLED_ALL 0
-#define DYNAMIC_ENABLED_NONE 1
-#define DYNAMIC_ENABLED_SOME 2
-
-extern int dynamic_enabled;
-
-/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
- * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
- * use independent hash functions, to reduce the chance of false positives.
- */
-extern long long dynamic_printk_enabled;
-extern long long dynamic_printk_enabled2;
-
-struct mod_debug {
-	char *modname;
-	char *logical_modname;
-	char *flag_names;
-	int type;
-	int hash;
-	int hash2;
-} __attribute__((aligned(8)));
-
-int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
-					char *flags, int hash, int hash2);
-
-#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
-extern int unregister_dynamic_debug_module(char *mod_name);
-extern int __dynamic_dbg_enabled_helper(char *modname, int type,
-					int value, int hash);
-
-#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({	     \
-	int __ret = 0;							     \
-	if (unlikely((dynamic_printk_enabled & (1LL << DEBUG_HASH)) &&	     \
-			(dynamic_printk_enabled2 & (1LL << DEBUG_HASH2))))   \
-			__ret = __dynamic_dbg_enabled_helper(module, type,   \
-								value, hash);\
-	__ret; })
-
-#define dynamic_pr_debug(fmt, ...) do {					    \
-	static char mod_name[]						    \
-	__attribute__((section("__verbose_strings")))			    \
-	 = KBUILD_MODNAME;						    \
-	static struct mod_debug descriptor				    \
-	__used								    \
-	__attribute__((section("__verbose"), aligned(8))) =		    \
-	{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
-	if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,		    \
-						0, 0, DEBUG_HASH))	    \
-		printk(KERN_DEBUG KBUILD_MODNAME ":" fmt,		    \
-				##__VA_ARGS__);				    \
-	} while (0)
-
-#define dynamic_dev_dbg(dev, format, ...) do {				    \
-	static char mod_name[]						    \
-	__attribute__((section("__verbose_strings")))			    \
-	 = KBUILD_MODNAME;						    \
-	static struct mod_debug descriptor				    \
-	__used								    \
-	__attribute__((section("__verbose"), aligned(8))) =		    \
-	{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
-	if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,		    \
-						0, 0, DEBUG_HASH))	    \
-			dev_printk(KERN_DEBUG, dev,			    \
-					KBUILD_MODNAME ": " format,	    \
-					##__VA_ARGS__);			    \
-	} while (0)
-
-#else
-
-static inline int unregister_dynamic_debug_module(const char *mod_name)
-{
-	return 0;
-}
-static inline int __dynamic_dbg_enabled_helper(char *modname, int type,
-						int value, int hash)
-{
-	return 0;
-}
-
-#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({ 0; })
-#define dynamic_pr_debug(fmt, ...)  do { } while (0)
-#define dynamic_dev_dbg(dev, format, ...)  do { } while (0)
-#endif
-
-#endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 92734c0..5bc81c4 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -141,6 +141,7 @@
 #define MS_RELATIME	(1<<21)	/* Update atime relative to mtime/ctime. */
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
+#define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
 #define MS_ACTIVE	(1<<30)
 #define MS_NOUSER	(1<<31)
 
diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
index c37e924..ed21bd3 100644
--- a/include/linux/hdreg.h
+++ b/include/linux/hdreg.h
@@ -511,7 +511,6 @@
 	unsigned short	words69_70[2];	/* reserved words 69-70
 					 * future command overlap and queuing
 					 */
-	/* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
 	unsigned short	words71_74[4];	/* reserved words 71-74
 					 * for IDENTIFY PACKET DEVICE command
 					 */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index fe235b6..854eba8 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -26,7 +26,7 @@
 #include <asm/io.h>
 #include <asm/mutex.h>
 
-#if defined(CONFIG_CRIS) || defined(CONFIG_FRV)
+#if defined(CONFIG_CRIS) || defined(CONFIG_FRV) || defined(CONFIG_MN10300)
 # define SUPPORT_VLB_SYNC 0
 #else
 # define SUPPORT_VLB_SYNC 1
@@ -193,24 +193,8 @@
 	hw->io_ports.ctl_addr = ctl_addr;
 }
 
-/* for IDE PCI controllers in legacy mode, temporary */
-static inline int __ide_default_irq(unsigned long base)
-{
-	switch (base) {
-#ifdef CONFIG_IA64
-	case 0x1f0: return isa_irq_to_vector(14);
-	case 0x170: return isa_irq_to_vector(15);
-#else
-	case 0x1f0: return 14;
-	case 0x170: return 15;
-#endif
-	}
-	return 0;
-}
-
-#if defined(CONFIG_ARM) || defined(CONFIG_FRV) || defined(CONFIG_M68K) || \
-    defined(CONFIG_MIPS) || defined(CONFIG_MN10300) || defined(CONFIG_PARISC) \
-    || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || defined(CONFIG_SPARC64)
+#if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
+    defined(CONFIG_PARISC) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
 #include <asm/ide.h>
 #else
 #include <asm-generic/ide_iops.h>
@@ -797,6 +781,7 @@
 	struct scatterlist *sg_table;
 	int sg_max_nents;		/* Maximum number of entries in it */
 	int sg_nents;			/* Current number of entries in it */
+	int orig_sg_nents;
 	int sg_dma_direction;		/* dma transfer direction */
 
 	/* data phase of the active command (currently only valid for PIO/DMA) */
@@ -865,7 +850,8 @@
 	ide_hwif_t	*ports[MAX_HOST_PORTS + 1];
 	unsigned int	n_ports;
 	struct device	*dev[2];
-	unsigned int	(*init_chipset)(struct pci_dev *);
+	int		(*init_chipset)(struct pci_dev *);
+	irq_handler_t	irq_handler;
 	unsigned long	host_flags;
 	void		*host_priv;
 	ide_hwif_t	*cur_port;	/* for hosts requiring serialization */
@@ -1144,11 +1130,14 @@
 extern int ide_vlb_clk;
 extern int ide_pci_clk;
 
-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);
+int ide_end_request(ide_drive_t *, int, int);
+int ide_end_dequeued_request(ide_drive_t *, struct request *, int, int);
+void ide_kill_rq(ide_drive_t *, struct request *);
 
-extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry);
+void __ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int,
+		       ide_expiry_t *);
+void ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int,
+		     ide_expiry_t *);
 
 void ide_execute_command(ide_drive_t *, u8, ide_handler_t *, unsigned int,
 			 ide_expiry_t *);
@@ -1167,13 +1156,14 @@
 
 int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
 
+ide_startstop_t ide_do_park_unpark(ide_drive_t *, struct request *);
+ide_startstop_t ide_do_devset(ide_drive_t *, struct request *);
+
 extern ide_startstop_t ide_do_reset (ide_drive_t *);
 
 extern int ide_devset_execute(ide_drive_t *drive,
 			      const struct ide_devset *setting, int arg);
 
-extern void ide_do_drive_cmd(ide_drive_t *, struct request *);
-
 extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
 
 void ide_tf_dump(const char *, struct ide_taskfile *);
@@ -1198,10 +1188,6 @@
 u8 ide_read_error(ide_drive_t *);
 void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *);
 
-extern int drive_is_ready(ide_drive_t *);
-
-void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8);
-
 int ide_check_atapi_device(ide_drive_t *, const char *);
 
 void ide_init_pc(struct ide_atapi_pc *);
@@ -1249,6 +1235,8 @@
 
 int ide_taskfile_ioctl(ide_drive_t *, unsigned int, unsigned long);
 
+int ide_dev_read_id(ide_drive_t *, u8, u16 *);
+
 extern int ide_driveid_update(ide_drive_t *);
 extern int ide_config_drive_speed(ide_drive_t *, u8);
 extern u8 eighty_ninty_three (ide_drive_t *);
@@ -1278,7 +1266,7 @@
 	return 0;
 }
 
-void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int,
+void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *,
 			 hw_regs_t *, hw_regs_t **);
 void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
 
@@ -1347,10 +1335,6 @@
 	IDE_HFLAG_ERROR_STOPS_FIFO	= (1 << 19),
 	/* serialize ports */
 	IDE_HFLAG_SERIALIZE		= (1 << 20),
-	/* use legacy IRQs */
-	IDE_HFLAG_LEGACY_IRQS		= (1 << 21),
-	/* force use of legacy IRQs */
-	IDE_HFLAG_FORCE_LEGACY_IRQS	= (1 << 22),
 	/* host is TRM290 */
 	IDE_HFLAG_TRM290		= (1 << 23),
 	/* use 32-bit I/O ops */
@@ -1378,7 +1362,7 @@
 
 struct ide_port_info {
 	char			*name;
-	unsigned int		(*init_chipset)(struct pci_dev *);
+	int			(*init_chipset)(struct pci_dev *);
 	void			(*init_iops)(ide_hwif_t *);
 	void                    (*init_hwif)(ide_hwif_t *);
 	int			(*init_dma)(ide_hwif_t *,
@@ -1469,6 +1453,7 @@
 
 void ide_dma_lost_irq(ide_drive_t *);
 void ide_dma_timeout(ide_drive_t *);
+ide_startstop_t ide_dma_timeout_retry(ide_drive_t *, int);
 
 #else
 static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; }
@@ -1480,21 +1465,24 @@
 static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
 static inline int ide_set_dma(ide_drive_t *drive) { return 1; }
 static inline void ide_check_dma_crc(ide_drive_t *drive) { ; }
+static inline ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) { return ide_stopped; }
 static inline void ide_release_dma_engine(ide_hwif_t *hwif) { ; }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 #ifdef CONFIG_BLK_DEV_IDEACPI
+int ide_acpi_init(void);
 extern int ide_acpi_exec_tfs(ide_drive_t *drive);
 extern void ide_acpi_get_timing(ide_hwif_t *hwif);
 extern void ide_acpi_push_timing(ide_hwif_t *hwif);
-extern void ide_acpi_init(ide_hwif_t *hwif);
+void ide_acpi_init_port(ide_hwif_t *);
 void ide_acpi_port_init_devices(ide_hwif_t *);
 extern void ide_acpi_set_state(ide_hwif_t *hwif, int on);
 #else
+static inline int ide_acpi_init(void) { return 0; }
 static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; }
 static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; }
 static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; }
-static inline void ide_acpi_init(ide_hwif_t *hwif) { ; }
+static inline void ide_acpi_init_port(ide_hwif_t *hwif) { ; }
 static inline void ide_acpi_port_init_devices(ide_hwif_t *hwif) { ; }
 static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
 #endif
@@ -1528,9 +1516,7 @@
 	hwif->hwif_data = data;
 }
 
-const char *ide_xfer_verbose(u8 mode);
 extern void ide_toggle_bounce(ide_drive_t *drive, int on);
-extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
 
 u64 ide_get_lba_addr(struct ide_taskfile *, int);
 u8 ide_dump_status(ide_drive_t *, const char *, u8);
@@ -1569,14 +1555,18 @@
 		      struct ide_timing *, unsigned int);
 int ide_timing_compute(ide_drive_t *, u8, struct ide_timing *, int, int);
 
+#ifdef CONFIG_IDE_XFER_MODE
 int ide_scan_pio_blacklist(char *);
-
+const char *ide_xfer_verbose(u8);
 u8 ide_get_best_pio_mode(ide_drive_t *, u8, u8);
-
 int ide_set_pio_mode(ide_drive_t *, u8);
 int ide_set_dma_mode(ide_drive_t *, u8);
-
 void ide_set_pio(ide_drive_t *, u8);
+int ide_set_xfer_rate(ide_drive_t *, u8);
+#else
+static inline void ide_set_pio(ide_drive_t *drive, u8 pio) { ; }
+static inline int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) { return -1; }
+#endif
 
 static inline void ide_set_max_pio(ide_drive_t *drive)
 {
@@ -1609,6 +1599,10 @@
 #define ide_port_for_each_dev(i, dev, port) \
 	for ((i) = 0; ((dev) = (port)->devices[i]) || (i) < MAX_DRIVES; (i)++)
 
+#define ide_port_for_each_present_dev(i, dev, port) \
+	for ((i) = 0; ((dev) = (port)->devices[i]) || (i) < MAX_DRIVES; (i)++) \
+		if ((dev)->dev_flags & IDE_DFLAG_PRESENT)
+
 #define ide_host_for_each_port(i, port, host) \
 	for ((i) = 0; ((port) = (host)->ports[i]) || (i) < MAX_HOST_PORTS; (i)++)
 
diff --git a/include/linux/ima.h b/include/linux/ima.h
new file mode 100644
index 0000000..0e2aa45
--- /dev/null
+++ b/include/linux/ima.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ * Author: Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ */
+
+#ifndef _LINUX_IMA_H
+#define _LINUX_IMA_H
+
+#include <linux/fs.h>
+struct linux_binprm;
+
+#ifdef CONFIG_IMA
+extern int ima_bprm_check(struct linux_binprm *bprm);
+extern int ima_inode_alloc(struct inode *inode);
+extern void ima_inode_free(struct inode *inode);
+extern int ima_path_check(struct path *path, int mask);
+extern void ima_file_free(struct file *file);
+extern int ima_file_mmap(struct file *file, unsigned long prot);
+extern void ima_shm_check(struct file *file);
+
+#else
+static inline int ima_bprm_check(struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+static inline int ima_inode_alloc(struct inode *inode)
+{
+	return 0;
+}
+
+static inline void ima_inode_free(struct inode *inode)
+{
+	return;
+}
+
+static inline int ima_path_check(struct path *path, int mask)
+{
+	return 0;
+}
+
+static inline void ima_file_free(struct file *file)
+{
+	return;
+}
+
+static inline int ima_file_mmap(struct file *file, unsigned long prot)
+{
+	return 0;
+}
+
+static inline void ima_shm_check(struct file *file)
+{
+	return;
+}
+#endif /* CONFIG_IMA_H */
+#endif /* _LINUX_IMA_H */
diff --git a/include/linux/input.h b/include/linux/input.h
index 1249a0c..6b28048 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -661,6 +661,7 @@
 #define SW_DOCK			0x05  /* set = plugged into dock */
 #define SW_LINEOUT_INSERT	0x06  /* set = inserted */
 #define SW_JACK_PHYSICAL_INSERT 0x07  /* set = mechanical switch set */
+#define SW_VIDEOOUT_INSERT	0x08  /* set = inserted */
 #define SW_MAX			0x0f
 #define SW_CNT			(SW_MAX+1)
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 7fa3718..914918a 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -16,7 +16,7 @@
 #include <linux/log2.h>
 #include <linux/typecheck.h>
 #include <linux/ratelimit.h>
-#include <linux/dynamic_printk.h>
+#include <linux/dynamic_debug.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
@@ -358,9 +358,10 @@
 #if defined(DEBUG)
 #define pr_debug(fmt, ...) \
 	printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
-#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#elif defined(CONFIG_DYNAMIC_DEBUG)
+/* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
 #define pr_debug(fmt, ...) do { \
-	dynamic_pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
+	dynamic_pr_debug(fmt, ##__VA_ARGS__); \
 	} while (0)
 #else
 #define pr_debug(fmt, ...) \
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 5437ac0..58ae8e00 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -68,10 +68,13 @@
 	unsigned int state_in_sysfs:1;
 	unsigned int state_add_uevent_sent:1;
 	unsigned int state_remove_uevent_sent:1;
+	unsigned int uevent_suppress:1;
 };
 
 extern int kobject_set_name(struct kobject *kobj, const char *name, ...)
 			    __attribute__((format(printf, 2, 3)));
+extern int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
+				  va_list vargs);
 
 static inline const char *kobject_name(const struct kobject *kobj)
 {
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 5d87bc0..76262d8 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -275,7 +275,7 @@
 	 * advised to wait only for the following duration before
 	 * doing SRST.
 	 */
-	ATA_TMOUT_PMP_SRST_WAIT	= 1000,
+	ATA_TMOUT_PMP_SRST_WAIT	= 5000,
 
 	/* ATA bus states */
 	BUS_UNKNOWN		= 0,
@@ -530,6 +530,7 @@
 	unsigned long		flags;		/* ATA_QCFLAG_xxx */
 	unsigned int		tag;
 	unsigned int		n_elem;
+	unsigned int		orig_n_elem;
 
 	int			dma_dir;
 
@@ -750,7 +751,8 @@
 	acpi_handle		acpi_handle;
 	struct ata_acpi_gtm	__acpi_init_gtm; /* use ata_acpi_init_gtm() */
 #endif
-	u8			sector_buf[ATA_SECT_SIZE]; /* owned by EH */
+	/* owned by EH */
+	u8			sector_buf[ATA_SECT_SIZE] ____cacheline_aligned;
 };
 
 /* The following initializer overrides a method to NULL whether one of
@@ -793,6 +795,7 @@
 	ata_reset_fn_t		pmp_hardreset;
 	ata_postreset_fn_t	pmp_postreset;
 	void (*error_handler)(struct ata_port *ap);
+	void (*lost_interrupt)(struct ata_port *ap);
 	void (*post_internal_cmd)(struct ata_queued_cmd *qc);
 
 	/*
@@ -834,6 +837,8 @@
 	void (*bmdma_start)(struct ata_queued_cmd *qc);
 	void (*bmdma_stop)(struct ata_queued_cmd *qc);
 	u8   (*bmdma_status)(struct ata_port *ap);
+
+	void (*drain_fifo)(struct ata_queued_cmd *qc);
 #endif /* CONFIG_ATA_SFF */
 
 	ssize_t (*em_show)(struct ata_port *ap, char *buf);
@@ -1006,6 +1011,9 @@
 extern int ata_cable_ignore(struct ata_port *ap);
 extern int ata_cable_unknown(struct ata_port *ap);
 
+extern void ata_pio_queue_task(struct ata_port *ap, void *data,
+			       unsigned long delay);
+
 /* 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);
@@ -1570,6 +1578,7 @@
 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_lost_interrupt(struct ata_port *ap);
 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);
@@ -1582,6 +1591,7 @@
 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_drain_fifo(struct ata_queued_cmd *qc);
 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);
diff --git a/include/linux/lm_interface.h b/include/linux/lm_interface.h
deleted file mode 100644
index 2ed8fa1..0000000
--- a/include/linux/lm_interface.h
+++ /dev/null
@@ -1,277 +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_INTERFACE_DOT_H__
-#define __LM_INTERFACE_DOT_H__
-
-
-typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
-
-/*
- * lm_mount() flags
- *
- * LM_MFLAG_SPECTATOR
- * GFS is asking to join the filesystem's lockspace, but it doesn't want to
- * 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
- *
- * LM_LSFLAG_LOCAL
- * The lock_nolock module returns LM_LSFLAG_LOCAL to GFS, indicating that GFS
- * can make single-node optimizations.
- */
-
-#define LM_LSFLAG_LOCAL		0x00000001
-
-/*
- * lm_lockname types
- */
-
-#define LM_TYPE_RESERVED	0x00
-#define LM_TYPE_NONDISK		0x01
-#define LM_TYPE_INODE		0x02
-#define LM_TYPE_RGRP		0x03
-#define LM_TYPE_META		0x04
-#define LM_TYPE_IOPEN		0x05
-#define LM_TYPE_FLOCK		0x06
-#define LM_TYPE_PLOCK		0x07
-#define LM_TYPE_QUOTA		0x08
-#define LM_TYPE_JOURNAL		0x09
-
-/*
- * lm_lock() states
- *
- * SHARED is compatible with SHARED, not with DEFERRED or EX.
- * DEFERRED is compatible with DEFERRED, not with SHARED or EX.
- */
-
-#define LM_ST_UNLOCKED		0
-#define LM_ST_EXCLUSIVE		1
-#define LM_ST_DEFERRED		2
-#define LM_ST_SHARED		3
-
-/*
- * lm_lock() flags
- *
- * LM_FLAG_TRY
- * Don't wait to acquire the lock if it can't be granted immediately.
- *
- * LM_FLAG_TRY_1CB
- * Send one blocking callback if TRY is set and the lock is not granted.
- *
- * LM_FLAG_NOEXP
- * GFS sets this flag on lock requests it makes while doing journal recovery.
- * These special requests should not be blocked due to the recovery like
- * ordinary locks would be.
- *
- * LM_FLAG_ANY
- * A SHARED request may also be granted in DEFERRED, or a DEFERRED request may
- * also be granted in SHARED.  The preferred state is whichever is compatible
- * with other granted locks, or the specified state if no other locks exist.
- *
- * LM_FLAG_PRIORITY
- * Override fairness considerations.  Suppose a lock is held in a shared state
- * and there is a pending request for the deferred state.  A shared lock
- * request with the priority flag would be allowed to bypass the deferred
- * request and directly join the other shared lock.  A shared lock request
- * without the priority flag might be forced to wait until the deferred
- * requested had acquired and released the lock.
- */
-
-#define LM_FLAG_TRY		0x00000001
-#define LM_FLAG_TRY_1CB		0x00000002
-#define LM_FLAG_NOEXP		0x00000004
-#define LM_FLAG_ANY		0x00000008
-#define LM_FLAG_PRIORITY	0x00000010
-
-/*
- * lm_lock() and lm_async_cb return flags
- *
- * LM_OUT_ST_MASK
- * Masks the lower two bits of lock state in the returned value.
- *
- * LM_OUT_CACHEABLE
- * The lock hasn't been released so GFS can continue to cache data for it.
- *
- * LM_OUT_CANCELED
- * The lock request was canceled.
- *
- * 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
-#define LM_OUT_CANCELED		0x00000008
-#define LM_OUT_ASYNC		0x00000080
-#define LM_OUT_ERROR		0x00000100
-
-/*
- * lm_callback_t types
- *
- * LM_CB_NEED_E LM_CB_NEED_D LM_CB_NEED_S
- * Blocking callback, a remote node is requesting the given lock in
- * EXCLUSIVE, DEFERRED, or SHARED.
- *
- * LM_CB_NEED_RECOVERY
- * The given journal needs to be recovered.
- *
- * LM_CB_ASYNC
- * The given lock has been granted.
- */
-
-#define LM_CB_NEED_E		257
-#define LM_CB_NEED_D		258
-#define LM_CB_NEED_S		259
-#define LM_CB_NEED_RECOVERY	260
-#define LM_CB_ASYNC		262
-
-/*
- * lm_recovery_done() messages
- */
-
-#define LM_RD_GAVEUP		308
-#define LM_RD_SUCCESS		309
-
-
-struct lm_lockname {
-	u64 ln_number;
-	unsigned int ln_type;
-};
-
-#define lm_name_equal(name1, name2) \
-	(((name1)->ln_number == (name2)->ln_number) && \
-	 ((name1)->ln_type == (name2)->ln_type)) \
-
-struct lm_async_cb {
-	struct lm_lockname lc_name;
-	int lc_ret;
-};
-
-struct lm_lockstruct;
-
-struct lm_lockops {
-	const char *lm_proto_name;
-
-	/*
-	 * Mount/Unmount
-	 */
-
-	int (*lm_mount) (char *table_name, char *host_data,
-			 lm_callback_t cb, void *cb_data,
-			 unsigned int min_lvb_size, int flags,
-			 struct lm_lockstruct *lockstruct,
-			 struct kobject *fskobj);
-
-	void (*lm_others_may_mount) (void *lockspace);
-
-	void (*lm_unmount) (void *lockspace);
-
-	void (*lm_withdraw) (void *lockspace);
-
-	/*
-	 * Lock oriented operations
-	 */
-
-	int (*lm_get_lock) (void *lockspace, struct lm_lockname *name, void **lockp);
-
-	void (*lm_put_lock) (void *lock);
-
-	unsigned int (*lm_lock) (void *lock, unsigned int cur_state,
-				 unsigned int req_state, unsigned int flags);
-
-	unsigned int (*lm_unlock) (void *lock, unsigned int cur_state);
-
-	void (*lm_cancel) (void *lock);
-
-	int (*lm_hold_lvb) (void *lock, char **lvbp);
-	void (*lm_unhold_lvb) (void *lock, char *lvb);
-
-	/*
-	 * Posix Lock oriented operations
-	 */
-
-	int (*lm_plock_get) (void *lockspace, struct lm_lockname *name,
-			     struct file *file, struct file_lock *fl);
-
-	int (*lm_plock) (void *lockspace, struct lm_lockname *name,
-			 struct file *file, int cmd, struct file_lock *fl);
-
-	int (*lm_punlock) (void *lockspace, struct lm_lockname *name,
-			   struct file *file, struct file_lock *fl);
-
-	/*
-	 * Client oriented operations
-	 */
-
-	void (*lm_recovery_done) (void *lockspace, unsigned int jid,
-				  unsigned int message);
-
-	struct module *lm_owner;
-};
-
-/*
- * lm_mount() return values
- *
- * ls_jid - the journal ID this node should use
- * ls_first - this node is the first to mount the file system
- * ls_lvb_size - size in bytes of lock value blocks
- * ls_lockspace - lock module's context for this file system
- * ls_ops - lock module's functions
- * ls_flags - lock module features
- */
-
-struct lm_lockstruct {
-	unsigned int ls_jid;
-	unsigned int ls_first;
-	unsigned int ls_lvb_size;
-	void *ls_lockspace;
-	const struct lm_lockops *ls_ops;
-	int ls_flags;
-};
-
-/*
- * Lock module bottom interface.  A lock module makes itself available to GFS
- * with these functions.
- */
-
-int gfs2_register_lockproto(const struct lm_lockops *proto);
-void gfs2_unregister_lockproto(const struct lm_lockops *proto);
-
-/*
- * Lock module top interface.  GFS calls these functions when mounting or
- * unmounting a file system.
- */
-
-int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data,
-			 lm_callback_t cb, void *cb_data,
-			 unsigned int min_lvb_size, int flags,
-			 struct lm_lockstruct *lockstruct,
-			 struct kobject *fskobj);
-
-void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct);
-
-void gfs2_withdraw_lockproto(struct lm_lockstruct *lockstruct);
-
-#endif /* __LM_INTERFACE_DOT_H__ */
-
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index aa6fe70..51855df 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -346,6 +346,7 @@
 	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 static inline int __nlm_cmp_addr6(const struct sockaddr *sap1,
 				  const struct sockaddr *sap2)
 {
@@ -353,6 +354,13 @@
 	const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
 	return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
 }
+#else	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
+static inline int __nlm_cmp_addr6(const struct sockaddr *sap1,
+				  const struct sockaddr *sap2)
+{
+	return 0;
+}
+#endif	/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
 
 /*
  * Compare two host addresses
diff --git a/include/linux/maple.h b/include/linux/maple.h
index c23d3f5..d9a51b9 100644
--- a/include/linux/maple.h
+++ b/include/linux/maple.h
@@ -8,33 +8,49 @@
 
 /* Maple Bus command and response codes */
 enum maple_code {
-	MAPLE_RESPONSE_FILEERR = -5,
-	MAPLE_RESPONSE_AGAIN = -4,	/* request should be retransmitted */
-	MAPLE_RESPONSE_BADCMD = -3,
-	MAPLE_RESPONSE_BADFUNC = -2,
-	MAPLE_RESPONSE_NONE = -1,	/* unit didn't respond at all */
-	MAPLE_COMMAND_DEVINFO = 1,
-	MAPLE_COMMAND_ALLINFO = 2,
-	MAPLE_COMMAND_RESET = 3,
-	MAPLE_COMMAND_KILL = 4,
-	MAPLE_RESPONSE_DEVINFO = 5,
-	MAPLE_RESPONSE_ALLINFO = 6,
-	MAPLE_RESPONSE_OK = 7,
-	MAPLE_RESPONSE_DATATRF = 8,
-	MAPLE_COMMAND_GETCOND = 9,
-	MAPLE_COMMAND_GETMINFO = 10,
-	MAPLE_COMMAND_BREAD = 11,
-	MAPLE_COMMAND_BWRITE = 12,
-	MAPLE_COMMAND_SETCOND = 14
+	MAPLE_RESPONSE_FILEERR =	-5,
+	MAPLE_RESPONSE_AGAIN,	/* retransmit */
+	MAPLE_RESPONSE_BADCMD,
+	MAPLE_RESPONSE_BADFUNC,
+	MAPLE_RESPONSE_NONE,	/* unit didn't respond*/
+	MAPLE_COMMAND_DEVINFO =		1,
+	MAPLE_COMMAND_ALLINFO,
+	MAPLE_COMMAND_RESET,
+	MAPLE_COMMAND_KILL,
+	MAPLE_RESPONSE_DEVINFO,
+	MAPLE_RESPONSE_ALLINFO,
+	MAPLE_RESPONSE_OK,
+	MAPLE_RESPONSE_DATATRF,
+	MAPLE_COMMAND_GETCOND,
+	MAPLE_COMMAND_GETMINFO,
+	MAPLE_COMMAND_BREAD,
+	MAPLE_COMMAND_BWRITE,
+	MAPLE_COMMAND_BSYNC,
+	MAPLE_COMMAND_SETCOND,
+	MAPLE_COMMAND_MICCONTROL
+};
+
+enum maple_file_errors {
+	MAPLE_FILEERR_INVALID_PARTITION =	0x01000000,
+	MAPLE_FILEERR_PHASE_ERROR =		0x02000000,
+	MAPLE_FILEERR_INVALID_BLOCK =		0x04000000,
+	MAPLE_FILEERR_WRITE_ERROR =		0x08000000,
+	MAPLE_FILEERR_INVALID_WRITE_LENGTH =	0x10000000,
+	MAPLE_FILEERR_BAD_CRC = 		0x20000000
+};
+
+struct maple_buffer {
+	char bufx[0x400];
+	void *buf;
 };
 
 struct mapleq {
 	struct list_head list;
 	struct maple_device *dev;
-	void *sendbuf, *recvbuf, *recvbufdcsp;
+	struct maple_buffer *recvbuf;
+	void *sendbuf, *recvbuf_p2;
 	unsigned char length;
 	enum maple_code command;
-	struct mutex mutex;
 };
 
 struct maple_devinfo {
@@ -52,11 +68,15 @@
 	struct maple_driver *driver;
 	struct mapleq *mq;
 	void (*callback) (struct mapleq * mq);
+	void (*fileerr_handler)(struct maple_device *mdev, void *recvbuf);
+	int (*can_unload)(struct maple_device *mdev);
 	unsigned long when, interval, function;
 	struct maple_devinfo devinfo;
 	unsigned char port, unit;
 	char product_name[32];
 	char product_licence[64];
+	atomic_t busy;
+	wait_queue_head_t maple_wait;
 	struct device dev;
 };
 
@@ -72,7 +92,7 @@
 int maple_driver_register(struct maple_driver *);
 void maple_driver_unregister(struct maple_driver *);
 
-int maple_add_packet_sleeps(struct maple_device *mdev, u32 function,
+int maple_add_packet(struct maple_device *mdev, u32 function,
 	u32 command, u32 length, void *data);
 void maple_clear_dev(struct maple_device *mdev);
 
diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h
index af95a1d..d899dc0 100644
--- a/include/linux/mfd/wm8350/audio.h
+++ b/include/linux/mfd/wm8350/audio.h
@@ -490,6 +490,7 @@
 /*
  * R231 (0xE7) - Jack Status
  */
+#define WM8350_JACK_L_LVL			0x0800
 #define WM8350_JACK_R_LVL                       0x0400
 
 /*
diff --git a/include/linux/mfd/wm8400-audio.h b/include/linux/mfd/wm8400-audio.h
index b6640e0..e06ed3e 100644
--- a/include/linux/mfd/wm8400-audio.h
+++ b/include/linux/mfd/wm8400-audio.h
@@ -1181,6 +1181,7 @@
 #define WM8400_FLL_OUTDIV_SHIFT                      0  /* FLL_OUTDIV - [2:0] */
 #define WM8400_FLL_OUTDIV_WIDTH                      3  /* FLL_OUTDIV - [2:0] */
 
+struct wm8400;
 void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400);
 
 #endif
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 92915e8..d84feb7 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -276,4 +276,7 @@
 #endif
 };
 
+/* Future-safe accessor for struct mm_struct's cpu_vm_mask. */
+#define mm_cpumask(mm) (&(mm)->cpu_vm_mask)
+
 #endif /* _LINUX_MM_TYPES_H */
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index fde8667..1bf5900 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -454,4 +454,13 @@
 
 #define DMI_MATCH(a, b)	{ a, b }
 
+#define PLATFORM_NAME_SIZE	20
+#define PLATFORM_MODULE_PREFIX	"platform:"
+
+struct platform_device_id {
+	char name[PLATFORM_NAME_SIZE];
+	kernel_ulong_t driver_data
+			__attribute__((aligned(sizeof(kernel_ulong_t))));
+};
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/mount.h b/include/linux/mount.h
index cab2a85..51f55f9 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -27,6 +27,7 @@
 #define MNT_NODIRATIME	0x10
 #define MNT_RELATIME	0x20
 #define MNT_READONLY	0x40	/* does the user want this to be r/o? */
+#define MNT_STRICTATIME 0x80
 
 #define MNT_SHRINKABLE	0x100
 #define MNT_IMBALANCED_WRITE_COUNT	0x200 /* just for debugging */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a550b52..2e5f000 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -406,6 +406,8 @@
 	int			mask;
 	struct posix_acl *	acl_access;
 	struct posix_acl *	acl_default;
+	size_t			len;
+	unsigned int		npages;
 	struct page **		pages;
 };
 
diff --git a/include/linux/nfsacl.h b/include/linux/nfsacl.h
index 54487a9..43011b6 100644
--- a/include/linux/nfsacl.h
+++ b/include/linux/nfsacl.h
@@ -37,6 +37,9 @@
 #define NFSACL_MAXPAGES		((2*(8+12*NFS_ACL_MAX_ENTRIES) + PAGE_SIZE-1) \
 				 >> PAGE_SHIFT)
 
+#define NFS_ACL_MAX_ENTRIES_INLINE	(5)
+#define NFS_ACL_INLINE_BUFSIZE	((2*(2+3*NFS_ACL_MAX_ENTRIES_INLINE)) << 2)
+
 static inline unsigned int
 nfsacl_size(struct posix_acl *acl_access, struct posix_acl *acl_default)
 {
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 3f9687a..097f410 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2116,6 +2116,8 @@
 #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
 #define PCI_DEVICE_ID_MELLANOX_SINAI	0x6274
 
+#define PCI_VENDOR_ID_DFI		0x15bd
+
 #define PCI_VENDOR_ID_QUICKNET		0x15e2
 #define PCI_DEVICE_ID_QUICKNET_XJ	0x0500
 
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 9a34269..76e470a 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -12,6 +12,7 @@
 #define _PLATFORM_DEVICE_H_
 
 #include <linux/device.h>
+#include <linux/mod_devicetable.h>
 
 struct platform_device {
 	const char	* name;
@@ -19,8 +20,13 @@
 	struct device	dev;
 	u32		num_resources;
 	struct resource	* resource;
+	void		*platform_data;
+
+	struct platform_device_id	*id_entry;
 };
 
+#define platform_get_device_id(pdev)	((pdev)->id_entry)
+
 #define to_platform_device(x) container_of((x), struct platform_device, dev)
 
 extern int platform_device_register(struct platform_device *);
@@ -56,6 +62,7 @@
 	int (*resume_early)(struct platform_device *);
 	int (*resume)(struct platform_device *);
 	struct device_driver driver;
+	struct platform_device_id *id_table;
 };
 
 extern int platform_driver_register(struct platform_driver *);
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 24ba5f6..1d4e2d2 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -400,6 +400,9 @@
 
 #else /* !CONFIG_PM_SLEEP */
 
+#define device_pm_lock() do {} while (0)
+#define device_pm_unlock() do {} while (0)
+
 static inline int device_suspend(pm_message_t state)
 {
 	return 0;
@@ -409,6 +412,14 @@
 
 #endif /* !CONFIG_PM_SLEEP */
 
+/* How to reorder dpm_list after device_move() */
+enum dpm_order {
+	DPM_ORDER_NONE,
+	DPM_ORDER_DEV_AFTER_PARENT,
+	DPM_ORDER_PARENT_BEFORE_DEV,
+	DPM_ORDER_DEV_LAST,
+};
+
 /*
  * Global Power Management flags
  * Used to keep APM and ACPI from both being active
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8c216e0..2c36f62 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1175,6 +1175,8 @@
 	/* ??? */
 	unsigned int personality;
 	unsigned did_exec:1;
+	unsigned in_execve:1;	/* Tell the LSMs that the process is doing an
+				 * execve */
 	pid_t pid;
 	pid_t tgid;
 
@@ -1419,6 +1421,9 @@
 #endif
 };
 
+/* Future-safe accessor for struct task_struct's cpus_allowed. */
+#define tsk_cpumask(tsk) (&(tsk)->cpus_allowed)
+
 /*
  * Priority of a process goes from 0..MAX_PRIO-1, valid RT
  * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 1bcb357..e0417e4 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -212,7 +212,7 @@
 #define SERIO_FUJITSU	0x35
 #define SERIO_ZHENHUA	0x36
 #define SERIO_INEXIO	0x37
-#define SERIO_TOUCHIT213	0x37
+#define SERIO_TOUCHIT213	0x38
 #define SERIO_W8001	0x39
 
 #endif
diff --git a/include/linux/sh_cmt.h b/include/linux/sh_cmt.h
new file mode 100644
index 0000000..68cacde
--- /dev/null
+++ b/include/linux/sh_cmt.h
@@ -0,0 +1,13 @@
+#ifndef __SH_CMT_H__
+#define __SH_CMT_H__
+
+struct sh_cmt_config {
+	char *name;
+	unsigned long channel_offset;
+	int timer_bit;
+	char *clk;
+	unsigned long clockevent_rating;
+	unsigned long clocksource_rating;
+};
+
+#endif /* __SH_CMT_H__ */
diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h
index 68e212f..eb1423a 100644
--- a/include/linux/sh_intc.h
+++ b/include/linux/sh_intc.h
@@ -85,6 +85,7 @@
 }
 #endif
 
+unsigned int intc_evt2irq(unsigned int vector);
 void __init register_intc_controller(struct intc_desc *desc);
 int intc_set_priority(unsigned int irq, unsigned int prio);
 
diff --git a/include/linux/timeriomem-rng.h b/include/linux/timeriomem-rng.h
new file mode 100644
index 0000000..dd25317
--- /dev/null
+++ b/include/linux/timeriomem-rng.h
@@ -0,0 +1,21 @@
+/*
+ * linux/include/linux/timeriomem-rng.h
+ *
+ * Copyright (c) 2009 Alexander Clouter <alex@digriz.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/completion.h>
+
+struct timeriomem_rng_data {
+	struct completion	completion;
+	unsigned int		present:1;
+
+	u32 __iomem		*address;
+
+	/* measures in usecs */
+	unsigned int		period;
+};
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
new file mode 100644
index 0000000..3338b3f
--- /dev/null
+++ b/include/linux/tpm.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ * Debora Velarde <dvelarde@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#ifndef __LINUX_TPM_H__
+#define __LINUX_TPM_H__
+
+/*
+ * Chip num is this value or a valid tpm idx
+ */
+#define	TPM_ANY_NUM 0xFFFF
+
+#if defined(CONFIG_TCG_TPM)
+
+extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
+extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
+#endif
+#endif
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
index a0bb6bd..5dcc9ff 100644
--- a/include/linux/uio_driver.h
+++ b/include/linux/uio_driver.h
@@ -22,6 +22,7 @@
 
 /**
  * struct uio_mem - description of a UIO memory region
+ * @name:		name of the memory region for identification
  * @addr:		address of the device's memory
  * @size:		size of IO
  * @memtype:		type of memory addr points to
@@ -29,6 +30,7 @@
  * @map:		for use by the UIO core only.
  */
 struct uio_mem {
+	const char		*name;
 	unsigned long		addr;
 	unsigned long		size;
 	int			memtype;
@@ -42,12 +44,14 @@
 
 /**
  * struct uio_port - description of a UIO port region
+ * @name:		name of the port region for identification
  * @start:		start of port region
  * @size:		size of port region
  * @porttype:		type of port (see UIO_PORT_* below)
  * @portio:		for use by the UIO core only.
  */
 struct uio_port {
+	const char		*name;
 	unsigned long		start;
 	unsigned long		size;
 	int			porttype;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 88079fd..c6b2ab4 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -643,186 +643,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/**
- * usb_endpoint_num - get the endpoint's number
- * @epd: endpoint to be checked
- *
- * Returns @epd's number: 0 to 15.
- */
-static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
-{
-	return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-}
-
-/**
- * usb_endpoint_type - get the endpoint's transfer type
- * @epd: endpoint to be checked
- *
- * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
- * to @epd's transfer type.
- */
-static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
-{
-	return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-}
-
-/**
- * usb_endpoint_dir_in - check if the endpoint has IN direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type IN, otherwise it returns false.
- */
-static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
-}
-
-/**
- * usb_endpoint_dir_out - check if the endpoint has OUT direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type OUT, otherwise it returns false.
- */
-static inline int usb_endpoint_dir_out(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-}
-
-/**
- * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type bulk, otherwise it returns false.
- */
-static inline int usb_endpoint_xfer_bulk(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_BULK);
-}
-
-/**
- * usb_endpoint_xfer_control - check if the endpoint has control transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type control, otherwise it returns false.
- */
-static inline int usb_endpoint_xfer_control(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_CONTROL);
-}
-
-/**
- * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type interrupt, otherwise it returns
- * false.
- */
-static inline int usb_endpoint_xfer_int(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_INT);
-}
-
-/**
- * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type isochronous, otherwise it returns
- * false.
- */
-static inline int usb_endpoint_xfer_isoc(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_ISOC);
-}
-
-/**
- * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and IN direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_bulk_in(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and OUT direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_bulk_out(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
-}
-
-/**
- * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and IN direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_int_in(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and OUT direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_int_out(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
-}
-
-/**
- * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and IN direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_isoc_in(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and OUT direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_isoc_out(
-				const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
-}
-
-/*-------------------------------------------------------------------------*/
-
 #define USB_DEVICE_ID_MATCH_DEVICE \
 		(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
 #define USB_DEVICE_ID_MATCH_DEV_RANGE \
@@ -1357,8 +1177,8 @@
 	unsigned int transfer_flags;	/* (in) URB_SHORT_NOT_OK | ...*/
 	void *transfer_buffer;		/* (in) associated data buffer */
 	dma_addr_t transfer_dma;	/* (in) dma addr for transfer_buffer */
-	int transfer_buffer_length;	/* (in) data buffer length */
-	int actual_length;		/* (return) actual transfer length */
+	u32 transfer_buffer_length;	/* (in) data buffer length */
+	u32 actual_length;		/* (return) actual transfer length */
 	unsigned char *setup_packet;	/* (in) setup packet (control only) */
 	dma_addr_t setup_dma;		/* (in) dma addr for setup_packet */
 	int start_frame;		/* (modify) start frame (ISO) */
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 9b42bae..b145119 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -102,7 +102,7 @@
 #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,
+/* The Link Power Management (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 ...
  */
@@ -353,6 +353,185 @@
 #define USB_ENDPOINT_XFER_INT		3
 #define USB_ENDPOINT_MAX_ADJUSTABLE	0x80
 
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_endpoint_num - get the endpoint's number
+ * @epd: endpoint to be checked
+ *
+ * Returns @epd's number: 0 to 15.
+ */
+static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
+{
+	return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+}
+
+/**
+ * usb_endpoint_type - get the endpoint's transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
+ * to @epd's transfer type.
+ */
+static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
+{
+	return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+}
+
+/**
+ * usb_endpoint_dir_in - check if the endpoint has IN direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type IN, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_out(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+/**
+ * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type bulk, otherwise it returns false.
+ */
+static inline int usb_endpoint_xfer_bulk(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		USB_ENDPOINT_XFER_BULK);
+}
+
+/**
+ * usb_endpoint_xfer_control - check if the endpoint has control transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type control, otherwise it returns false.
+ */
+static inline int usb_endpoint_xfer_control(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		USB_ENDPOINT_XFER_CONTROL);
+}
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_int(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		USB_ENDPOINT_XFER_INT);
+}
+
+/**
+ * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type isochronous, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_isoc(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		USB_ENDPOINT_XFER_ISOC);
+}
+
+/**
+ * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_in(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_out(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_in(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_out(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_in(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_out(
+				const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -584,8 +763,8 @@
 	/* chapter 9 and authentication (wireless) device states */
 	USB_STATE_ATTACHED,
 	USB_STATE_POWERED,			/* wired */
-	USB_STATE_UNAUTHENTICATED,		/* auth */
 	USB_STATE_RECONNECTING,			/* auth */
+	USB_STATE_UNAUTHENTICATED,		/* auth */
 	USB_STATE_DEFAULT,			/* limited function */
 	USB_STATE_ADDRESS,
 	USB_STATE_CONFIGURED,			/* most functions */
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 935c380..acd7b0f 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -244,6 +244,10 @@
  *	value; it should return zero on successful initialization.
  * @unbind: Reverses @bind(); called as a side effect of unregistering
  *	this driver.
+ * @suspend: Notifies when the host stops sending USB traffic,
+ *	after function notifications
+ * @resume: Notifies configuration when the host restarts USB traffic,
+ *	before function notifications
  *
  * Devices default to reporting self powered operation.  Devices which rely
  * on bus powered operation should report this in their @bind() method.
@@ -268,6 +272,10 @@
 
 	int			(*bind)(struct usb_composite_dev *);
 	int			(*unbind)(struct usb_composite_dev *);
+
+	/* global suspend hooks */
+	void			(*suspend)(struct usb_composite_dev *);
+	void			(*resume)(struct usb_composite_dev *);
 };
 
 extern int usb_composite_register(struct usb_composite_driver *);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 0460a74..bbf45d5 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -598,6 +598,7 @@
 /**
  * usb_gadget_vbus_connect - Notify controller that VBUS is powered
  * @gadget:The device which now has VBUS power.
+ * Context: can sleep
  *
  * This call is used by a driver for an external transceiver (or GPIO)
  * that detects a VBUS power session starting.  Common responses include
@@ -636,6 +637,7 @@
 /**
  * usb_gadget_vbus_disconnect - notify controller about VBUS session end
  * @gadget:the device whose VBUS supply is being described
+ * Context: can sleep
  *
  * This call is used by a driver for an external transceiver (or GPIO)
  * that detects a VBUS power session ending.  Common responses include
@@ -792,19 +794,20 @@
 /**
  * usb_gadget_register_driver - register a gadget driver
  * @driver:the driver being registered
+ * Context: can sleep
  *
  * Call this in your gadget driver's module initialization function,
  * to tell the underlying usb controller driver about your driver.
  * The driver's bind() function will be called to bind it to a
  * gadget before this registration call returns.  It's expected that
  * the bind() functions will be in init sections.
- * This function must be called in a context that can sleep.
  */
 int usb_gadget_register_driver(struct usb_gadget_driver *driver);
 
 /**
  * usb_gadget_unregister_driver - unregister a gadget driver
  * @driver:the driver being unregistered
+ * Context: can sleep
  *
  * Call this in your gadget driver's module cleanup function,
  * to tell the underlying usb controller that your driver is
@@ -813,7 +816,6 @@
  * to unbind() and clean up any device state, before this procedure
  * finally returns.  It's expected that the unbind() functions
  * will in in exit sections, so may not be linked in some kernels.
- * This function must be called in a context that can sleep.
  */
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
 
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 94df4fe..1aaa826 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -80,12 +80,17 @@
 
 /* for board-specific init logic */
 extern int otg_set_transceiver(struct otg_transceiver *);
+#ifdef CONFIG_NOP_USB_XCEIV
+extern void usb_nop_xceiv_register(void);
+extern void usb_nop_xceiv_unregister(void);
+#endif
 
 
 /* for usb host and peripheral controller drivers */
 extern struct otg_transceiver *otg_get_transceiver(void);
 extern void otg_put_transceiver(struct otg_transceiver *);
 
+/* Context: can sleep */
 static inline int
 otg_start_hnp(struct otg_transceiver *otg)
 {
@@ -102,6 +107,8 @@
 
 
 /* for usb peripheral controller drivers */
+
+/* Context: can sleep */
 static inline int
 otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph)
 {
@@ -114,6 +121,7 @@
 	return otg->set_power(otg, mA);
 }
 
+/* Context: can sleep */
 static inline int
 otg_set_suspend(struct otg_transceiver *otg, int suspend)
 {
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 7f6c603..2526f3b 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -16,4 +16,7 @@
 /* device can't handle Set-Interface requests */
 #define USB_QUIRK_NO_SET_INTF		0x00000004
 
+/* device can't handle its Configuration or Interface strings */
+#define USB_QUIRK_CONFIG_INTF_STRINGS	0x00000008
+
 #endif /* __LINUX_USB_QUIRKS_H */
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 0b8617a..b958425 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -130,7 +130,8 @@
 	struct usb_device		*dev;
 	struct usb_serial_driver	*type;
 	struct usb_interface		*interface;
-	unsigned char			disconnected;
+	unsigned char			disconnected:1;
+	unsigned char			suspending:1;
 	unsigned char			minor;
 	unsigned char			num_ports;
 	unsigned char			num_port_pointers;
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index 1eea1ab..3d15fb9 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -96,39 +96,26 @@
 #define US_PR_CBI	0x00		/* Control/Bulk/Interrupt */
 #define US_PR_CB	0x01		/* Control/Bulk w/o interrupt */
 #define US_PR_BULK	0x50		/* bulk only */
-#ifdef CONFIG_USB_STORAGE_USBAT
+
 #define US_PR_USBAT	0x80		/* SCM-ATAPI bridge */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR09
 #define US_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR55
 #define US_PR_SDDR55	0x82		/* SDDR-55 (made up) */
-#endif
 #define US_PR_DPCM_USB  0xf0		/* Combination CB/SDDR09 */
-#ifdef CONFIG_USB_STORAGE_FREECOM
 #define US_PR_FREECOM   0xf1		/* Freecom */
-#endif
-#ifdef CONFIG_USB_STORAGE_DATAFAB
 #define US_PR_DATAFAB   0xf2		/* Datafab chipsets */
-#endif
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
 #define US_PR_JUMPSHOT  0xf3		/* Lexar Jumpshot */
-#endif
-#ifdef CONFIG_USB_STORAGE_ALAUDA
 #define US_PR_ALAUDA    0xf4		/* Alauda chipsets */
-#endif
-#ifdef CONFIG_USB_STORAGE_KARMA
 #define US_PR_KARMA     0xf5		/* Rio Karma */
-#endif
 
 #define US_PR_DEVICE	0xff		/* Use device's value */
 
 /*
  */
+extern int usb_usual_ignore_device(struct usb_interface *intf);
+extern struct usb_device_id usb_storage_usb_ids[];
+
 #ifdef CONFIG_USB_LIBUSUAL
 
-extern struct usb_device_id storage_usb_ids[];
 extern void usb_usual_set_present(int type);
 extern void usb_usual_clear_present(int type);
 extern int usb_usual_check_type(const struct usb_device_id *, int type);
diff --git a/include/scsi/fc/fc_fcoe.h b/include/scsi/fc/fc_fcoe.h
index 57aaa8f..f271d9c 100644
--- a/include/scsi/fc/fc_fcoe.h
+++ b/include/scsi/fc/fc_fcoe.h
@@ -31,10 +31,6 @@
 #define	ETH_P_FCOE	0x8906		/* FCOE ether type */
 #endif
 
-#ifndef ETH_P_8021Q
-#define	ETH_P_8021Q	0x8100
-#endif
-
 /*
  * FC_FCOE_OUI hasn't been standardized yet.   XXX TBD.
  */
diff --git a/include/scsi/fc/fc_fs.h b/include/scsi/fc/fc_fs.h
index 3e4801d..1b7af3a 100644
--- a/include/scsi/fc/fc_fs.h
+++ b/include/scsi/fc/fc_fs.h
@@ -337,4 +337,9 @@
 	FC_RJT_VENDOR =		0xff,	/* vendor specific reject */
 };
 
+/* default timeout values */
+
+#define FC_DEF_E_D_TOV	2000UL
+#define FC_DEF_R_A_TOV	10000UL
+
 #endif /* _FC_FS_H_ */
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 9f28763..a2e126b 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -68,9 +68,6 @@
 /*
  * FC HBA status
  */
-#define FC_PAUSE		    (1 << 1)
-#define FC_LINK_UP		    (1 << 0)
-
 enum fc_lport_state {
 	LPORT_ST_NONE = 0,
 	LPORT_ST_FLOGI,
@@ -339,31 +336,17 @@
 
 struct libfc_function_template {
 
-	/**
-	 * Mandatory Fields
-	 *
-	 * These handlers must be implemented by the LLD.
-	 */
-
 	/*
 	 * Interface to send a FC frame
+	 *
+	 * STATUS: REQUIRED
 	 */
 	int (*frame_send)(struct fc_lport *lp, struct fc_frame *fp);
 
-	/**
-	 * Optional Fields
-	 *
-	 * The LLD may choose to implement any of the following handlers.
-	 * If LLD doesn't specify hander and leaves its pointer NULL then
-	 * the default libfc function will be used for that handler.
-	 */
-
-	/**
-	 * ELS/CT interfaces
-	 */
-
 	/*
-	 * elsct_send - sends ELS/CT frame
+	 * Interface to send ELS/CT frames
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	struct fc_seq *(*elsct_send)(struct fc_lport *lport,
 				     struct fc_rport *rport,
@@ -373,9 +356,6 @@
 					     struct fc_frame *fp,
 					     void *arg),
 				     void *arg, u32 timer_msec);
-	/**
-	 * Exhance Manager interfaces
-	 */
 
 	/*
 	 * Send the FC frame payload using a new exchange and sequence.
@@ -407,6 +387,8 @@
 	 * timer_msec argument is specified. The timer is canceled when
 	 * it fires or when the exchange is done. The exchange timeout handler
 	 * is registered by EM layer.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	struct fc_seq *(*exch_seq_send)(struct fc_lport *lp,
 					struct fc_frame *fp,
@@ -418,14 +400,18 @@
 					void *arg, unsigned int timer_msec);
 
 	/*
-	 * send a frame using existing sequence and exchange.
+	 * Send a frame using an existing sequence and exchange.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	int (*seq_send)(struct fc_lport *lp, struct fc_seq *sp,
 			struct fc_frame *fp);
 
 	/*
-	 * Send ELS response using mainly infomation
-	 * in exchange and sequence in EM layer.
+	 * Send an ELS response using infomation from a previous
+	 * exchange and sequence.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*seq_els_rsp_send)(struct fc_seq *sp, enum fc_els_cmd els_cmd,
 				 struct fc_seq_els_data *els_data);
@@ -437,6 +423,8 @@
 	 * A timer_msec can be specified for abort timeout, if non-zero
 	 * timer_msec value is specified then exchange resp handler
 	 * will be called with timeout error if no response to abort.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	int (*seq_exch_abort)(const struct fc_seq *req_sp,
 			      unsigned int timer_msec);
@@ -444,6 +432,8 @@
 	/*
 	 * Indicate that an exchange/sequence tuple is complete and the memory
 	 * allocated for the related objects may be freed.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*exch_done)(struct fc_seq *sp);
 
@@ -451,6 +441,8 @@
 	 * Assigns a EM and a free XID for an new exchange and then
 	 * allocates a new exchange and sequence pair.
 	 * The fp can be used to determine free XID.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	struct fc_exch *(*exch_get)(struct fc_lport *lp, struct fc_frame *fp);
 
@@ -458,12 +450,16 @@
 	 * Release previously assigned XID by exch_get API.
 	 * The LLD may implement this if XID is assigned by LLD
 	 * in exch_get().
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*exch_put)(struct fc_lport *lp, struct fc_exch_mgr *mp,
 			 u16 ex_id);
 
 	/*
 	 * Start a new sequence on the same exchange/sequence tuple.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	struct fc_seq *(*seq_start_next)(struct fc_seq *sp);
 
@@ -471,26 +467,38 @@
 	 * Reset an exchange manager, completing all sequences and exchanges.
 	 * If s_id is non-zero, reset only exchanges originating from that FID.
 	 * If d_id is non-zero, reset only exchanges sending to that FID.
+	 *
+	 * STATUS: OPTIONAL
 	 */
-	void (*exch_mgr_reset)(struct fc_exch_mgr *,
+	void (*exch_mgr_reset)(struct fc_lport *,
 			       u32 s_id, u32 d_id);
 
-	void (*rport_flush_queue)(void);
-	/**
-	 * Local Port interfaces
+	/*
+	 * Flush the rport work queue. Generally used before shutdown.
+	 *
+	 * STATUS: OPTIONAL
 	 */
+	void (*rport_flush_queue)(void);
 
 	/*
-	 * Receive a frame to a local port.
+	 * Receive a frame for a local port.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*lport_recv)(struct fc_lport *lp, struct fc_seq *sp,
 			   struct fc_frame *fp);
 
+	/*
+	 * Reset the local port.
+	 *
+	 * STATUS: OPTIONAL
+	 */
 	int (*lport_reset)(struct fc_lport *);
 
-	/**
-	 * Remote Port interfaces
+	/*
+	 * Create a remote port
 	 */
+	struct fc_rport *(*rport_create)(struct fc_disc_port *);
 
 	/*
 	 * Initiates the RP state machine. It is called from the LP module.
@@ -500,26 +508,33 @@
 	 * - PLOGI
 	 * - PRLI
 	 * - RTV
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	int (*rport_login)(struct fc_rport *rport);
 
 	/*
 	 * Logoff, and remove the rport from the transport if
 	 * it had been added. This will send a LOGO to the target.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	int (*rport_logoff)(struct fc_rport *rport);
 
 	/*
 	 * Recieve a request from a remote port.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*rport_recv_req)(struct fc_seq *, struct fc_frame *,
 			       struct fc_rport *);
 
-	struct fc_rport *(*rport_lookup)(const struct fc_lport *, u32);
-
-	/**
-	 * FCP interfaces
+	/*
+	 * lookup an rport by it's port ID.
+	 *
+	 * STATUS: OPTIONAL
 	 */
+	struct fc_rport *(*rport_lookup)(const struct fc_lport *, u32);
 
 	/*
 	 * Send a fcp cmd from fsp pkt.
@@ -527,30 +542,38 @@
 	 *
 	 * The resp handler is called when FCP_RSP received.
 	 *
+	 * STATUS: OPTIONAL
 	 */
 	int (*fcp_cmd_send)(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
 			    void (*resp)(struct fc_seq *, struct fc_frame *fp,
 					 void *arg));
 
 	/*
-	 * Used at least durring linkdown and reset
+	 * Cleanup the FCP layer, used durring link down and reset
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*fcp_cleanup)(struct fc_lport *lp);
 
 	/*
 	 * Abort all I/O on a local port
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*fcp_abort_io)(struct fc_lport *lp);
 
-	/**
-	 * Discovery interfaces
+	/*
+	 * Receive a request for the discovery layer.
+	 *
+	 * STATUS: OPTIONAL
 	 */
-
 	void (*disc_recv_req)(struct fc_seq *,
 			      struct fc_frame *, struct fc_lport *);
 
 	/*
 	 * Start discovery for a local port.
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*disc_start)(void (*disc_callback)(struct fc_lport *,
 						 enum fc_disc_event),
@@ -559,6 +582,8 @@
 	/*
 	 * Stop discovery for a given lport. This will remove
 	 * all discovered rports
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*disc_stop) (struct fc_lport *);
 
@@ -566,6 +591,8 @@
 	 * Stop discovery for a given lport. This will block
 	 * until all discovered rports are deleted from the
 	 * FC transport class
+	 *
+	 * STATUS: OPTIONAL
 	 */
 	void (*disc_stop_final) (struct fc_lport *);
 };
@@ -603,7 +630,8 @@
 
 	/* Operational Information */
 	struct libfc_function_template tt;
-	u16			link_status;
+	u8			link_up;
+	u8			qfull;
 	enum fc_lport_state	state;
 	unsigned long		boot_time;
 
@@ -637,7 +665,7 @@
 	struct delayed_work	disc_work;
 };
 
-/**
+/*
  * FC_LPORT HELPER FUNCTIONS
  *****************************/
 static inline void *lport_priv(const struct fc_lport *lp)
@@ -669,7 +697,7 @@
 }
 
 
-/**
+/*
  * LOCAL PORT LAYER
  *****************************/
 int fc_lport_init(struct fc_lport *lp);
@@ -704,12 +732,6 @@
 void fc_linkdown(struct fc_lport *);
 
 /*
- * Pause and unpause traffic.
- */
-void fc_pause(struct fc_lport *);
-void fc_unpause(struct fc_lport *);
-
-/*
  * Configure the local port.
  */
 int fc_lport_config(struct fc_lport *);
@@ -725,19 +747,19 @@
 int fc_set_mfs(struct fc_lport *lp, u32 mfs);
 
 
-/**
+/*
  * REMOTE PORT LAYER
  *****************************/
 int fc_rport_init(struct fc_lport *lp);
 void fc_rport_terminate_io(struct fc_rport *rp);
 
-/**
+/*
  * DISCOVERY LAYER
  *****************************/
 int fc_disc_init(struct fc_lport *lp);
 
 
-/**
+/*
  * SCSI LAYER
  *****************************/
 /*
@@ -798,7 +820,7 @@
  */
 void fc_fcp_destroy(struct fc_lport *);
 
-/**
+/*
  * ELS/CT interface
  *****************************/
 /*
@@ -807,7 +829,7 @@
 int fc_elsct_init(struct fc_lport *lp);
 
 
-/**
+/*
  * EXCHANGE MANAGER LAYER
  *****************************/
 /*
@@ -916,7 +938,7 @@
  * If s_id is non-zero, reset only exchanges originating from that FID.
  * If d_id is non-zero, reset only exchanges sending to that FID.
  */
-void fc_exch_mgr_reset(struct fc_exch_mgr *, u32 s_id, u32 d_id);
+void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id);
 
 /*
  * Functions for fc_functions_template
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index 89fdbb9..941818f 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -46,6 +46,7 @@
 	struct net_device *phys_dev;		/* device with ethtool_ops */
 	struct packet_type  fcoe_packet_type;
 	struct sk_buff_head fcoe_pending_queue;
+	u8	fcoe_pending_queue_active;
 
 	u8 dest_addr[ETH_ALEN];
 	u8 ctl_src_addr[ETH_ALEN];
@@ -58,16 +59,10 @@
 	u8 address_mode;
 };
 
-static inline struct fcoe_softc *fcoe_softc(
-	const struct fc_lport *lp)
-{
-	return (struct fcoe_softc *)lport_priv(lp);
-}
-
 static inline struct net_device *fcoe_netdev(
 	const struct fc_lport *lp)
 {
-	return fcoe_softc(lp)->real_dev;
+	return ((struct fcoe_softc *)lport_priv(lp))->real_dev;
 }
 
 static inline struct fcoe_hdr *skb_fcoe_header(const struct sk_buff *skb)
diff --git a/include/sound/ad1816a.h b/include/sound/ad1816a.h
index b3aa62e..d010858 100644
--- a/include/sound/ad1816a.h
+++ b/include/sound/ad1816a.h
@@ -169,5 +169,7 @@
 
 extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm);
 extern int snd_ad1816a_mixer(struct snd_ad1816a *chip);
+extern int snd_ad1816a_timer(struct snd_ad1816a *chip, int device,
+			     struct snd_timer **rtimer);
 
 #endif	/* __SOUND_AD1816A_H */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 1c02ed1..fad3e0c 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -126,12 +126,10 @@
 	unsigned long driver_data;	/* W: driver-specific data */
 };
 
-enum {
-	SNDRV_HWDEP_IOCTL_PVERSION = _IOR ('H', 0x00, int),
-	SNDRV_HWDEP_IOCTL_INFO = _IOR ('H', 0x01, struct snd_hwdep_info),
-	SNDRV_HWDEP_IOCTL_DSP_STATUS = _IOR('H', 0x02, struct snd_hwdep_dsp_status),
-	SNDRV_HWDEP_IOCTL_DSP_LOAD   = _IOW('H', 0x03, struct snd_hwdep_dsp_image)
-};
+#define SNDRV_HWDEP_IOCTL_PVERSION	_IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO		_IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS	_IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD	_IOW('H', 0x03, struct snd_hwdep_dsp_image)
 
 /*****************************************************************************
  *                                                                           *
@@ -451,40 +449,35 @@
 	SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
 };
 
-enum {
-	SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
-	SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct snd_pcm_info),
-	SNDRV_PCM_IOCTL_TSTAMP = _IOW('A', 0x02, int),
-	SNDRV_PCM_IOCTL_TTSTAMP = _IOW('A', 0x03, int),
-	SNDRV_PCM_IOCTL_HW_REFINE = _IOWR('A', 0x10, struct snd_pcm_hw_params),
-	SNDRV_PCM_IOCTL_HW_PARAMS = _IOWR('A', 0x11, struct snd_pcm_hw_params),
-	SNDRV_PCM_IOCTL_HW_FREE = _IO('A', 0x12),
-	SNDRV_PCM_IOCTL_SW_PARAMS = _IOWR('A', 0x13, struct snd_pcm_sw_params),
-	SNDRV_PCM_IOCTL_STATUS = _IOR('A', 0x20, struct snd_pcm_status),
-	SNDRV_PCM_IOCTL_DELAY = _IOR('A', 0x21, snd_pcm_sframes_t),
-	SNDRV_PCM_IOCTL_HWSYNC = _IO('A', 0x22),
-	SNDRV_PCM_IOCTL_SYNC_PTR = _IOWR('A', 0x23, struct snd_pcm_sync_ptr),
-	SNDRV_PCM_IOCTL_CHANNEL_INFO = _IOR('A', 0x32, struct snd_pcm_channel_info),
-	SNDRV_PCM_IOCTL_PREPARE = _IO('A', 0x40),
-	SNDRV_PCM_IOCTL_RESET = _IO('A', 0x41),
-	SNDRV_PCM_IOCTL_START = _IO('A', 0x42),
-	SNDRV_PCM_IOCTL_DROP = _IO('A', 0x43),
-	SNDRV_PCM_IOCTL_DRAIN = _IO('A', 0x44),
-	SNDRV_PCM_IOCTL_PAUSE = _IOW('A', 0x45, int),
-	SNDRV_PCM_IOCTL_REWIND = _IOW('A', 0x46, snd_pcm_uframes_t),
-	SNDRV_PCM_IOCTL_RESUME = _IO('A', 0x47),
-	SNDRV_PCM_IOCTL_XRUN = _IO('A', 0x48),
-	SNDRV_PCM_IOCTL_FORWARD = _IOW('A', 0x49, snd_pcm_uframes_t),
-	SNDRV_PCM_IOCTL_WRITEI_FRAMES = _IOW('A', 0x50, struct snd_xferi),
-	SNDRV_PCM_IOCTL_READI_FRAMES = _IOR('A', 0x51, struct snd_xferi),
-	SNDRV_PCM_IOCTL_WRITEN_FRAMES = _IOW('A', 0x52, struct snd_xfern),
-	SNDRV_PCM_IOCTL_READN_FRAMES = _IOR('A', 0x53, struct snd_xfern),
-	SNDRV_PCM_IOCTL_LINK = _IOW('A', 0x60, int),
-	SNDRV_PCM_IOCTL_UNLINK = _IO('A', 0x61),
-};
-
-/* Trick to make alsa-lib/acinclude.m4 happy */
-#define SNDRV_PCM_IOCTL_REWIND SNDRV_PCM_IOCTL_REWIND
+#define SNDRV_PCM_IOCTL_PVERSION	_IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO		_IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP		_IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP		_IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE	_IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS	_IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE		_IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS	_IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS		_IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY		_IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC		_IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR	_IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO	_IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE		_IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET		_IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START		_IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP		_IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN		_IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE		_IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND		_IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME		_IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN		_IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD		_IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES	_IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES	_IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES	_IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES	_IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK		_IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK		_IO('A', 0x61)
 
 /*****************************************************************************
  *                                                                           *
@@ -538,14 +531,12 @@
 	unsigned char reserved[16];	/* reserved for future use */
 };
 
-enum {
-	SNDRV_RAWMIDI_IOCTL_PVERSION = _IOR('W', 0x00, int),
-	SNDRV_RAWMIDI_IOCTL_INFO = _IOR('W', 0x01, struct snd_rawmidi_info),
-	SNDRV_RAWMIDI_IOCTL_PARAMS = _IOWR('W', 0x10, struct snd_rawmidi_params),
-	SNDRV_RAWMIDI_IOCTL_STATUS = _IOWR('W', 0x20, struct snd_rawmidi_status),
-	SNDRV_RAWMIDI_IOCTL_DROP = _IOW('W', 0x30, int),
-	SNDRV_RAWMIDI_IOCTL_DRAIN = _IOW('W', 0x31, int),
-};
+#define SNDRV_RAWMIDI_IOCTL_PVERSION	_IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO	_IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS	_IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS	_IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP	_IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN	_IOW('W', 0x31, int)
 
 /*
  *  Timer section - /dev/snd/timer
@@ -654,23 +645,21 @@
 	unsigned char reserved[64];	/* reserved */
 };
 
-enum {
-	SNDRV_TIMER_IOCTL_PVERSION = _IOR('T', 0x00, int),
-	SNDRV_TIMER_IOCTL_NEXT_DEVICE = _IOWR('T', 0x01, struct snd_timer_id),
-	SNDRV_TIMER_IOCTL_TREAD = _IOW('T', 0x02, int),
-	SNDRV_TIMER_IOCTL_GINFO = _IOWR('T', 0x03, struct snd_timer_ginfo),
-	SNDRV_TIMER_IOCTL_GPARAMS = _IOW('T', 0x04, struct snd_timer_gparams),
-	SNDRV_TIMER_IOCTL_GSTATUS = _IOWR('T', 0x05, struct snd_timer_gstatus),
-	SNDRV_TIMER_IOCTL_SELECT = _IOW('T', 0x10, struct snd_timer_select),
-	SNDRV_TIMER_IOCTL_INFO = _IOR('T', 0x11, struct snd_timer_info),
-	SNDRV_TIMER_IOCTL_PARAMS = _IOW('T', 0x12, struct snd_timer_params),
-	SNDRV_TIMER_IOCTL_STATUS = _IOR('T', 0x14, struct snd_timer_status),
-	/* The following four ioctls are changed since 1.0.9 due to confliction */
-	SNDRV_TIMER_IOCTL_START = _IO('T', 0xa0),
-	SNDRV_TIMER_IOCTL_STOP = _IO('T', 0xa1),
-	SNDRV_TIMER_IOCTL_CONTINUE = _IO('T', 0xa2),
-	SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0xa3),
-};
+#define SNDRV_TIMER_IOCTL_PVERSION	_IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE	_IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD		_IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO		_IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS	_IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS	_IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT	_IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO		_IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS	_IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS	_IOR('T', 0x14, struct snd_timer_status)
+/* The following four ioctls are changed since 1.0.9 due to confliction */
+#define SNDRV_TIMER_IOCTL_START		_IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP		_IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE	_IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE		_IO('T', 0xa3)
 
 struct snd_timer_read {
 	unsigned int resolution;
@@ -847,33 +836,31 @@
         unsigned int tlv[0];	/* first TLV */
 };
 
-enum {
-	SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int),
-	SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info),
-	SNDRV_CTL_IOCTL_ELEM_LIST = _IOWR('U', 0x10, struct snd_ctl_elem_list),
-	SNDRV_CTL_IOCTL_ELEM_INFO = _IOWR('U', 0x11, struct snd_ctl_elem_info),
-	SNDRV_CTL_IOCTL_ELEM_READ = _IOWR('U', 0x12, struct snd_ctl_elem_value),
-	SNDRV_CTL_IOCTL_ELEM_WRITE = _IOWR('U', 0x13, struct snd_ctl_elem_value),
-	SNDRV_CTL_IOCTL_ELEM_LOCK = _IOW('U', 0x14, struct snd_ctl_elem_id),
-	SNDRV_CTL_IOCTL_ELEM_UNLOCK = _IOW('U', 0x15, struct snd_ctl_elem_id),
-	SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS = _IOWR('U', 0x16, int),
-	SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info),
-	SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info),
-	SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id),
-	SNDRV_CTL_IOCTL_TLV_READ = _IOWR('U', 0x1a, struct snd_ctl_tlv),
-	SNDRV_CTL_IOCTL_TLV_WRITE = _IOWR('U', 0x1b, struct snd_ctl_tlv),
-	SNDRV_CTL_IOCTL_TLV_COMMAND = _IOWR('U', 0x1c, struct snd_ctl_tlv),
-	SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int),
-	SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info),
-	SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int),
-	SNDRV_CTL_IOCTL_PCM_INFO = _IOWR('U', 0x31, struct snd_pcm_info),
-	SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE = _IOW('U', 0x32, int),
-	SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE = _IOWR('U', 0x40, int),
-	SNDRV_CTL_IOCTL_RAWMIDI_INFO = _IOWR('U', 0x41, struct snd_rawmidi_info),
-	SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE = _IOW('U', 0x42, int),
-	SNDRV_CTL_IOCTL_POWER = _IOWR('U', 0xd0, int),
-	SNDRV_CTL_IOCTL_POWER_STATE = _IOR('U', 0xd1, int),
-};
+#define SNDRV_CTL_IOCTL_PVERSION	_IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO	_IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST	_IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO	_IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ	_IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE	_IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK	_IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK	_IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD	_IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE	_IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE	_IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ	_IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE	_IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND	_IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO	_IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE	_IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO	_IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO	_IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER		_IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE	_IOR('U', 0xd1, int)
 
 /*
  *  Read interface.
@@ -919,18 +906,4 @@
 #define SNDRV_CTL_NAME_IEC958_PCM_STREAM		"PCM Stream"
 #define SNDRV_CTL_NAME_IEC958(expl,direction,what)	"IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
 
-/*
- *
- */
-
-struct snd_xferv {
-	const struct iovec *vector;
-	unsigned long count;
-};
-
-enum {
-	SNDRV_IOCTL_READV = _IOW('K', 0x00, struct snd_xferv),
-	SNDRV_IOCTL_WRITEV = _IOW('K', 0x01, struct snd_xferv),
-};
-
 #endif /* __SOUND_ASOUND_H */
diff --git a/include/sound/atmel-abdac.h b/include/sound/atmel-abdac.h
new file mode 100644
index 0000000..edff6a8
--- /dev/null
+++ b/include/sound/atmel-abdac.h
@@ -0,0 +1,23 @@
+/*
+ * Driver for the Atmel Audio Bitstream DAC (ABDAC)
+ *
+ * Copyright (C) 2009 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 __INCLUDE_SOUND_ATMEL_ABDAC_H
+#define __INCLUDE_SOUND_ATMEL_ABDAC_H
+
+#include <linux/dw_dmac.h>
+
+/**
+ * struct atmel_abdac_pdata - board specific ABDAC configuration
+ * @dws: DMA slave interface to use for sound playback.
+ */
+struct atmel_abdac_pdata {
+	struct dw_dma_slave	dws;
+};
+
+#endif /* __INCLUDE_SOUND_ATMEL_ABDAC_H */
diff --git a/include/sound/atmel-ac97c.h b/include/sound/atmel-ac97c.h
new file mode 100644
index 0000000..e6aabdb
--- /dev/null
+++ b/include/sound/atmel-ac97c.h
@@ -0,0 +1,40 @@
+/*
+ * Driver for the Atmel AC97C controller
+ *
+ * Copyright (C) 2005-2009 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 __INCLUDE_SOUND_ATMEL_AC97C_H
+#define __INCLUDE_SOUND_ATMEL_AC97C_H
+
+#include <linux/dw_dmac.h>
+
+#define AC97C_CAPTURE	0x01
+#define AC97C_PLAYBACK	0x02
+#define AC97C_BOTH	(AC97C_CAPTURE | AC97C_PLAYBACK)
+
+/**
+ * struct atmel_ac97c_pdata - board specific AC97C configuration
+ * @rx_dws: DMA slave interface to use for sound capture.
+ * @tx_dws: DMA slave interface to use for sound playback.
+ * @reset_pin: GPIO pin wired to the reset input on the external AC97 codec,
+ *             optional to use, set to -ENODEV if not in use. AC97 layer will
+ *             try to do a software reset of the external codec anyway.
+ * @flags: Flags for which directions should be enabled.
+ *
+ * If the user do not want to use a DMA channel for playback or capture, i.e.
+ * only one feature is required on the board. The slave for playback or capture
+ * can be set to NULL. The AC97C driver will take use of this when setting up
+ * the sound streams.
+ */
+struct ac97c_platform_data {
+	struct dw_dma_slave	rx_dws;
+	struct dw_dma_slave	tx_dws;
+	unsigned int 		flags;
+	int			reset_pin;
+};
+
+#endif /* __INCLUDE_SOUND_ATMEL_AC97C_H */
diff --git a/include/sound/control.h b/include/sound/control.h
index 4721b4b..ef96f07 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -171,6 +171,54 @@
  */
 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);
-		      
+int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
+		       unsigned int flags);
+/* optional flags for slave */
+#define SND_CTL_SLAVE_NEED_UPDATE	(1 << 0)
+
+/**
+ * snd_ctl_add_slave - Add a virtual slave control
+ * @master: vmaster element
+ * @slave: slave element to add
+ *
+ * Add a virtual slave control to the given master element created via
+ * snd_ctl_create_virtual_master() beforehand.
+ * Returns zero if successful or a negative error code.
+ *
+ * All slaves must be the same type (returning the same information
+ * via info callback).  The fucntion doesn't check it, so it's your
+ * responsibility.
+ *
+ * Also, some additional limitations:
+ * at most two channels,
+ * logarithmic volume control (dB level) thus no linear volume,
+ * master can only attenuate the volume without gain
+ */
+static inline int
+snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
+{
+	return _snd_ctl_add_slave(master, slave, 0);
+}
+
+/**
+ * snd_ctl_add_slave_uncached - Add a virtual slave control
+ * @master: vmaster element
+ * @slave: slave element to add
+ *
+ * Add a virtual slave control to the given master.
+ * Unlike snd_ctl_add_slave(), the element added via this function
+ * is supposed to have volatile values, and get callback is called
+ * at each time quried from the master.
+ *
+ * When the control peeks the hardware values directly and the value
+ * can be changed by other means than the put callback of the element,
+ * this function should be used to keep the value always up-to-date.
+ */
+static inline int
+snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
+			   struct snd_kcontrol *slave)
+{
+	return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE);
+}
+
 #endif	/* __SOUND_CONTROL_H */
diff --git a/include/sound/core.h b/include/sound/core.h
index f632484..3dea798 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -97,9 +97,9 @@
 
 struct snd_monitor_file {
 	struct file *file;
-	struct snd_monitor_file *next;
 	const struct file_operations *disconnected_f_op;
-	struct list_head shutdown_list;
+	struct list_head shutdown_list;	/* still need to shutdown */
+	struct list_head list;	/* link of monitor files */
 };
 
 /* main structure for soundcard */
@@ -134,7 +134,7 @@
 	struct snd_info_entry *proc_id;	/* the card id */
 	struct proc_dir_entry *proc_root_link;	/* number link to real id */
 
-	struct snd_monitor_file *files; /* all files associated to this card */
+	struct list_head files_list;	/* all files associated to this card */
 	struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown
 								state */
 	spinlock_t files_lock;		/* lock the files for this card */
@@ -296,8 +296,20 @@
 extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
 #endif
 
+int snd_card_create(int idx, const char *id,
+		    struct module *module, int extra_size,
+		    struct snd_card **card_ret);
+
+static inline __deprecated
 struct snd_card *snd_card_new(int idx, const char *id,
-			 struct module *module, int extra_size);
+			      struct module *module, int extra_size)
+{
+	struct snd_card *card;
+	if (snd_card_create(idx, id, module, extra_size, &card) < 0)
+		return NULL;
+	return card;
+}
+
 int snd_card_disconnect(struct snd_card *card);
 int snd_card_free(struct snd_card *card);
 int snd_card_free_when_closed(struct snd_card *card);
@@ -446,21 +458,33 @@
 struct snd_pci_quirk {
 	unsigned short subvendor;	/* PCI subvendor ID */
 	unsigned short subdevice;	/* PCI subdevice ID */
+	unsigned short subdevice_mask;	/* bitmask to match */
 	int value;			/* value */
 #ifdef CONFIG_SND_DEBUG_VERBOSE
 	const char *name;		/* name of the device (optional) */
 #endif
 };
 
-#define _SND_PCI_QUIRK_ID(vend,dev) \
-	.subvendor = (vend), .subdevice = (dev)
+#define _SND_PCI_QUIRK_ID_MASK(vend, mask, dev)	\
+	.subvendor = (vend), .subdevice = (dev), .subdevice_mask = (mask)
+#define _SND_PCI_QUIRK_ID(vend, dev) \
+	_SND_PCI_QUIRK_ID_MASK(vend, 0xffff, dev)
 #define SND_PCI_QUIRK_ID(vend,dev) {_SND_PCI_QUIRK_ID(vend, dev)}
 #ifdef CONFIG_SND_DEBUG_VERBOSE
 #define SND_PCI_QUIRK(vend,dev,xname,val) \
 	{_SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname)}
+#define SND_PCI_QUIRK_VENDOR(vend, xname, val)			\
+	{_SND_PCI_QUIRK_ID_MASK(vend, 0, 0), .value = (val), .name = (xname)}
+#define SND_PCI_QUIRK_MASK(vend, mask, dev, xname, val)			\
+	{_SND_PCI_QUIRK_ID_MASK(vend, mask, dev),			\
+			.value = (val), .name = (xname)}
 #else
 #define SND_PCI_QUIRK(vend,dev,xname,val) \
 	{_SND_PCI_QUIRK_ID(vend, dev), .value = (val)}
+#define SND_PCI_QUIRK_MASK(vend, mask, dev, xname, val)			\
+	{_SND_PCI_QUIRK_ID_MASK(vend, mask, dev), .value = (val)}
+#define SND_PCI_QUIRK_VENDOR(vend, xname, val)			\
+	{_SND_PCI_QUIRK_ID_MASK(vend, 0, 0), .value = (val)}
 #endif
 
 const struct snd_pci_quirk *
diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h
index d9eea01..8c05e47a 100644
--- a/include/sound/hwdep.h
+++ b/include/sound/hwdep.h
@@ -27,18 +27,28 @@
 
 struct snd_hwdep;
 
+/* hwdep file ops; all ops can be NULL */
 struct snd_hwdep_ops {
-	long long (*llseek) (struct snd_hwdep *hw, struct file * file, long long offset, int orig);
-	long (*read) (struct snd_hwdep *hw, char __user *buf, long count, loff_t *offset);
-	long (*write) (struct snd_hwdep *hw, const char __user *buf, long count, loff_t *offset);
-	int (*open) (struct snd_hwdep * hw, struct file * file);
-	int (*release) (struct snd_hwdep *hw, struct file * file);
-	unsigned int (*poll) (struct snd_hwdep *hw, struct file * file, poll_table * wait);
-	int (*ioctl) (struct snd_hwdep *hw, struct file * file, unsigned int cmd, unsigned long arg);
-	int (*ioctl_compat) (struct snd_hwdep *hw, struct file * file, unsigned int cmd, unsigned long arg);
-	int (*mmap) (struct snd_hwdep *hw, struct file * file, struct vm_area_struct * vma);
-	int (*dsp_status) (struct snd_hwdep *hw, struct snd_hwdep_dsp_status *status);
-	int (*dsp_load) (struct snd_hwdep *hw, struct snd_hwdep_dsp_image *image);
+	long long (*llseek)(struct snd_hwdep *hw, struct file *file,
+			    long long offset, int orig);
+	long (*read)(struct snd_hwdep *hw, char __user *buf,
+		     long count, loff_t *offset);
+	long (*write)(struct snd_hwdep *hw, const char __user *buf,
+		      long count, loff_t *offset);
+	int (*open)(struct snd_hwdep *hw, struct file * file);
+	int (*release)(struct snd_hwdep *hw, struct file * file);
+	unsigned int (*poll)(struct snd_hwdep *hw, struct file *file,
+			     poll_table *wait);
+	int (*ioctl)(struct snd_hwdep *hw, struct file *file,
+		     unsigned int cmd, unsigned long arg);
+	int (*ioctl_compat)(struct snd_hwdep *hw, struct file *file,
+			    unsigned int cmd, unsigned long arg);
+	int (*mmap)(struct snd_hwdep *hw, struct file *file,
+		    struct vm_area_struct *vma);
+	int (*dsp_status)(struct snd_hwdep *hw,
+			  struct snd_hwdep_dsp_status *status);
+	int (*dsp_load)(struct snd_hwdep *hw,
+			struct snd_hwdep_dsp_image *image);
 };
 
 struct snd_hwdep {
@@ -61,9 +71,9 @@
 	void (*private_free) (struct snd_hwdep *hwdep);
 
 	struct mutex open_mutex;
-	int used;
-	unsigned int dsp_loaded;
-	unsigned int exclusive: 1;
+	int used;			/* reference counter */
+	unsigned int dsp_loaded;	/* bit fields of loaded dsp indices */
+	unsigned int exclusive:1;	/* exclusive access mode */
 };
 
 extern int snd_hwdep_new(struct snd_card *card, char *id, int device,
diff --git a/include/sound/jack.h b/include/sound/jack.h
index 2e0315c..6b013c6 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -30,6 +30,9 @@
 /**
  * Jack types which can be reported.  These values are used as a
  * bitmask.
+ *
+ * Note that this must be kept in sync with the lookup table in
+ * sound/core/jack.c.
  */
 enum snd_jack_types {
 	SND_JACK_HEADPHONE	= 0x0001,
@@ -37,6 +40,8 @@
 	SND_JACK_HEADSET	= SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
 	SND_JACK_LINEOUT	= 0x0004,
 	SND_JACK_MECHANICAL	= 0x0008, /* If detected separately */
+	SND_JACK_VIDEOOUT	= 0x0010,
+	SND_JACK_AVOUT		= SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
 };
 
 struct snd_jack {
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 40c5a6f..8904b19 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -364,7 +364,6 @@
         /* -- timer section -- */
 	struct snd_timer *timer;		/* timer */
 	unsigned timer_running: 1;	/* time is running */
-	spinlock_t timer_lock;
 	/* -- next substream -- */
 	struct snd_pcm_substream *next;
 	/* -- linked substreams -- */
@@ -451,7 +450,7 @@
 
 extern const struct file_operations snd_pcm_f_ops[2];
 
-int snd_pcm_new(struct snd_card *card, char *id, int device,
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
 		int playback_count, int capture_count,
 		struct snd_pcm **rpcm);
 int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count);
diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 2fd3d25..2c894b6 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -42,4 +42,19 @@
 extern int pxa2xx_ac97_hw_probe(struct platform_device *dev);
 extern void pxa2xx_ac97_hw_remove(struct platform_device *dev);
 
+/* AC97 platform_data */
+/**
+ * struct pxa2xx_ac97_platform_data - pxa ac97 platform data
+ * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95)
+ *              a -1 value means no gpio will be used for reset
+ *
+ * Platform data should only be specified for pxa27x CPUs where a silicon bug
+ * prevents correct operation of the reset line. If not specified, the default
+ * behaviour is to consider gpio 113 as the AC97 reset line, which is the
+ * default on most boards.
+ */
+struct pxa2xx_ac97_platform_data {
+	int reset_gpio;
+};
+
 #endif
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index b550a41..c23c265 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -42,7 +42,6 @@
 #define SNDRV_RAWMIDI_LFLG_INPUT	(1<<1)
 #define SNDRV_RAWMIDI_LFLG_OPEN		(3<<0)
 #define SNDRV_RAWMIDI_LFLG_APPEND	(1<<2)
-#define	SNDRV_RAWMIDI_LFLG_NOOPENLOCK	(1<<3)
 
 struct snd_rawmidi;
 struct snd_rawmidi_substream;
diff --git a/include/sound/sb.h b/include/sound/sb.h
index 85f93c5..4e62ee1 100644
--- a/include/sound/sb.h
+++ b/include/sound/sb.h
@@ -249,6 +249,7 @@
 #define SB_ALS4000_3D_AUTO_MUTE	0x52
 #define SB_ALS4000_ANALOG_BLOCK_CTRL 0x53
 #define SB_ALS4000_3D_DELAYLINE_PATTERN 0x54
+#define SB_ALS4000_CR3_CONFIGURATION	0xc3 /* bit 7 is Digital Loop Enable */
 #define SB_ALS4000_QSOUND	0xdb
 
 /* IRQ setting bitmap */
@@ -330,7 +331,8 @@
 	SB_MIX_DOUBLE,
 	SB_MIX_INPUT_SW,
 	SB_MIX_CAPTURE_PRO,
-	SB_MIX_CAPTURE_DT019X
+	SB_MIX_CAPTURE_DT019X,
+	SB_MIX_MONO_CAPTURE_ALS4K
 };
 
 #define SB_MIXVAL_DOUBLE(left_reg, right_reg, left_shift, right_shift, mask) \
diff --git a/include/sound/sfnt_info.h b/include/sound/sfnt_info.h
index 5d1ab9c..1bce7fd 100644
--- a/include/sound/sfnt_info.h
+++ b/include/sound/sfnt_info.h
@@ -202,13 +202,11 @@
 	int value2;	/* reserved */
 };
 
-enum {
-	SNDRV_EMUX_IOCTL_VERSION = _IOR('H', 0x80, unsigned int),
-	SNDRV_EMUX_IOCTL_LOAD_PATCH = _IOWR('H', 0x81, struct soundfont_patch_info),
-	SNDRV_EMUX_IOCTL_RESET_SAMPLES = _IO('H', 0x82),
-	SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES = _IO('H', 0x83),
-	SNDRV_EMUX_IOCTL_MEM_AVAIL = _IOW('H', 0x84, int),
-	SNDRV_EMUX_IOCTL_MISC_MODE = _IOWR('H', 0x84, struct snd_emux_misc_mode),
-};
+#define SNDRV_EMUX_IOCTL_VERSION	_IOR('H', 0x80, unsigned int)
+#define SNDRV_EMUX_IOCTL_LOAD_PATCH	_IOWR('H', 0x81, struct soundfont_patch_info)
+#define SNDRV_EMUX_IOCTL_RESET_SAMPLES	_IO('H', 0x82)
+#define SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES _IO('H', 0x83)
+#define SNDRV_EMUX_IOCTL_MEM_AVAIL	_IOW('H', 0x84, int)
+#define SNDRV_EMUX_IOCTL_MISC_MODE	_IOWR('H', 0x84, struct snd_emux_misc_mode)
 
 #endif /* __SOUND_SFNT_INFO_H */
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 24247f7..1367647 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -203,7 +203,7 @@
 	int (*resume)(struct snd_soc_dai *dai);
 
 	/* ops */
-	struct snd_soc_dai_ops ops;
+	struct snd_soc_dai_ops *ops;
 
 	/* DAI capabilities */
 	struct snd_soc_pcm_stream capture;
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index dfa8049..a7def6a 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -76,6 +76,11 @@
 	 wcontrols, wncontrols)\
 {	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
 	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
+#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \
+	 wcontrols, wncontrols)\
+{       .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \
+	.shift = wshift, .invert = winvert, .kcontrols = wcontrols, \
+	.num_kcontrols = wncontrols}
 #define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
 {	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
 	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0}
@@ -101,6 +106,11 @@
 {	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
 	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
 	.event = wevent, .event_flags = wflags}
+#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
+	wcontrols, wncontrols, wevent, wflags) \
+{       .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, \
+	.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \
 {	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
 	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \
@@ -182,6 +192,12 @@
 	.get = snd_soc_dapm_get_value_enum_double, \
 	.put = snd_soc_dapm_put_value_enum_double, \
 	.private_value = (unsigned long)&xenum }
+#define SOC_DAPM_PIN_SWITCH(xname) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \
+	.info = snd_soc_dapm_info_pin_switch, \
+	.get = snd_soc_dapm_get_pin_switch, \
+	.put = snd_soc_dapm_put_pin_switch, \
+	.private_value = (unsigned long)xname }
 
 /* dapm stream operations */
 #define SND_SOC_DAPM_STREAM_NOP			0x0
@@ -228,6 +244,12 @@
 	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo);
+int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *uncontrol);
+int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *uncontrol);
 int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
 	const struct snd_soc_dapm_widget *widget);
 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
@@ -250,10 +272,10 @@
 int snd_soc_dapm_sys_add(struct device *dev);
 
 /* dapm audio pin control and status */
-int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin);
-int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin);
-int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin);
-int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin);
+int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin);
+int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin);
+int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin);
+int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin);
 int snd_soc_dapm_sync(struct snd_soc_codec *codec);
 
 /* dapm widget types */
@@ -263,6 +285,7 @@
 	snd_soc_dapm_mux,			/* selects 1 analog signal from many inputs */
 	snd_soc_dapm_value_mux,			/* selects 1 analog signal from many inputs */
 	snd_soc_dapm_mixer,			/* mixes several analog signals together */
+	snd_soc_dapm_mixer_named_ctl,		/* mixer with named controls */
 	snd_soc_dapm_pga,			/* programmable gain/attenuation (volume) */
 	snd_soc_dapm_adc,			/* analog to digital converter */
 	snd_soc_dapm_dac,			/* digital to analog converter */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 24593ac..a40bc6f 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -16,6 +16,8 @@
 #include <linux/platform_device.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/control.h>
@@ -154,6 +156,8 @@
 	SND_SOC_BIAS_OFF,
 };
 
+struct snd_jack;
+struct snd_soc_card;
 struct snd_soc_device;
 struct snd_soc_pcm_stream;
 struct snd_soc_ops;
@@ -164,6 +168,11 @@
 struct snd_soc_codec;
 struct soc_enum;
 struct snd_soc_ac97_ops;
+struct snd_soc_jack;
+struct snd_soc_jack_pin;
+#ifdef CONFIG_GPIOLIB
+struct snd_soc_jack_gpio;
+#endif
 
 typedef int (*hw_write_t)(void *,const char* ,int);
 typedef int (*hw_read_t)(void *,char* ,int);
@@ -184,6 +193,19 @@
 int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
 	const struct snd_pcm_hardware *hw);
 
+/* Jack reporting */
+int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
+		     struct snd_soc_jack *jack);
+void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
+int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
+			  struct snd_soc_jack_pin *pins);
+#ifdef CONFIG_GPIOLIB
+int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
+			struct snd_soc_jack_gpio *gpios);
+void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
+			struct snd_soc_jack_gpio *gpios);
+#endif
+
 /* codec IO */
 #define snd_soc_read(codec, reg) codec->read(codec, reg)
 #define snd_soc_write(codec, reg, value) codec->write(codec, reg, value)
@@ -203,6 +225,8 @@
  */
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 	void *data, char *long_name);
+int snd_soc_add_controls(struct snd_soc_codec *codec,
+	const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
@@ -237,6 +261,48 @@
 int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 
+/**
+ * struct snd_soc_jack_pin - Describes a pin to update based on jack detection
+ *
+ * @pin:    name of the pin to update
+ * @mask:   bits to check for in reported jack status
+ * @invert: if non-zero then pin is enabled when status is not reported
+ */
+struct snd_soc_jack_pin {
+	struct list_head list;
+	const char *pin;
+	int mask;
+	bool invert;
+};
+
+/**
+ * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection
+ *
+ * @gpio:         gpio number
+ * @name:         gpio name
+ * @report:       value to report when jack detected
+ * @invert:       report presence in low state
+ * @debouce_time: debouce time in ms
+ */
+#ifdef CONFIG_GPIOLIB
+struct snd_soc_jack_gpio {
+	unsigned int gpio;
+	const char *name;
+	int report;
+	int invert;
+	int debounce_time;
+	struct snd_soc_jack *jack;
+	struct work_struct work;
+};
+#endif
+
+struct snd_soc_jack {
+	struct snd_jack *jack;
+	struct snd_soc_card *card;
+	struct list_head pins;
+	int status;
+};
+
 /* SoC PCM stream information */
 struct snd_soc_pcm_stream {
 	char *stream_name;
@@ -384,6 +450,8 @@
 
 	struct snd_soc_device *socdev;
 
+	struct snd_soc_codec *codec;
+
 	struct snd_soc_platform *platform;
 	struct delayed_work delayed_work;
 	struct work_struct deferred_resume_work;
@@ -393,7 +461,6 @@
 struct snd_soc_device {
 	struct device *dev;
 	struct snd_soc_card *card;
-	struct snd_soc_codec *codec;
 	struct snd_soc_codec_device *codec_dev;
 	void *codec_data;
 };
diff --git a/include/sound/uda1341.h b/include/sound/uda1341.h
deleted file mode 100644
index 110d5dc..0000000
--- a/include/sound/uda1341.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- *  linux/include/linux/l3/uda1341.h
- *
- * Philips UDA1341 mixer device driver for ALSA
- *
- * Copyright (c) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License.
- *
- * History:
- *
- * 2002-03-13 Tomas Kasparek Initial release - based on uda1341.h from OSS
- * 2002-03-30 Tomas Kasparek Proc filesystem support, complete mixer and DSP
- *                           features support
- */
-
-#define UDA1341_ALSA_NAME "snd-uda1341"
-
-/*
- * Default rate set after inicialization
- */
-#define AUDIO_RATE_DEFAULT	44100
-
-/*
- * UDA1341 L3 address and command types
- */
-#define UDA1341_L3ADDR		5
-#define UDA1341_DATA0		(UDA1341_L3ADDR << 2 | 0)
-#define UDA1341_DATA1		(UDA1341_L3ADDR << 2 | 1)
-#define UDA1341_STATUS		(UDA1341_L3ADDR << 2 | 2)
-
-enum uda1341_onoff {
-	OFF=0,
-	ON,
-};
-
-enum uda1341_format {
-	I2S=0,
-	LSB16,
-	LSB18,
-	LSB20,
-	MSB,
-	LSB16MSB,
-	LSB18MSB,
-	LSB20MSB,        
-};
-
-enum uda1341_fs {
-	F512=0,
-	F384,
-	F256,
-	Funused,
-};
-
-enum uda1341_peak {
-	BEFORE=0,
-	AFTER,
-};
-
-enum uda1341_filter {
-	FLAT=0,
-	MIN,
-	MIN2,
-	MAX,
-};
-
-enum uda1341_mixer {
-	DOUBLE,
-	LINE,
-	MIC,
-	MIXER,
-};
-
-enum uda1341_deemp {
-	NONE,
-	D32,
-	D44,
-	D48,
-};
-
-enum uda1341_config {
-	CMD_READ_REG = 0,
-	CMD_RESET,
-	CMD_FS,
-	CMD_FORMAT,
-	CMD_OGAIN,
-	CMD_IGAIN,
-	CMD_DAC,
-	CMD_ADC,
-	CMD_VOLUME,
-	CMD_BASS,
-	CMD_TREBBLE,
-	CMD_PEAK,
-	CMD_DEEMP,
-	CMD_MUTE,        
-	CMD_FILTER,
-	CMD_CH1,
-	CMD_CH2,
-	CMD_MIC,       
-	CMD_MIXER,
-	CMD_AGC,
-	CMD_IG,
-	CMD_AGC_TIME,
-	CMD_AGC_LEVEL,
-#ifdef CONFIG_PM
-	CMD_SUSPEND,
-	CMD_RESUME,
-#endif
-	CMD_LAST,
-};
-
-enum write_through {
-	//used in update_bits (write_cfg) to avoid l3_write - just update local copy of regs.
-	REGS_ONLY=0,
-	//update local regs and write value to uda1341 - do l3_write
-	FLUSH,
-};
-
-int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **clnt);
-
-/*
- * Local variables:
- * indent-tabs-mode: t
- * End:
- */
diff --git a/include/sound/version.h b/include/sound/version.h
index 2b48237..a7e74e2 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h */
-#define CONFIG_SND_VERSION "1.0.18a"
+#define CONFIG_SND_VERSION "1.0.19"
 #define CONFIG_SND_DATE ""
diff --git a/include/sound/wss.h b/include/sound/wss.h
index fd01f22..6d65f32 100644
--- a/include/sound/wss.h
+++ b/include/sound/wss.h
@@ -154,6 +154,7 @@
 		      unsigned short hardware,
 		      unsigned short hwshare,
 		      struct snd_wss **rchip);
+int snd_wss_free(struct snd_wss *chip);
 int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
 int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer);
 int snd_wss_mixer(struct snd_wss *chip);
diff --git a/init/Kconfig b/init/Kconfig
index f068071..6a5c5fe 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -675,6 +675,9 @@
 config SYSCTL
 	bool
 
+config ANON_INODES
+	bool
+
 menuconfig EMBEDDED
 	bool "Configure standard kernel features (for small systems)"
 	help
@@ -780,18 +783,6 @@
           This option allows to disable the internal PC-Speaker
           support, saving some memory.
 
-config COMPAT_BRK
-	bool "Disable heap randomization"
-	default y
-	help
-	  Randomizing heap placement makes heap exploits harder, but it
-	  also breaks ancient binaries (including anything libc5 based).
-	  This option changes the bootup default to heap randomization
-	  disabled, and can be overriden runtime by setting
-	  /proc/sys/kernel/randomize_va_space to 2.
-
-	  On non-ancient distros (post-2000 ones) N is usually a safe choice.
-
 config BASE_FULL
 	default y
 	bool "Enable full-sized data structures for core" if EMBEDDED
@@ -809,9 +800,6 @@
 	  support for "fast userspace mutexes".  The resulting kernel may not
 	  run glibc-based applications correctly.
 
-config ANON_INODES
-	bool
-
 config EPOLL
 	bool "Enable eventpoll support" if EMBEDDED
 	default y
@@ -897,6 +885,18 @@
 	  SLUB sysfs support. /sys/slab will not exist and there will be
 	  no support for cache validation etc.
 
+config COMPAT_BRK
+	bool "Disable heap randomization"
+	default y
+	help
+	  Randomizing heap placement makes heap exploits harder, but it
+	  also breaks ancient binaries (including anything libc5 based).
+	  This option changes the bootup default to heap randomization
+	  disabled, and can be overriden runtime by setting
+	  /proc/sys/kernel/randomize_va_space to 2.
+
+	  On non-ancient distros (post-2000 ones) N is usually a safe choice.
+
 choice
 	prompt "Choose SLAB allocator"
 	default SLUB
diff --git a/ipc/shm.c b/ipc/shm.c
index 05d51d2..f239d87 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -39,6 +39,7 @@
 #include <linux/nsproxy.h>
 #include <linux/mount.h>
 #include <linux/ipc_namespace.h>
+#include <linux/ima.h>
 
 #include <asm/uaccess.h>
 
@@ -383,6 +384,7 @@
 	error = PTR_ERR(file);
 	if (IS_ERR(file))
 		goto no_file;
+	ima_shm_check(file);
 
 	id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
 	if (id < 0) {
@@ -887,6 +889,7 @@
 	file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations);
 	if (!file)
 		goto out_free;
+	ima_shm_check(file);
 
 	file->private_data = sfd;
 	file->f_mapping = shp->shm_file->f_mapping;
diff --git a/kernel/fork.c b/kernel/fork.c
index a66fbde..4854c2c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1179,10 +1179,6 @@
 #endif
 	clear_all_latency_tracing(p);
 
-	/* Our parent execution domain becomes current domain
-	   These must match for thread signalling to apply */
-	p->parent_exec_id = p->self_exec_id;
-
 	/* ok, now we should be set up.. */
 	p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL);
 	p->pdeath_signal = 0;
@@ -1220,10 +1216,13 @@
 		set_task_cpu(p, smp_processor_id());
 
 	/* CLONE_PARENT re-uses the old parent */
-	if (clone_flags & (CLONE_PARENT|CLONE_THREAD))
+	if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
 		p->real_parent = current->real_parent;
-	else
+		p->parent_exec_id = current->parent_exec_id;
+	} else {
 		p->real_parent = current;
+		p->parent_exec_id = current->self_exec_id;
+	}
 
 	spin_lock(&current->sighand->siglock);
 
diff --git a/kernel/module.c b/kernel/module.c
index ba22484..7767223 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -822,7 +822,7 @@
 	mutex_lock(&module_mutex);
 	/* Store the name of the last unloaded module for diagnostic purposes */
 	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
-	unregister_dynamic_debug_module(mod->name);
+	ddebug_remove_module(mod->name);
 	free_module(mod);
 
  out:
@@ -1827,19 +1827,13 @@
 }
 #endif /* CONFIG_KALLSYMS */
 
-static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num)
+static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)
 {
-#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
-	unsigned int i;
-
-	for (i = 0; i < num; i++) {
-		register_dynamic_debug_module(debug[i].modname,
-					      debug[i].type,
-					      debug[i].logical_modname,
-					      debug[i].flag_names,
-					      debug[i].hash, debug[i].hash2);
-	}
-#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
+#ifdef CONFIG_DYNAMIC_DEBUG
+	if (ddebug_add_module(debug, num, debug->modname))
+		printk(KERN_ERR "dynamic debug error adding module: %s\n",
+					debug->modname);
+#endif
 }
 
 static void *module_alloc_update_bounds(unsigned long size)
@@ -2015,14 +2009,6 @@
 	if (err < 0)
 		goto free_mod;
 
-#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
-	mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t),
-				      mod->name);
-	if (!mod->refptr) {
-		err = -ENOMEM;
-		goto free_mod;
-	}
-#endif
 	if (pcpuindex) {
 		/* We have a special allocation for this section. */
 		percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size,
@@ -2030,7 +2016,7 @@
 					 mod->name);
 		if (!percpu) {
 			err = -ENOMEM;
-			goto free_percpu;
+			goto free_mod;
 		}
 		sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
 		mod->percpu = percpu;
@@ -2082,6 +2068,14 @@
 	/* Module has been moved. */
 	mod = (void *)sechdrs[modindex].sh_addr;
 
+#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
+	mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t),
+				      mod->name);
+	if (!mod->refptr) {
+		err = -ENOMEM;
+		goto free_init;
+	}
+#endif
 	/* Now we've moved module, initialize linked lists, etc. */
 	module_unload_init(mod);
 
@@ -2213,12 +2207,13 @@
 	add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
 
 	if (!mod->taints) {
-		struct mod_debug *debug;
+		struct _ddebug *debug;
 		unsigned int num_debug;
 
 		debug = section_objs(hdr, sechdrs, secstrings, "__verbose",
 				     sizeof(*debug), &num_debug);
-		dynamic_printk_setup(debug, num_debug);
+		if (debug)
+			dynamic_debug_setup(debug, num_debug);
 	}
 
 	/* sechdrs[0].sh_size is always zero */
@@ -2288,15 +2283,17 @@
 	ftrace_release(mod->module_core, mod->core_size);
  free_unload:
 	module_unload_free(mod);
-	module_free(mod, mod->module_init);
- free_core:
-	module_free(mod, mod->module_core);
- free_percpu:
-	if (percpu)
-		percpu_modfree(percpu);
+ free_init:
 #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
 	percpu_modfree(mod->refptr);
 #endif
+	module_free(mod, mod->module_init);
+ free_core:
+	module_free(mod, mod->module_core);
+	/* mod will be freed with core. Don't access it beyond this line! */
+ free_percpu:
+	if (percpu)
+		percpu_modfree(percpu);
  free_mod:
 	kfree(args);
  free_hdr:
diff --git a/kernel/signal.c b/kernel/signal.c
index 2a74fe8..1c88144 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1575,7 +1575,15 @@
 	read_lock(&tasklist_lock);
 	if (may_ptrace_stop()) {
 		do_notify_parent_cldstop(current, CLD_TRAPPED);
+		/*
+		 * Don't want to allow preemption here, because
+		 * sys_ptrace() needs this task to be inactive.
+		 *
+		 * XXX: implement read_unlock_no_resched().
+		 */
+		preempt_disable();
 		read_unlock(&tasklist_lock);
+		preempt_enable_no_resched();
 		schedule();
 	} else {
 		/*
diff --git a/kernel/softirq.c b/kernel/softirq.c
index bdbe9de..9041ea7 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -626,6 +626,7 @@
 			preempt_enable_no_resched();
 			cond_resched();
 			preempt_disable();
+			rcu_qsctr_inc((long)__bind_cpu);
 		}
 		preempt_enable();
 		set_current_state(TASK_INTERRUPTIBLE);
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 43f891b..00d59d0 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -122,8 +122,10 @@
 	if (likely(tsk->mm)) {
 		cputime_t time, dtime;
 		struct timeval value;
+		unsigned long flags;
 		u64 delta;
 
+		local_irq_save(flags);
 		time = tsk->stime + tsk->utime;
 		dtime = cputime_sub(time, tsk->acct_timexpd);
 		jiffies_to_timeval(cputime_to_jiffies(dtime), &value);
@@ -131,10 +133,12 @@
 		delta = delta * USEC_PER_SEC + value.tv_usec;
 
 		if (delta == 0)
-			return;
+			goto out;
 		tsk->acct_timexpd = time;
 		tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
 		tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
+	out:
+		local_irq_restore(flags);
 	}
 }
 
diff --git a/kernel/user.c b/kernel/user.c
index 6a9b696..850e0ba 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -20,7 +20,7 @@
 
 struct user_namespace init_user_ns = {
 	.kref = {
-		.refcount	= ATOMIC_INIT(1),
+		.refcount	= ATOMIC_INIT(2),
 	},
 	.creator = &root_user,
 };
@@ -286,14 +286,12 @@
 /* work function to remove sysfs directory for a user and free up
  * corresponding structures.
  */
-static void remove_user_sysfs_dir(struct work_struct *w)
+static void cleanup_user_struct(struct work_struct *w)
 {
 	struct user_struct *up = container_of(w, struct user_struct, work);
 	unsigned long flags;
 	int remove_user = 0;
 
-	if (up->user_ns != &init_user_ns)
-		return;
 	/* Make uid_hash_remove() + sysfs_remove_file() + kobject_del()
 	 * atomic.
 	 */
@@ -312,9 +310,11 @@
 	if (!remove_user)
 		goto done;
 
-	kobject_uevent(&up->kobj, KOBJ_REMOVE);
-	kobject_del(&up->kobj);
-	kobject_put(&up->kobj);
+	if (up->user_ns == &init_user_ns) {
+		kobject_uevent(&up->kobj, KOBJ_REMOVE);
+		kobject_del(&up->kobj);
+		kobject_put(&up->kobj);
+	}
 
 	sched_destroy_user(up);
 	key_put(up->uid_keyring);
@@ -335,7 +335,7 @@
 	atomic_inc(&up->__count);
 	spin_unlock_irqrestore(&uidhash_lock, flags);
 
-	INIT_WORK(&up->work, remove_user_sysfs_dir);
+	INIT_WORK(&up->work, cleanup_user_struct);
 	schedule_work(&up->work);
 }
 
diff --git a/lib/Kconfig b/lib/Kconfig
index 03c2c24..cea9e30 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -174,4 +174,10 @@
        bool "Disable obsolete cpumask functions" if DEBUG_PER_CPU_MAPS
        depends on EXPERIMENTAL && BROKEN
 
+#
+# Netlink attribute parsing support is select'ed if needed
+#
+config NLATTR
+	bool
+
 endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1bcf9cd..8fee0a1 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -847,60 +847,70 @@
 
 	  Say N if you are unsure.
 
-config DYNAMIC_PRINTK_DEBUG
-	bool "Enable dynamic printk() call support"
+config DYNAMIC_DEBUG
+	bool "Enable dynamic printk() support"
 	default n
 	depends on PRINTK
+	depends on DEBUG_FS
 	select PRINTK_DEBUG
 	help
 
 	  Compiles debug level messages into the kernel, which would not
 	  otherwise be available at runtime. These messages can then be
-	  enabled/disabled on a per module basis. This mechanism implicitly
-	  enables all pr_debug() and dev_dbg() calls. The impact of this
-	  compile option is a larger kernel text size of about 2%.
+	  enabled/disabled based on various levels of scope - per source file,
+	  function, module, format string, and line number. This mechanism
+	  implicitly enables all pr_debug() and dev_dbg() calls. The impact of
+	  this compile option is a larger kernel text size of about 2%.
 
 	  Usage:
 
-	  Dynamic debugging is controlled by the debugfs file,
-	  dynamic_printk/modules. This file contains a list of the modules that
-	  can be enabled. The format of the file is the module name, followed
-	  by a set of flags that can be enabled. The first flag is always the
-	  'enabled' flag. For example:
+	  Dynamic debugging is controlled via the 'dynamic_debug/ddebug' file,
+	  which is contained in the 'debugfs' filesystem. Thus, the debugfs
+	  filesystem must first be mounted before making use of this feature.
+	  We refer the control file as: <debugfs>/dynamic_debug/ddebug. This
+	  file contains a list of the debug statements that can be enabled. The
+	  format for each line of the file is:
 
-		<module_name> <enabled=0/1>
-				.
-				.
-				.
+		filename:lineno [module]function flags format
 
-	  <module_name> : Name of the module in which the debug call resides
-	  <enabled=0/1> : whether the messages are enabled or not
+	  filename : source file of the debug statement
+	  lineno : line number of the debug statement
+	  module : module that contains the debug statement
+	  function : function that contains the debug statement
+          flags : 'p' means the line is turned 'on' for printing
+          format : the format used for the debug statement
 
 	  From a live system:
 
-		snd_hda_intel enabled=0
-		fixup enabled=0
-		driver enabled=0
+		nullarbor:~ # cat <debugfs>/dynamic_debug/ddebug
+		# filename:lineno [module]function flags format
+		fs/aio.c:222 [aio]__put_ioctx - "__put_ioctx:\040freeing\040%p\012"
+		fs/aio.c:248 [aio]ioctx_alloc - "ENOMEM:\040nr_events\040too\040high\012"
+		fs/aio.c:1770 [aio]sys_io_cancel - "calling\040cancel\012"
 
-	  Enable a module:
+	  Example usage:
 
-	  	$echo "set enabled=1 <module_name>" > dynamic_printk/modules
+		// enable the message at line 1603 of file svcsock.c
+		nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+						<debugfs>/dynamic_debug/ddebug
 
-	  Disable a module:
+		// enable all the messages in file svcsock.c
+		nullarbor:~ # echo -n 'file svcsock.c +p' >
+						<debugfs>/dynamic_debug/ddebug
 
-	  	$echo "set enabled=0 <module_name>" > dynamic_printk/modules
+		// enable all the messages in the NFS server module
+		nullarbor:~ # echo -n 'module nfsd +p' >
+						<debugfs>/dynamic_debug/ddebug
 
-	  Enable all modules:
+		// enable all 12 messages in the function svc_process()
+		nullarbor:~ # echo -n 'func svc_process +p' >
+						<debugfs>/dynamic_debug/ddebug
 
-		$echo "set enabled=1 all" > dynamic_printk/modules
+		// disable all 12 messages in the function svc_process()
+		nullarbor:~ # echo -n 'func svc_process -p' >
+						<debugfs>/dynamic_debug/ddebug
 
-	  Disable all modules:
-
-		$echo "set enabled=0 all" > dynamic_printk/modules
-
-	  Finally, passing "dynamic_printk" at the command line enables
-	  debugging for all modules. This mode can be turned off via the above
-	  disable command.
+	  See Documentation/dynamic-debug-howto.txt for additional information.
 
 source "samples/Kconfig"
 
diff --git a/lib/Makefile b/lib/Makefile
index 32b0e64..0dd9229 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -82,7 +82,9 @@
 
 obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o
 
-obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o
+obj-$(CONFIG_DYNAMIC_DEBUG) += dynamic_debug.o
+
+obj-$(CONFIG_NLATTR) += nlattr.o
 
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 1338469..35a1f7f 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -948,15 +948,15 @@
  */
 int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
 {
-	int pos;		/* scans bitmap by regions of size order */
+	int pos, end;		/* scans bitmap by regions of size order */
 
-	for (pos = 0; pos < bits; pos += (1 << order))
-		if (__reg_op(bitmap, pos, order, REG_OP_ISFREE))
-			break;
-	if (pos == bits)
-		return -ENOMEM;
-	__reg_op(bitmap, pos, order, REG_OP_ALLOC);
-	return pos;
+	for (pos = 0 ; (end = pos + (1 << order)) <= bits; pos = end) {
+		if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
+			continue;
+		__reg_op(bitmap, pos, order, REG_OP_ALLOC);
+		return pos;
+	}
+	return -ENOMEM;
 }
 EXPORT_SYMBOL(bitmap_find_free_region);
 
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
new file mode 100644
index 0000000..833139c
--- /dev/null
+++ b/lib/dynamic_debug.c
@@ -0,0 +1,769 @@
+/*
+ * lib/dynamic_debug.c
+ *
+ * make pr_debug()/dev_dbg() calls runtime configurable based upon their
+ * source module.
+ *
+ * Copyright (C) 2008 Jason Baron <jbaron@redhat.com>
+ * By Greg Banks <gnb@melbourne.sgi.com>
+ * Copyright (c) 2008 Silicon Graphics Inc.  All Rights Reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kallsyms.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/list.h>
+#include <linux/sysctl.h>
+#include <linux/ctype.h>
+#include <linux/uaccess.h>
+#include <linux/dynamic_debug.h>
+#include <linux/debugfs.h>
+
+extern struct _ddebug __start___verbose[];
+extern struct _ddebug __stop___verbose[];
+
+/* dynamic_debug_enabled, and dynamic_debug_enabled2 are bitmasks in which
+ * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
+ * use independent hash functions, to reduce the chance of false positives.
+ */
+long long dynamic_debug_enabled;
+EXPORT_SYMBOL_GPL(dynamic_debug_enabled);
+long long dynamic_debug_enabled2;
+EXPORT_SYMBOL_GPL(dynamic_debug_enabled2);
+
+struct ddebug_table {
+	struct list_head link;
+	char *mod_name;
+	unsigned int num_ddebugs;
+	unsigned int num_enabled;
+	struct _ddebug *ddebugs;
+};
+
+struct ddebug_query {
+	const char *filename;
+	const char *module;
+	const char *function;
+	const char *format;
+	unsigned int first_lineno, last_lineno;
+};
+
+struct ddebug_iter {
+	struct ddebug_table *table;
+	unsigned int idx;
+};
+
+static DEFINE_MUTEX(ddebug_lock);
+static LIST_HEAD(ddebug_tables);
+static int verbose = 0;
+
+/* Return the last part of a pathname */
+static inline const char *basename(const char *path)
+{
+	const char *tail = strrchr(path, '/');
+	return tail ? tail+1 : path;
+}
+
+/* format a string into buf[] which describes the _ddebug's flags */
+static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
+				    size_t maxlen)
+{
+	char *p = buf;
+
+	BUG_ON(maxlen < 4);
+	if (dp->flags & _DPRINTK_FLAGS_PRINT)
+		*p++ = 'p';
+	if (p == buf)
+		*p++ = '-';
+	*p = '\0';
+
+	return buf;
+}
+
+/*
+ * must be called with ddebug_lock held
+ */
+
+static int disabled_hash(char hash, bool first_table)
+{
+	struct ddebug_table *dt;
+	char table_hash_value;
+
+	list_for_each_entry(dt, &ddebug_tables, link) {
+		if (first_table)
+			table_hash_value = dt->ddebugs->primary_hash;
+		else
+			table_hash_value = dt->ddebugs->secondary_hash;
+		if (dt->num_enabled && (hash == table_hash_value))
+			return 0;
+	}
+	return 1;
+}
+
+/*
+ * Search the tables for _ddebug's which match the given
+ * `query' and apply the `flags' and `mask' to them.  Tells
+ * the user which ddebug's were changed, or whether none
+ * were matched.
+ */
+static void ddebug_change(const struct ddebug_query *query,
+			   unsigned int flags, unsigned int mask)
+{
+	int i;
+	struct ddebug_table *dt;
+	unsigned int newflags;
+	unsigned int nfound = 0;
+	char flagbuf[8];
+
+	/* search for matching ddebugs */
+	mutex_lock(&ddebug_lock);
+	list_for_each_entry(dt, &ddebug_tables, link) {
+
+		/* match against the module name */
+		if (query->module != NULL &&
+		    strcmp(query->module, dt->mod_name))
+			continue;
+
+		for (i = 0 ; i < dt->num_ddebugs ; i++) {
+			struct _ddebug *dp = &dt->ddebugs[i];
+
+			/* match against the source filename */
+			if (query->filename != NULL &&
+			    strcmp(query->filename, dp->filename) &&
+			    strcmp(query->filename, basename(dp->filename)))
+				continue;
+
+			/* match against the function */
+			if (query->function != NULL &&
+			    strcmp(query->function, dp->function))
+				continue;
+
+			/* match against the format */
+			if (query->format != NULL &&
+			    strstr(dp->format, query->format) == NULL)
+				continue;
+
+			/* match against the line number range */
+			if (query->first_lineno &&
+			    dp->lineno < query->first_lineno)
+				continue;
+			if (query->last_lineno &&
+			    dp->lineno > query->last_lineno)
+				continue;
+
+			nfound++;
+
+			newflags = (dp->flags & mask) | flags;
+			if (newflags == dp->flags)
+				continue;
+
+			if (!newflags)
+				dt->num_enabled--;
+			else if (!dp-flags)
+				dt->num_enabled++;
+			dp->flags = newflags;
+			if (newflags) {
+				dynamic_debug_enabled |=
+						(1LL << dp->primary_hash);
+				dynamic_debug_enabled2 |=
+						(1LL << dp->secondary_hash);
+			} else {
+				if (disabled_hash(dp->primary_hash, true))
+					dynamic_debug_enabled &=
+						~(1LL << dp->primary_hash);
+				if (disabled_hash(dp->secondary_hash, false))
+					dynamic_debug_enabled2 &=
+						~(1LL << dp->secondary_hash);
+			}
+			if (verbose)
+				printk(KERN_INFO
+					"ddebug: changed %s:%d [%s]%s %s\n",
+					dp->filename, dp->lineno,
+					dt->mod_name, dp->function,
+					ddebug_describe_flags(dp, flagbuf,
+							sizeof(flagbuf)));
+		}
+	}
+	mutex_unlock(&ddebug_lock);
+
+	if (!nfound && verbose)
+		printk(KERN_INFO "ddebug: no matches for query\n");
+}
+
+/*
+ * Split the buffer `buf' into space-separated words.
+ * Handles simple " and ' quoting, i.e. without nested,
+ * embedded or escaped \".  Return the number of words
+ * or <0 on error.
+ */
+static int ddebug_tokenize(char *buf, char *words[], int maxwords)
+{
+	int nwords = 0;
+
+	while (*buf) {
+		char *end;
+
+		/* Skip leading whitespace */
+		while (*buf && isspace(*buf))
+			buf++;
+		if (!*buf)
+			break;	/* oh, it was trailing whitespace */
+
+		/* Run `end' over a word, either whitespace separated or quoted */
+		if (*buf == '"' || *buf == '\'') {
+			int quote = *buf++;
+			for (end = buf ; *end && *end != quote ; end++)
+				;
+			if (!*end)
+				return -EINVAL;	/* unclosed quote */
+		} else {
+			for (end = buf ; *end && !isspace(*end) ; end++)
+				;
+			BUG_ON(end == buf);
+		}
+		/* Here `buf' is the start of the word, `end' is one past the end */
+
+		if (nwords == maxwords)
+			return -EINVAL;	/* ran out of words[] before bytes */
+		if (*end)
+			*end++ = '\0';	/* terminate the word */
+		words[nwords++] = buf;
+		buf = end;
+	}
+
+	if (verbose) {
+		int i;
+		printk(KERN_INFO "%s: split into words:", __func__);
+		for (i = 0 ; i < nwords ; i++)
+			printk(" \"%s\"", words[i]);
+		printk("\n");
+	}
+
+	return nwords;
+}
+
+/*
+ * Parse a single line number.  Note that the empty string ""
+ * is treated as a special case and converted to zero, which
+ * is later treated as a "don't care" value.
+ */
+static inline int parse_lineno(const char *str, unsigned int *val)
+{
+	char *end = NULL;
+	BUG_ON(str == NULL);
+	if (*str == '\0') {
+		*val = 0;
+		return 0;
+	}
+	*val = simple_strtoul(str, &end, 10);
+	return end == NULL || end == str || *end != '\0' ? -EINVAL : 0;
+}
+
+/*
+ * Undo octal escaping in a string, inplace.  This is useful to
+ * allow the user to express a query which matches a format
+ * containing embedded spaces.
+ */
+#define isodigit(c)		((c) >= '0' && (c) <= '7')
+static char *unescape(char *str)
+{
+	char *in = str;
+	char *out = str;
+
+	while (*in) {
+		if (*in == '\\') {
+			if (in[1] == '\\') {
+				*out++ = '\\';
+				in += 2;
+				continue;
+			} else if (in[1] == 't') {
+				*out++ = '\t';
+				in += 2;
+				continue;
+			} else if (in[1] == 'n') {
+				*out++ = '\n';
+				in += 2;
+				continue;
+			} else if (isodigit(in[1]) &&
+			         isodigit(in[2]) &&
+			         isodigit(in[3])) {
+				*out++ = ((in[1] - '0')<<6) |
+				          ((in[2] - '0')<<3) |
+				          (in[3] - '0');
+				in += 4;
+				continue;
+			}
+		}
+		*out++ = *in++;
+	}
+	*out = '\0';
+
+	return str;
+}
+
+/*
+ * Parse words[] as a ddebug query specification, which is a series
+ * of (keyword, value) pairs chosen from these possibilities:
+ *
+ * func <function-name>
+ * file <full-pathname>
+ * file <base-filename>
+ * module <module-name>
+ * format <escaped-string-to-find-in-format>
+ * line <lineno>
+ * line <first-lineno>-<last-lineno> // where either may be empty
+ */
+static int ddebug_parse_query(char *words[], int nwords,
+			       struct ddebug_query *query)
+{
+	unsigned int i;
+
+	/* check we have an even number of words */
+	if (nwords % 2 != 0)
+		return -EINVAL;
+	memset(query, 0, sizeof(*query));
+
+	for (i = 0 ; i < nwords ; i += 2) {
+		if (!strcmp(words[i], "func"))
+			query->function = words[i+1];
+		else if (!strcmp(words[i], "file"))
+			query->filename = words[i+1];
+		else if (!strcmp(words[i], "module"))
+			query->module = words[i+1];
+		else if (!strcmp(words[i], "format"))
+			query->format = unescape(words[i+1]);
+		else if (!strcmp(words[i], "line")) {
+			char *first = words[i+1];
+			char *last = strchr(first, '-');
+			if (last)
+				*last++ = '\0';
+			if (parse_lineno(first, &query->first_lineno) < 0)
+				return -EINVAL;
+			if (last != NULL) {
+				/* range <first>-<last> */
+				if (parse_lineno(last, &query->last_lineno) < 0)
+					return -EINVAL;
+			} else {
+				query->last_lineno = query->first_lineno;
+			}
+		} else {
+			if (verbose)
+				printk(KERN_ERR "%s: unknown keyword \"%s\"\n",
+					__func__, words[i]);
+			return -EINVAL;
+		}
+	}
+
+	if (verbose)
+		printk(KERN_INFO "%s: q->function=\"%s\" q->filename=\"%s\" "
+		       "q->module=\"%s\" q->format=\"%s\" q->lineno=%u-%u\n",
+			__func__, query->function, query->filename,
+			query->module, query->format, query->first_lineno,
+			query->last_lineno);
+
+	return 0;
+}
+
+/*
+ * Parse `str' as a flags specification, format [-+=][p]+.
+ * Sets up *maskp and *flagsp to be used when changing the
+ * flags fields of matched _ddebug's.  Returns 0 on success
+ * or <0 on error.
+ */
+static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
+			       unsigned int *maskp)
+{
+	unsigned flags = 0;
+	int op = '=';
+
+	switch (*str) {
+	case '+':
+	case '-':
+	case '=':
+		op = *str++;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (verbose)
+		printk(KERN_INFO "%s: op='%c'\n", __func__, op);
+
+	for ( ; *str ; ++str) {
+		switch (*str) {
+		case 'p':
+			flags |= _DPRINTK_FLAGS_PRINT;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+	if (flags == 0)
+		return -EINVAL;
+	if (verbose)
+		printk(KERN_INFO "%s: flags=0x%x\n", __func__, flags);
+
+	/* calculate final *flagsp, *maskp according to mask and op */
+	switch (op) {
+	case '=':
+		*maskp = 0;
+		*flagsp = flags;
+		break;
+	case '+':
+		*maskp = ~0U;
+		*flagsp = flags;
+		break;
+	case '-':
+		*maskp = ~flags;
+		*flagsp = 0;
+		break;
+	}
+	if (verbose)
+		printk(KERN_INFO "%s: *flagsp=0x%x *maskp=0x%x\n",
+			__func__, *flagsp, *maskp);
+	return 0;
+}
+
+/*
+ * File_ops->write method for <debugfs>/dynamic_debug/conrol.  Gathers the
+ * command text from userspace, parses and executes it.
+ */
+static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
+				  size_t len, loff_t *offp)
+{
+	unsigned int flags = 0, mask = 0;
+	struct ddebug_query query;
+#define MAXWORDS 9
+	int nwords;
+	char *words[MAXWORDS];
+	char tmpbuf[256];
+
+	if (len == 0)
+		return 0;
+	/* we don't check *offp -- multiple writes() are allowed */
+	if (len > sizeof(tmpbuf)-1)
+		return -E2BIG;
+	if (copy_from_user(tmpbuf, ubuf, len))
+		return -EFAULT;
+	tmpbuf[len] = '\0';
+	if (verbose)
+		printk(KERN_INFO "%s: read %d bytes from userspace\n",
+			__func__, (int)len);
+
+	nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS);
+	if (nwords < 0)
+		return -EINVAL;
+	if (ddebug_parse_query(words, nwords-1, &query))
+		return -EINVAL;
+	if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
+		return -EINVAL;
+
+	/* actually go and implement the change */
+	ddebug_change(&query, flags, mask);
+
+	*offp += len;
+	return len;
+}
+
+/*
+ * Set the iterator to point to the first _ddebug object
+ * and return a pointer to that first object.  Returns
+ * NULL if there are no _ddebugs at all.
+ */
+static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
+{
+	if (list_empty(&ddebug_tables)) {
+		iter->table = NULL;
+		iter->idx = 0;
+		return NULL;
+	}
+	iter->table = list_entry(ddebug_tables.next,
+				 struct ddebug_table, link);
+	iter->idx = 0;
+	return &iter->table->ddebugs[iter->idx];
+}
+
+/*
+ * Advance the iterator to point to the next _ddebug
+ * object from the one the iterator currently points at,
+ * and returns a pointer to the new _ddebug.  Returns
+ * NULL if the iterator has seen all the _ddebugs.
+ */
+static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
+{
+	if (iter->table == NULL)
+		return NULL;
+	if (++iter->idx == iter->table->num_ddebugs) {
+		/* iterate to next table */
+		iter->idx = 0;
+		if (list_is_last(&iter->table->link, &ddebug_tables)) {
+			iter->table = NULL;
+			return NULL;
+		}
+		iter->table = list_entry(iter->table->link.next,
+					 struct ddebug_table, link);
+	}
+	return &iter->table->ddebugs[iter->idx];
+}
+
+/*
+ * Seq_ops start method.  Called at the start of every
+ * read() call from userspace.  Takes the ddebug_lock and
+ * seeks the seq_file's iterator to the given position.
+ */
+static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
+{
+	struct ddebug_iter *iter = m->private;
+	struct _ddebug *dp;
+	int n = *pos;
+
+	if (verbose)
+		printk(KERN_INFO "%s: called m=%p *pos=%lld\n",
+			__func__, m, (unsigned long long)*pos);
+
+	mutex_lock(&ddebug_lock);
+
+	if (!n)
+		return SEQ_START_TOKEN;
+	if (n < 0)
+		return NULL;
+	dp = ddebug_iter_first(iter);
+	while (dp != NULL && --n > 0)
+		dp = ddebug_iter_next(iter);
+	return dp;
+}
+
+/*
+ * Seq_ops next method.  Called several times within a read()
+ * call from userspace, with ddebug_lock held.  Walks to the
+ * next _ddebug object with a special case for the header line.
+ */
+static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	struct ddebug_iter *iter = m->private;
+	struct _ddebug *dp;
+
+	if (verbose)
+		printk(KERN_INFO "%s: called m=%p p=%p *pos=%lld\n",
+			__func__, m, p, (unsigned long long)*pos);
+
+	if (p == SEQ_START_TOKEN)
+		dp = ddebug_iter_first(iter);
+	else
+		dp = ddebug_iter_next(iter);
+	++*pos;
+	return dp;
+}
+
+/*
+ * Seq_ops show method.  Called several times within a read()
+ * call from userspace, with ddebug_lock held.  Formats the
+ * current _ddebug as a single human-readable line, with a
+ * special case for the header line.
+ */
+static int ddebug_proc_show(struct seq_file *m, void *p)
+{
+	struct ddebug_iter *iter = m->private;
+	struct _ddebug *dp = p;
+	char flagsbuf[8];
+
+	if (verbose)
+		printk(KERN_INFO "%s: called m=%p p=%p\n",
+			__func__, m, p);
+
+	if (p == SEQ_START_TOKEN) {
+		seq_puts(m,
+			"# filename:lineno [module]function flags format\n");
+		return 0;
+	}
+
+	seq_printf(m, "%s:%u [%s]%s %s \"",
+		   dp->filename, dp->lineno,
+		   iter->table->mod_name, dp->function,
+		   ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf)));
+	seq_escape(m, dp->format, "\t\r\n\"");
+	seq_puts(m, "\"\n");
+
+	return 0;
+}
+
+/*
+ * Seq_ops stop method.  Called at the end of each read()
+ * call from userspace.  Drops ddebug_lock.
+ */
+static void ddebug_proc_stop(struct seq_file *m, void *p)
+{
+	if (verbose)
+		printk(KERN_INFO "%s: called m=%p p=%p\n",
+			__func__, m, p);
+	mutex_unlock(&ddebug_lock);
+}
+
+static const struct seq_operations ddebug_proc_seqops = {
+	.start = ddebug_proc_start,
+	.next = ddebug_proc_next,
+	.show = ddebug_proc_show,
+	.stop = ddebug_proc_stop
+};
+
+/*
+ * File_ops->open method for <debugfs>/dynamic_debug/control.  Does the seq_file
+ * setup dance, and also creates an iterator to walk the _ddebugs.
+ * Note that we create a seq_file always, even for O_WRONLY files
+ * where it's not needed, as doing so simplifies the ->release method.
+ */
+static int ddebug_proc_open(struct inode *inode, struct file *file)
+{
+	struct ddebug_iter *iter;
+	int err;
+
+	if (verbose)
+		printk(KERN_INFO "%s: called\n", __func__);
+
+	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+	if (iter == NULL)
+		return -ENOMEM;
+
+	err = seq_open(file, &ddebug_proc_seqops);
+	if (err) {
+		kfree(iter);
+		return err;
+	}
+	((struct seq_file *) file->private_data)->private = iter;
+	return 0;
+}
+
+static const struct file_operations ddebug_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = ddebug_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release_private,
+	.write = ddebug_proc_write
+};
+
+/*
+ * Allocate a new ddebug_table for the given module
+ * and add it to the global list.
+ */
+int ddebug_add_module(struct _ddebug *tab, unsigned int n,
+			     const char *name)
+{
+	struct ddebug_table *dt;
+	char *new_name;
+
+	dt = kzalloc(sizeof(*dt), GFP_KERNEL);
+	if (dt == NULL)
+		return -ENOMEM;
+	new_name = kstrdup(name, GFP_KERNEL);
+	if (new_name == NULL) {
+		kfree(dt);
+		return -ENOMEM;
+	}
+	dt->mod_name = new_name;
+	dt->num_ddebugs = n;
+	dt->num_enabled = 0;
+	dt->ddebugs = tab;
+
+	mutex_lock(&ddebug_lock);
+	list_add_tail(&dt->link, &ddebug_tables);
+	mutex_unlock(&ddebug_lock);
+
+	if (verbose)
+		printk(KERN_INFO "%u debug prints in module %s\n",
+				 n, dt->mod_name);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ddebug_add_module);
+
+static void ddebug_table_free(struct ddebug_table *dt)
+{
+	list_del_init(&dt->link);
+	kfree(dt->mod_name);
+	kfree(dt);
+}
+
+/*
+ * Called in response to a module being unloaded.  Removes
+ * any ddebug_table's which point at the module.
+ */
+int ddebug_remove_module(char *mod_name)
+{
+	struct ddebug_table *dt, *nextdt;
+	int ret = -ENOENT;
+
+	if (verbose)
+		printk(KERN_INFO "%s: removing module \"%s\"\n",
+				__func__, mod_name);
+
+	mutex_lock(&ddebug_lock);
+	list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
+		if (!strcmp(dt->mod_name, mod_name)) {
+			ddebug_table_free(dt);
+			ret = 0;
+		}
+	}
+	mutex_unlock(&ddebug_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ddebug_remove_module);
+
+static void ddebug_remove_all_tables(void)
+{
+	mutex_lock(&ddebug_lock);
+	while (!list_empty(&ddebug_tables)) {
+		struct ddebug_table *dt = list_entry(ddebug_tables.next,
+						      struct ddebug_table,
+						      link);
+		ddebug_table_free(dt);
+	}
+	mutex_unlock(&ddebug_lock);
+}
+
+static int __init dynamic_debug_init(void)
+{
+	struct dentry *dir, *file;
+	struct _ddebug *iter, *iter_start;
+	const char *modname = NULL;
+	int ret = 0;
+	int n = 0;
+
+	dir = debugfs_create_dir("dynamic_debug", NULL);
+	if (!dir)
+		return -ENOMEM;
+	file = debugfs_create_file("control", 0644, dir, NULL,
+					&ddebug_proc_fops);
+	if (!file) {
+		debugfs_remove(dir);
+		return -ENOMEM;
+	}
+	if (__start___verbose != __stop___verbose) {
+		iter = __start___verbose;
+		modname = iter->modname;
+		iter_start = iter;
+		for (; iter < __stop___verbose; iter++) {
+			if (strcmp(modname, iter->modname)) {
+				ret = ddebug_add_module(iter_start, n, modname);
+				if (ret)
+					goto out_free;
+				n = 0;
+				modname = iter->modname;
+				iter_start = iter;
+			}
+			n++;
+		}
+		ret = ddebug_add_module(iter_start, n, modname);
+	}
+out_free:
+	if (ret) {
+		ddebug_remove_all_tables();
+		debugfs_remove(dir);
+		debugfs_remove(file);
+	}
+	return 0;
+}
+module_init(dynamic_debug_init);
diff --git a/lib/dynamic_printk.c b/lib/dynamic_printk.c
deleted file mode 100644
index 165a197..0000000
--- a/lib/dynamic_printk.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * lib/dynamic_printk.c
- *
- * make pr_debug()/dev_dbg() calls runtime configurable based upon their
- * their source module.
- *
- * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <linux/seq_file.h>
-#include <linux/debugfs.h>
-#include <linux/fs.h>
-
-extern struct mod_debug __start___verbose[];
-extern struct mod_debug __stop___verbose[];
-
-struct debug_name {
-	struct hlist_node hlist;
-	struct hlist_node hlist2;
-	int hash1;
-	int hash2;
-	char *name;
-	int enable;
-	int type;
-};
-
-static int nr_entries;
-static int num_enabled;
-int dynamic_enabled = DYNAMIC_ENABLED_NONE;
-static struct hlist_head module_table[DEBUG_HASH_TABLE_SIZE] =
-	{ [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT };
-static struct hlist_head module_table2[DEBUG_HASH_TABLE_SIZE] =
-	{ [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT };
-static DECLARE_MUTEX(debug_list_mutex);
-
-/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
- * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
- * use independent hash functions, to reduce the chance of false positives.
- */
-long long dynamic_printk_enabled;
-EXPORT_SYMBOL_GPL(dynamic_printk_enabled);
-long long dynamic_printk_enabled2;
-EXPORT_SYMBOL_GPL(dynamic_printk_enabled2);
-
-/* returns the debug module pointer. */
-static struct debug_name *find_debug_module(char *module_name)
-{
-	int i;
-	struct hlist_head *head;
-	struct hlist_node *node;
-	struct debug_name *element;
-
-	element = NULL;
-	for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) {
-		head = &module_table[i];
-		hlist_for_each_entry_rcu(element, node, head, hlist)
-			if (!strcmp(element->name, module_name))
-				return element;
-	}
-	return NULL;
-}
-
-/* returns the debug module pointer. */
-static struct debug_name *find_debug_module_hash(char *module_name, int hash)
-{
-	struct hlist_head *head;
-	struct hlist_node *node;
-	struct debug_name *element;
-
-	element = NULL;
-	head = &module_table[hash];
-	hlist_for_each_entry_rcu(element, node, head, hlist)
-		if (!strcmp(element->name, module_name))
-			return element;
-	return NULL;
-}
-
-/* caller must hold mutex*/
-static int __add_debug_module(char *mod_name, int hash, int hash2)
-{
-	struct debug_name *new;
-	char *module_name;
-	int ret = 0;
-
-	if (find_debug_module(mod_name)) {
-		ret = -EINVAL;
-		goto out;
-	}
-	module_name = kmalloc(strlen(mod_name) + 1, GFP_KERNEL);
-	if (!module_name) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	module_name = strcpy(module_name, mod_name);
-	module_name[strlen(mod_name)] = '\0';
-	new = kzalloc(sizeof(struct debug_name), GFP_KERNEL);
-	if (!new) {
-		kfree(module_name);
-		ret = -ENOMEM;
-		goto out;
-	}
-	INIT_HLIST_NODE(&new->hlist);
-	INIT_HLIST_NODE(&new->hlist2);
-	new->name = module_name;
-	new->hash1 = hash;
-	new->hash2 = hash2;
-	hlist_add_head_rcu(&new->hlist, &module_table[hash]);
-	hlist_add_head_rcu(&new->hlist2, &module_table2[hash2]);
-	nr_entries++;
-out:
-	return ret;
-}
-
-int unregister_dynamic_debug_module(char *mod_name)
-{
-	struct debug_name *element;
-	int ret = 0;
-
-	down(&debug_list_mutex);
-	element = find_debug_module(mod_name);
-	if (!element) {
-		ret = -EINVAL;
-		goto out;
-	}
-	hlist_del_rcu(&element->hlist);
-	hlist_del_rcu(&element->hlist2);
-	synchronize_rcu();
-	kfree(element->name);
-	if (element->enable)
-		num_enabled--;
-	kfree(element);
-	nr_entries--;
-out:
-	up(&debug_list_mutex);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module);
-
-int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
-					char *flags, int hash, int hash2)
-{
-	struct debug_name *elem;
-	int ret = 0;
-
-	down(&debug_list_mutex);
-	elem = find_debug_module(mod_name);
-	if (!elem) {
-		if (__add_debug_module(mod_name, hash, hash2))
-			goto out;
-		elem = find_debug_module(mod_name);
-		if (dynamic_enabled == DYNAMIC_ENABLED_ALL &&
-				!strcmp(mod_name, share_name)) {
-			elem->enable = true;
-			num_enabled++;
-		}
-	}
-	elem->type |= type;
-out:
-	up(&debug_list_mutex);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(register_dynamic_debug_module);
-
-int __dynamic_dbg_enabled_helper(char *mod_name, int type, int value, int hash)
-{
-	struct debug_name *elem;
-	int ret = 0;
-
-	if (dynamic_enabled == DYNAMIC_ENABLED_ALL)
-		return 1;
-	rcu_read_lock();
-	elem = find_debug_module_hash(mod_name, hash);
-	if (elem && elem->enable)
-		ret = 1;
-	rcu_read_unlock();
-	return ret;
-}
-EXPORT_SYMBOL_GPL(__dynamic_dbg_enabled_helper);
-
-static void set_all(bool enable)
-{
-	struct debug_name *e;
-	struct hlist_node *node;
-	int i;
-	long long enable_mask;
-
-	for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) {
-		if (module_table[i].first != NULL) {
-			hlist_for_each_entry(e, node, &module_table[i], hlist) {
-				e->enable = enable;
-			}
-		}
-	}
-	if (enable)
-		enable_mask = ULLONG_MAX;
-	else
-		enable_mask = 0;
-	dynamic_printk_enabled = enable_mask;
-	dynamic_printk_enabled2 = enable_mask;
-}
-
-static int disabled_hash(int i, bool first_table)
-{
-	struct debug_name *e;
-	struct hlist_node *node;
-
-	if (first_table) {
-		hlist_for_each_entry(e, node, &module_table[i], hlist) {
-			if (e->enable)
-				return 0;
-		}
-	} else {
-		hlist_for_each_entry(e, node, &module_table2[i], hlist2) {
-			if (e->enable)
-				return 0;
-		}
-	}
-	return 1;
-}
-
-static ssize_t pr_debug_write(struct file *file, const char __user *buf,
-				size_t length, loff_t *ppos)
-{
-	char *buffer, *s, *value_str, *setting_str;
-	int err, value;
-	struct debug_name *elem = NULL;
-	int all = 0;
-
-	if (length > PAGE_SIZE || length < 0)
-		return -EINVAL;
-
-	buffer = (char *)__get_free_page(GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	err = -EFAULT;
-	if (copy_from_user(buffer, buf, length))
-		goto out;
-
-	err = -EINVAL;
-	if (length < PAGE_SIZE)
-		buffer[length] = '\0';
-	else if (buffer[PAGE_SIZE-1])
-		goto out;
-
-	err = -EINVAL;
-	down(&debug_list_mutex);
-
-	if (strncmp("set", buffer, 3))
-		goto out_up;
-	s = buffer + 3;
-	setting_str = strsep(&s, "=");
-	if (s == NULL)
-		goto out_up;
-	setting_str = strstrip(setting_str);
-	value_str = strsep(&s, " ");
-	if (s == NULL)
-		goto out_up;
-	s = strstrip(s);
-	if (!strncmp(s, "all", 3))
-		all = 1;
-	else
-		elem = find_debug_module(s);
-	if (!strncmp(setting_str, "enable", 6)) {
-		value = !!simple_strtol(value_str, NULL, 10);
-		if (all) {
-			if (value) {
-				set_all(true);
-				num_enabled = nr_entries;
-				dynamic_enabled = DYNAMIC_ENABLED_ALL;
-			} else {
-				set_all(false);
-				num_enabled = 0;
-				dynamic_enabled = DYNAMIC_ENABLED_NONE;
-			}
-			err = 0;
-		} else if (elem) {
-			if (value && (elem->enable == 0)) {
-				dynamic_printk_enabled |= (1LL << elem->hash1);
-				dynamic_printk_enabled2 |= (1LL << elem->hash2);
-				elem->enable = 1;
-				num_enabled++;
-				dynamic_enabled = DYNAMIC_ENABLED_SOME;
-				err = 0;
-				printk(KERN_DEBUG
-					"debugging enabled for module %s\n",
-					elem->name);
-			} else if (!value && (elem->enable == 1)) {
-				elem->enable = 0;
-				num_enabled--;
-				if (disabled_hash(elem->hash1, true))
-					dynamic_printk_enabled &=
-							~(1LL << elem->hash1);
-				if (disabled_hash(elem->hash2, false))
-					dynamic_printk_enabled2 &=
-							~(1LL << elem->hash2);
-				if (num_enabled)
-					dynamic_enabled = DYNAMIC_ENABLED_SOME;
-				else
-					dynamic_enabled = DYNAMIC_ENABLED_NONE;
-				err = 0;
-				printk(KERN_DEBUG
-					"debugging disabled for module %s\n",
-					elem->name);
-			}
-		}
-	}
-	if (!err)
-		err = length;
-out_up:
-	up(&debug_list_mutex);
-out:
-	free_page((unsigned long)buffer);
-	return err;
-}
-
-static void *pr_debug_seq_start(struct seq_file *f, loff_t *pos)
-{
-	return (*pos < DEBUG_HASH_TABLE_SIZE) ? pos : NULL;
-}
-
-static void *pr_debug_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
-	(*pos)++;
-	if (*pos >= DEBUG_HASH_TABLE_SIZE)
-		return NULL;
-	return pos;
-}
-
-static void pr_debug_seq_stop(struct seq_file *s, void *v)
-{
-	/* Nothing to do */
-}
-
-static int pr_debug_seq_show(struct seq_file *s, void *v)
-{
-	struct hlist_head *head;
-	struct hlist_node *node;
-	struct debug_name *elem;
-	unsigned int i = *(loff_t *) v;
-
-	rcu_read_lock();
-	head = &module_table[i];
-	hlist_for_each_entry_rcu(elem, node, head, hlist) {
-		seq_printf(s, "%s enabled=%d", elem->name, elem->enable);
-		seq_printf(s, "\n");
-	}
-	rcu_read_unlock();
-	return 0;
-}
-
-static struct seq_operations pr_debug_seq_ops = {
-	.start = pr_debug_seq_start,
-	.next  = pr_debug_seq_next,
-	.stop  = pr_debug_seq_stop,
-	.show  = pr_debug_seq_show
-};
-
-static int pr_debug_open(struct inode *inode, struct file *filp)
-{
-	return seq_open(filp, &pr_debug_seq_ops);
-}
-
-static const struct file_operations pr_debug_operations = {
-	.open		= pr_debug_open,
-	.read		= seq_read,
-	.write		= pr_debug_write,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-static int __init dynamic_printk_init(void)
-{
-	struct dentry *dir, *file;
-	struct mod_debug *iter;
-	unsigned long value;
-
-	dir = debugfs_create_dir("dynamic_printk", NULL);
-	if (!dir)
-		return -ENOMEM;
-	file = debugfs_create_file("modules", 0644, dir, NULL,
-					&pr_debug_operations);
-	if (!file) {
-		debugfs_remove(dir);
-		return -ENOMEM;
-	}
-	for (value = (unsigned long)__start___verbose;
-		value < (unsigned long)__stop___verbose;
-		value += sizeof(struct mod_debug)) {
-			iter = (struct mod_debug *)value;
-			register_dynamic_debug_module(iter->modname,
-				iter->type,
-				iter->logical_modname,
-				iter->flag_names, iter->hash, iter->hash2);
-	}
-	if (dynamic_enabled == DYNAMIC_ENABLED_ALL)
-		set_all(true);
-	return 0;
-}
-module_init(dynamic_printk_init);
-/* may want to move this earlier so we can get traces as early as possible */
-
-static int __init dynamic_printk_setup(char *str)
-{
-	if (str)
-		return -ENOENT;
-	dynamic_enabled = DYNAMIC_ENABLED_ALL;
-	return 0;
-}
-/* Use early_param(), so we can get debug output as early as possible */
-early_param("dynamic_printk", dynamic_printk_setup);
diff --git a/lib/idr.c b/lib/idr.c
index c11c576..dab4bca 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -449,6 +449,7 @@
 
 	n = idp->layers * IDR_BITS;
 	p = idp->top;
+	rcu_assign_pointer(idp->top, NULL);
 	max = 1 << n;
 
 	id = 0;
@@ -467,7 +468,6 @@
 			p = *--paa;
 		}
 	}
-	rcu_assign_pointer(idp->top, NULL);
 	idp->layers = 0;
 }
 EXPORT_SYMBOL(idr_remove_all);
diff --git a/lib/kobject.c b/lib/kobject.c
index 0487d1f..a6dec32 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -212,7 +212,7 @@
  * @fmt: format string used to build the name
  * @vargs: vargs to format the string.
  */
-static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
+int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
 				  va_list vargs)
 {
 	const char *old_name = kobj->name;
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 3813102..97a777a 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -118,6 +118,13 @@
 	kset = top_kobj->kset;
 	uevent_ops = kset->uevent_ops;
 
+	/* skip the event, if uevent_suppress is set*/
+	if (kobj->uevent_suppress) {
+		pr_debug("kobject: '%s' (%p): %s: uevent_suppress "
+				 "caused the event to drop!\n",
+				 kobject_name(kobj), kobj, __func__);
+		return 0;
+	}
 	/* skip the event, if the filter returns zero. */
 	if (uevent_ops && uevent_ops->filter)
 		if (!uevent_ops->filter(kset, kobj)) {
@@ -251,7 +258,7 @@
 			goto exit;
 
 		retval = call_usermodehelper(argv[0], argv,
-					     env->envp, UMH_WAIT_EXEC);
+					     env->envp, UMH_NO_WAIT);
 	}
 
 exit:
diff --git a/net/netlink/attr.c b/lib/nlattr.c
similarity index 99%
rename from net/netlink/attr.c
rename to lib/nlattr.c
index 56c3ce7..80009a2 100644
--- a/net/netlink/attr.c
+++ b/lib/nlattr.c
@@ -281,6 +281,7 @@
 	return d;
 }
 
+#ifdef CONFIG_NET
 /**
  * __nla_reserve - reserve room for attribute on the skb
  * @skb: socket buffer to reserve room on
@@ -305,6 +306,7 @@
 
 	return nla;
 }
+EXPORT_SYMBOL(__nla_reserve);
 
 /**
  * __nla_reserve_nohdr - reserve room for attribute without header
@@ -325,6 +327,7 @@
 
 	return start;
 }
+EXPORT_SYMBOL(__nla_reserve_nohdr);
 
 /**
  * nla_reserve - reserve room for attribute on the skb
@@ -345,6 +348,7 @@
 
 	return __nla_reserve(skb, attrtype, attrlen);
 }
+EXPORT_SYMBOL(nla_reserve);
 
 /**
  * nla_reserve_nohdr - reserve room for attribute without header
@@ -363,6 +367,7 @@
 
 	return __nla_reserve_nohdr(skb, attrlen);
 }
+EXPORT_SYMBOL(nla_reserve_nohdr);
 
 /**
  * __nla_put - Add a netlink attribute to a socket buffer
@@ -382,6 +387,7 @@
 	nla = __nla_reserve(skb, attrtype, attrlen);
 	memcpy(nla_data(nla), data, attrlen);
 }
+EXPORT_SYMBOL(__nla_put);
 
 /**
  * __nla_put_nohdr - Add a netlink attribute without header
@@ -399,6 +405,7 @@
 	start = __nla_reserve_nohdr(skb, attrlen);
 	memcpy(start, data, attrlen);
 }
+EXPORT_SYMBOL(__nla_put_nohdr);
 
 /**
  * nla_put - Add a netlink attribute to a socket buffer
@@ -418,6 +425,7 @@
 	__nla_put(skb, attrtype, attrlen, data);
 	return 0;
 }
+EXPORT_SYMBOL(nla_put);
 
 /**
  * nla_put_nohdr - Add a netlink attribute without header
@@ -436,6 +444,7 @@
 	__nla_put_nohdr(skb, attrlen, data);
 	return 0;
 }
+EXPORT_SYMBOL(nla_put_nohdr);
 
 /**
  * nla_append - Add a netlink attribute without header or padding
@@ -454,20 +463,13 @@
 	memcpy(skb_put(skb, attrlen), data, attrlen);
 	return 0;
 }
+EXPORT_SYMBOL(nla_append);
+#endif
 
 EXPORT_SYMBOL(nla_validate);
 EXPORT_SYMBOL(nla_parse);
 EXPORT_SYMBOL(nla_find);
 EXPORT_SYMBOL(nla_strlcpy);
-EXPORT_SYMBOL(__nla_reserve);
-EXPORT_SYMBOL(__nla_reserve_nohdr);
-EXPORT_SYMBOL(nla_reserve);
-EXPORT_SYMBOL(nla_reserve_nohdr);
-EXPORT_SYMBOL(__nla_put);
-EXPORT_SYMBOL(__nla_put_nohdr);
-EXPORT_SYMBOL(nla_put);
-EXPORT_SYMBOL(nla_put_nohdr);
 EXPORT_SYMBOL(nla_memcpy);
 EXPORT_SYMBOL(nla_memcmp);
 EXPORT_SYMBOL(nla_strcmp);
-EXPORT_SYMBOL(nla_append);
diff --git a/mm/mmap.c b/mm/mmap.c
index 00ced3e..1abb918 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/hugetlb.h>
 #include <linux/profile.h>
 #include <linux/module.h>
@@ -1049,6 +1050,9 @@
 	error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
 	if (error)
 		return error;
+	error = ima_file_mmap(file, prot);
+	if (error)
+		return error;
 
 	return mmap_region(file, addr, len, flags, vm_flags, pgoff);
 }
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 74dc57c..40ca7cd 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -66,7 +66,7 @@
 /*
  * Start background writeback (via pdflush) at this percentage
  */
-int dirty_background_ratio = 5;
+int dirty_background_ratio = 10;
 
 /*
  * dirty_background_bytes starts at 0 (disabled) so that it is a function of
@@ -83,7 +83,7 @@
 /*
  * The generator of dirty data starts writeback at this percentage
  */
-int vm_dirty_ratio = 10;
+int vm_dirty_ratio = 20;
 
 /*
  * vm_dirty_bytes starts at 0 (disabled) so that it is a function of
diff --git a/mm/shmem.c b/mm/shmem.c
index 4103a23..7ec78e2 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -28,6 +28,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/swap.h>
+#include <linux/ima.h>
 
 static struct vfsmount *shm_mnt;
 
@@ -2665,6 +2666,7 @@
 	if (IS_ERR(file))
 		return PTR_ERR(file);
 
+	ima_shm_check(file);
 	if (vma->vm_file)
 		fput(vma->vm_file);
 	vma->vm_file = file;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 6177e3b..56ddf41 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1262,7 +1262,6 @@
 	 * Move the pages to the [file or anon] inactive list.
 	 */
 	pagevec_init(&pvec, 1);
-	pgmoved = 0;
 	lru = LRU_BASE + file * LRU_FILE;
 
 	spin_lock_irq(&zone->lru_lock);
@@ -1274,6 +1273,7 @@
 	 */
 	reclaim_stat->recent_rotated[!!file] += pgmoved;
 
+	pgmoved = 0;
 	while (!list_empty(&l_inactive)) {
 		page = lru_to_page(&l_inactive);
 		prefetchw_prev_lru_page(page, &l_inactive, flags);
@@ -1469,7 +1469,7 @@
 		int file = is_file_lru(l);
 		int scan;
 
-		scan = zone_page_state(zone, NR_LRU_BASE + l);
+		scan = zone_nr_pages(zone, sc, l);
 		if (priority) {
 			scan >>= priority;
 			scan = (scan * percent[file]) / 100;
diff --git a/net/Kconfig b/net/Kconfig
index 93998a9..ec93e7e 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -4,6 +4,7 @@
 
 menuconfig NET
 	bool "Networking support"
+	select NLATTR
 	---help---
 	  Unless you really know what you are doing, you should say Y here.
 	  The reason is that some programs need kernel networking support even
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 1a1f916..ed82796 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -140,7 +140,7 @@
 		dev = device_find_child(&conn->dev, NULL, __match_tty);
 		if (!dev)
 			break;
-		device_move(dev, NULL);
+		device_move(dev, NULL, DPM_ORDER_DEV_LAST);
 		put_device(dev);
 	}
 
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index d030c69..abdc703 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -731,7 +731,8 @@
 	remove_wait_queue(&dev->wait, &wait);
 
 	if (err == 0)
-		device_move(dev->tty_dev, rfcomm_get_device(dev));
+		device_move(dev->tty_dev, rfcomm_get_device(dev),
+			    DPM_ORDER_DEV_AFTER_PARENT);
 
 	rfcomm_tty_copy_pending(dev);
 
@@ -751,7 +752,7 @@
 
 	if (atomic_dec_and_test(&dev->opened)) {
 		if (dev->tty_dev->parent)
-			device_move(dev->tty_dev, NULL);
+			device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
 
 		/* Close DLC and dettach TTY */
 		rfcomm_dlc_close(dev->dlc, 0);
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 72cca63..3807ac7 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -66,7 +66,7 @@
 			     struct nf_conntrack_expect *exp) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn);
 
-#if defined(DEBUG) || defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
 /* PptpControlMessageType names */
 const char *const pptp_msg_name[] = {
 	"UNKNOWN_MESSAGE",
diff --git a/net/netlink/Makefile b/net/netlink/Makefile
index e3589c2..bdd6ddf 100644
--- a/net/netlink/Makefile
+++ b/net/netlink/Makefile
@@ -2,4 +2,4 @@
 # Makefile for the netlink driver.
 #
 
-obj-y  				:= af_netlink.o attr.o genetlink.o
+obj-y  				:= af_netlink.o genetlink.o
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 385f427..ff50a05 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -293,11 +293,6 @@
 	rpc_clear_queued(task);
 	if (rpc_test_and_set_running(task))
 		return;
-	/* We might have raced */
-	if (RPC_IS_QUEUED(task)) {
-		rpc_clear_running(task);
-		return;
-	}
 	if (RPC_IS_ASYNC(task)) {
 		int status;
 
@@ -607,7 +602,9 @@
  */
 static void __rpc_execute(struct rpc_task *task)
 {
-	int		status = 0;
+	struct rpc_wait_queue *queue;
+	int task_is_async = RPC_IS_ASYNC(task);
+	int status = 0;
 
 	dprintk("RPC: %5u __rpc_execute flags=0x%x\n",
 			task->tk_pid, task->tk_flags);
@@ -647,15 +644,25 @@
 		 */
 		if (!RPC_IS_QUEUED(task))
 			continue;
-		rpc_clear_running(task);
-		if (RPC_IS_ASYNC(task)) {
-			/* Careful! we may have raced... */
-			if (RPC_IS_QUEUED(task))
-				return;
-			if (rpc_test_and_set_running(task))
-				return;
+		/*
+		 * The queue->lock protects against races with
+		 * rpc_make_runnable().
+		 *
+		 * Note that once we clear RPC_TASK_RUNNING on an asynchronous
+		 * rpc_task, rpc_make_runnable() can assign it to a
+		 * different workqueue. We therefore cannot assume that the
+		 * rpc_task pointer may still be dereferenced.
+		 */
+		queue = task->tk_waitqueue;
+		spin_lock_bh(&queue->lock);
+		if (!RPC_IS_QUEUED(task)) {
+			spin_unlock_bh(&queue->lock);
 			continue;
 		}
+		rpc_clear_running(task);
+		spin_unlock_bh(&queue->lock);
+		if (task_is_async)
+			return;
 
 		/* sync task: sleep here */
 		dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 29e401b..62098d1 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -663,7 +663,7 @@
 			xprt, (xprt_connected(xprt) ? "is" : "is not"));
 
 	if (!xprt_bound(xprt)) {
-		task->tk_status = -EIO;
+		task->tk_status = -EAGAIN;
 		return;
 	}
 	if (!xprt_lock_write(xprt, task))
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index b49e434..568330e 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -467,7 +467,7 @@
 	int err, sent = 0;
 
 	if (unlikely(!sock))
-		return -ENOTCONN;
+		return -ENOTSOCK;
 
 	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
 	if (base != 0) {
@@ -577,6 +577,8 @@
 				req->rq_svec->iov_base,
 				req->rq_svec->iov_len);
 
+	if (!xprt_bound(xprt))
+		return -ENOTCONN;
 	status = xs_sendpages(transport->sock,
 			      xs_addr(xprt),
 			      xprt->addrlen, xdr,
@@ -594,6 +596,10 @@
 	}
 
 	switch (status) {
+	case -ENOTSOCK:
+		status = -ENOTCONN;
+		/* Should we call xs_close() here? */
+		break;
 	case -EAGAIN:
 		xs_nospace(task);
 		break;
@@ -693,6 +699,10 @@
 	}
 
 	switch (status) {
+	case -ENOTSOCK:
+		status = -ENOTCONN;
+		/* Should we call xs_close() here? */
+		break;
 	case -EAGAIN:
 		xs_nospace(task);
 		break;
@@ -1512,7 +1522,7 @@
 	struct socket *sock = transport->sock;
 	int err, status = -EIO;
 
-	if (xprt->shutdown || !xprt_bound(xprt))
+	if (xprt->shutdown)
 		goto out;
 
 	/* Start by resetting any existing state */
@@ -1553,7 +1563,7 @@
 	struct socket *sock = transport->sock;
 	int err, status = -EIO;
 
-	if (xprt->shutdown || !xprt_bound(xprt))
+	if (xprt->shutdown)
 		goto out;
 
 	/* Start by resetting any existing state */
@@ -1637,6 +1647,9 @@
 		write_unlock_bh(&sk->sk_callback_lock);
 	}
 
+	if (!xprt_bound(xprt))
+		return -ENOTCONN;
+
 	/* Tell the socket layer to start connecting... */
 	xprt->stat.connect_count++;
 	xprt->stat.connect_start = jiffies;
@@ -1657,7 +1670,7 @@
 	struct socket *sock = transport->sock;
 	int err, status = -EIO;
 
-	if (xprt->shutdown || !xprt_bound(xprt))
+	if (xprt->shutdown)
 		goto out;
 
 	if (!sock) {
@@ -1717,7 +1730,7 @@
 	struct socket *sock = transport->sock;
 	int err, status = -EIO;
 
-	if (xprt->shutdown || !xprt_bound(xprt))
+	if (xprt->shutdown)
 		goto out;
 
 	if (!sock) {
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index e0636577..c18fa15 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -97,7 +97,7 @@
                  -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
 
 #hash values
-ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
+ifdef CONFIG_DYNAMIC_DEBUG
 debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
               -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
 else
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 3e1057f..d190092 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -11,6 +11,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 
 #define LKC_DIRECT_LINK
 #include "lkc.h"
@@ -464,9 +465,22 @@
 			input_mode = set_yes;
 			break;
 		case 'r':
+		{
+			struct timeval now;
+			unsigned int seed;
+
+			/*
+			 * Use microseconds derived seed,
+			 * compensate for systems where it may be zero
+			 */
+			gettimeofday(&now, NULL);
+
+			seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
+			srand(seed);
+
 			input_mode = set_random;
-			srand(time(NULL));
 			break;
+		}
 		case 'h':
 			printf(_("See README for usage info\n"));
 			exit(0);
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 830d9ea..273d738 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -843,7 +843,7 @@
 			default:
 				continue;
 			}
-			if (!sym_is_choice(sym) || mode != def_random)
+			if (!(sym_is_choice(sym) && mode == def_random))
 				sym->flags |= SYMBOL_DEF_USER;
 			break;
 		default:
@@ -856,28 +856,49 @@
 
 	if (mode != def_random)
 		return;
-
+	/*
+	 * We have different type of choice blocks.
+	 * If curr.tri equal to mod then we can select several
+	 * choice symbols in one block.
+	 * In this case we do nothing.
+	 * If curr.tri equal yes then only one symbol can be
+	 * selected in a choice block and we set it to yes,
+	 * and the rest to no.
+	 */
 	for_all_symbols(i, csym) {
 		if (sym_has_value(csym) || !sym_is_choice(csym))
 			continue;
 
 		sym_calc_value(csym);
+
+		if (csym->curr.tri != yes)
+			continue;
+
 		prop = sym_get_choice_prop(csym);
-		def = -1;
-		while (1) {
-			cnt = 0;
-			expr_list_for_each_sym(prop->expr, e, sym) {
-				if (sym->visible == no)
-					continue;
-				if (def == cnt++) {
-					csym->def[S_DEF_USER].val = sym;
-					break;
-				}
+
+		/* count entries in choice block */
+		cnt = 0;
+		expr_list_for_each_sym(prop->expr, e, sym)
+			cnt++;
+
+		/*
+		 * find a random value and set it to yes,
+		 * set the rest to no so we have only one set
+		 */
+		def = (rand() % cnt);
+
+		cnt = 0;
+		expr_list_for_each_sym(prop->expr, e, sym) {
+			if (def == cnt++) {
+				sym->def[S_DEF_USER].tri = yes;
+				csym->def[S_DEF_USER].val = sym;
 			}
-			if (def >= 0 || cnt < 2)
-				break;
-			def = (rand() % cnt) + 1;
+			else {
+				sym->def[S_DEF_USER].tri = no;
+			}
 		}
 		csym->flags |= SYMBOL_DEF_USER;
+		/* clear VALID to get value calculated */
+		csym->flags &= ~(SYMBOL_VALID);
 	}
 }
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 4eea60b..a334428 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -710,6 +710,14 @@
 	strcat(alias, ":");
 	return 1;
 }
+
+static int do_platform_entry(const char *filename,
+			     struct platform_device_id *id, char *alias)
+{
+	sprintf(alias, PLATFORM_MODULE_PREFIX "%s", id->name);
+	return 1;
+}
+
 /* Ignore any prefix, eg. some architectures prepend _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -849,6 +857,10 @@
 		do_table(symval, sym->st_size,
 			 sizeof(struct dmi_system_id), "dmi",
 			 do_dmi_entry, mod);
+	else if (sym_is(symname, "__mod_platform_device_table"))
+		do_table(symval, sym->st_size,
+			 sizeof(struct platform_device_id), "platform",
+			 do_platform_entry, mod);
 	free(zeros);
 }
 
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index 8c6b7b0..fa4a0a1 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -35,9 +35,10 @@
 rpm-pkg rpm: $(objtree)/kernel.spec FORCE
 	$(MAKE) clean
 	$(PREV) ln -sf $(srctree) $(KERNELPATH)
+	$(CONFIG_SHELL) $(srctree)/scripts/setlocalversion > $(objtree)/.scmversion
 	$(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/.
 	$(PREV) rm $(KERNELPATH)
-
+	rm -f $(objtree)/.scmversion
 	set -e; \
 	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
 	set -e; \
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index ee448cd..3d93f8c 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -96,7 +96,7 @@
 
 echo ""
 echo "%clean"
-echo '#echo -rf $RPM_BUILD_ROOT'
+echo 'rm -rf $RPM_BUILD_ROOT'
 echo ""
 echo "%files"
 echo '%defattr (-, root, root)'
diff --git a/scripts/unifdef.c b/scripts/unifdef.c
index 552025e..05a31a6 100644
--- a/scripts/unifdef.c
+++ b/scripts/unifdef.c
@@ -206,7 +206,7 @@
 static void             error(const char *);
 static int              findsym(const char *);
 static void             flushline(bool);
-static Linetype         getline(void);
+static Linetype         get_line(void);
 static Linetype         ifeval(const char **);
 static void             ignoreoff(void);
 static void             ignoreon(void);
@@ -512,7 +512,7 @@
 
 	for (;;) {
 		linenum++;
-		lineval = getline();
+		lineval = get_line();
 		trans_table[ifstate[depth]][lineval]();
 		debug("process %s -> %s depth %d",
 		    linetype_name[lineval],
@@ -526,7 +526,7 @@
  * help from skipcomment().
  */
 static Linetype
-getline(void)
+get_line(void)
 {
 	const char *cp;
 	int cursym;
diff --git a/security/Kconfig b/security/Kconfig
index 9438535..bb24477 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -55,7 +55,8 @@
 	bool "Enable the securityfs filesystem"
 	help
 	  This will build the securityfs filesystem.  It is currently used by
-	  the TPM bios character driver.  It is not used by SELinux or SMACK.
+	  the TPM bios character driver and IMA, an integrity provider.  It is
+	  not used by SELinux or SMACK.
 
 	  If you are unsure how to answer this question, answer N.
 
@@ -134,6 +135,9 @@
 
 source security/selinux/Kconfig
 source security/smack/Kconfig
+source security/tomoyo/Kconfig
+
+source security/integrity/ima/Kconfig
 
 endmenu
 
diff --git a/security/Makefile b/security/Makefile
index c05c127..fa77021 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -5,6 +5,7 @@
 obj-$(CONFIG_KEYS)			+= keys/
 subdir-$(CONFIG_SECURITY_SELINUX)	+= selinux
 subdir-$(CONFIG_SECURITY_SMACK)		+= smack
+subdir-$(CONFIG_SECURITY_TOMOYO)        += tomoyo
 
 # always enable default capabilities
 obj-y		+= commoncap.o
@@ -15,5 +16,10 @@
 # Must precede capability.o in order to stack properly.
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_SMACK)		+= smack/built-in.o
+obj-$(CONFIG_SECURITY_TOMOYO)		+= tomoyo/built-in.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= root_plug.o
 obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
+
+# Object integrity file lists
+subdir-$(CONFIG_IMA)			+= integrity/ima
+obj-$(CONFIG_IMA)			+= integrity/ima/built-in.o
diff --git a/security/inode.c b/security/inode.c
index 007ef25..f3b91bf 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -202,12 +202,11 @@
  * This function returns a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the securityfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here).  If an error occurs, %NULL is returned.
+ * you are responsible here).  If an error occurs, the function will return
+ * the erorr value (via ERR_PTR).
  *
  * If securityfs is not enabled in the kernel, the value %-ENODEV is
- * returned.  It is not wise to check for this value, but rather, check for
- * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
- * code.
+ * returned.
  */
 struct dentry *securityfs_create_file(const char *name, mode_t mode,
 				   struct dentry *parent, void *data,
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
new file mode 100644
index 0000000..53d9764
--- /dev/null
+++ b/security/integrity/ima/Kconfig
@@ -0,0 +1,55 @@
+# IBM Integrity Measurement Architecture
+#
+config IMA
+	bool "Integrity Measurement Architecture(IMA)"
+	depends on ACPI
+	select SECURITYFS
+	select CRYPTO
+	select CRYPTO_HMAC
+	select CRYPTO_MD5
+	select CRYPTO_SHA1
+	select TCG_TPM
+	select TCG_TIS
+	help
+	  The Trusted Computing Group(TCG) runtime Integrity
+	  Measurement Architecture(IMA) maintains a list of hash
+	  values of executables and other sensitive system files,
+	  as they are read or executed. If an attacker manages
+	  to change the contents of an important system file
+	  being measured, we can tell.
+
+	  If your system has a TPM chip, then IMA also maintains
+	  an aggregate integrity value over this list inside the
+	  TPM hardware, so that the TPM can prove to a third party
+	  whether or not critical system files have been modified.
+	  Read <http://www.usenix.org/events/sec04/tech/sailer.html>
+	  to learn more about IMA.
+	  If unsure, say N.
+
+config IMA_MEASURE_PCR_IDX
+	int
+	depends on IMA
+	range 8 14
+	default 10
+	help
+	  IMA_MEASURE_PCR_IDX determines the TPM PCR register index
+	  that IMA uses to maintain the integrity aggregate of the
+	  measurement list.  If unsure, use the default 10.
+
+config IMA_AUDIT
+	bool
+	depends on IMA
+	default y
+	help
+	  This option adds a kernel parameter 'ima_audit', which
+	  allows informational auditing messages to be enabled
+	  at boot.  If this option is selected, informational integrity
+	  auditing messages can be enabled with 'ima_audit=1' on
+	  the kernel command line.
+
+config IMA_LSM_RULES
+	bool
+	depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK)
+	default y
+	help
+	  Disabling this option will disregard LSM based policy rules.
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
new file mode 100644
index 0000000..787c4cb
--- /dev/null
+++ b/security/integrity/ima/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for building Trusted Computing Group's(TCG) runtime Integrity
+# Measurement Architecture(IMA).
+#
+
+obj-$(CONFIG_IMA) += ima.o
+
+ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
+	 ima_policy.o ima_iint.o ima_audit.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
new file mode 100644
index 0000000..165eb53
--- /dev/null
+++ b/security/integrity/ima/ima.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima.h
+ *	internal Integrity Measurement Architecture (IMA) definitions
+ */
+
+#ifndef __LINUX_IMA_H
+#define __LINUX_IMA_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/security.h>
+#include <linux/hash.h>
+#include <linux/tpm.h>
+#include <linux/audit.h>
+
+enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII };
+enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
+
+/* digest size for IMA, fits SHA1 or MD5 */
+#define IMA_DIGEST_SIZE		20
+#define IMA_EVENT_NAME_LEN_MAX	255
+
+#define IMA_HASH_BITS 9
+#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)
+
+/* set during initialization */
+extern int ima_initialized;
+extern int ima_used_chip;
+extern char *ima_hash;
+
+/* IMA inode template definition */
+struct ima_template_data {
+	u8 digest[IMA_DIGEST_SIZE];	/* sha1/md5 measurement hash */
+	char file_name[IMA_EVENT_NAME_LEN_MAX + 1];	/* name + \0 */
+};
+
+struct ima_template_entry {
+	u8 digest[IMA_DIGEST_SIZE];	/* sha1 or md5 measurement hash */
+	const char *template_name;
+	int template_len;
+	struct ima_template_data template;
+};
+
+struct ima_queue_entry {
+	struct hlist_node hnext;	/* place in hash collision list */
+	struct list_head later;		/* place in ima_measurements list */
+	struct ima_template_entry *entry;
+};
+extern struct list_head ima_measurements;	/* list of all measurements */
+
+/* declarations */
+void integrity_audit_msg(int audit_msgno, struct inode *inode,
+			 const unsigned char *fname, const char *op,
+			 const char *cause, int result, int info);
+
+/* Internal IMA function definitions */
+void ima_iintcache_init(void);
+int ima_init(void);
+void ima_cleanup(void);
+int ima_fs_init(void);
+void ima_fs_cleanup(void);
+int ima_add_template_entry(struct ima_template_entry *entry, int violation,
+			   const char *op, struct inode *inode);
+int ima_calc_hash(struct file *file, char *digest);
+int ima_calc_template_hash(int template_len, void *template, char *digest);
+int ima_calc_boot_aggregate(char *digest);
+void ima_add_violation(struct inode *inode, const unsigned char *filename,
+		       const char *op, const char *cause);
+
+/*
+ * used to protect h_table and sha_table
+ */
+extern spinlock_t ima_queue_lock;
+
+struct ima_h_table {
+	atomic_long_t len;	/* number of stored measurements in the list */
+	atomic_long_t violations;
+	struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE];
+};
+extern struct ima_h_table ima_htable;
+
+static inline unsigned long ima_hash_key(u8 *digest)
+{
+	return hash_long(*digest, IMA_HASH_BITS);
+}
+
+/* iint cache flags */
+#define IMA_MEASURED		1
+#define IMA_IINT_DUMP_STACK	512
+
+/* integrity data associated with an inode */
+struct ima_iint_cache {
+	u64 version;		/* track inode changes */
+	unsigned long flags;
+	u8 digest[IMA_DIGEST_SIZE];
+	struct mutex mutex;	/* protects: version, flags, digest */
+	long readcount;		/* measured files readcount */
+	long writecount;	/* measured files writecount */
+	long opencount;		/* opens reference count */
+	struct kref refcount;	/* ima_iint_cache reference count */
+	struct rcu_head rcu;
+};
+
+/* LIM API function definitions */
+int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
+		     int mask, int function);
+int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file);
+void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
+			   const unsigned char *filename);
+int ima_store_template(struct ima_template_entry *entry, int violation,
+		       struct inode *inode);
+void ima_template_show(struct seq_file *m, void *e,
+		       enum ima_show_type show);
+
+/* radix tree calls to lookup, insert, delete
+ * integrity data associated with an inode.
+ */
+struct ima_iint_cache *ima_iint_insert(struct inode *inode);
+struct ima_iint_cache *ima_iint_find_get(struct inode *inode);
+struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode);
+void ima_iint_delete(struct inode *inode);
+void iint_free(struct kref *kref);
+void iint_rcu_free(struct rcu_head *rcu);
+
+/* IMA policy related functions */
+enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK };
+
+int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask);
+void ima_init_policy(void);
+void ima_update_policy(void);
+int ima_parse_add_rule(char *);
+void ima_delete_rules(void);
+
+/* LSM based policy rules require audit */
+#ifdef CONFIG_IMA_LSM_RULES
+
+#define security_filter_rule_init security_audit_rule_init
+#define security_filter_rule_match security_audit_rule_match
+
+#else
+
+static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr,
+					    void **lsmrule)
+{
+	return -EINVAL;
+}
+
+static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
+					     void *lsmrule,
+					     struct audit_context *actx)
+{
+	return -EINVAL;
+}
+#endif /* CONFIG_IMA_LSM_RULES */
+#endif
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
new file mode 100644
index 0000000..3cd58b6
--- /dev/null
+++ b/security/integrity/ima/ima_api.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ *
+ * Author: Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_api.c
+ *	Implements must_measure, collect_measurement, store_measurement,
+ *	and store_template.
+ */
+#include <linux/module.h>
+
+#include "ima.h"
+static const char *IMA_TEMPLATE_NAME = "ima";
+
+/*
+ * ima_store_template - store ima template measurements
+ *
+ * Calculate the hash of a template entry, add the template entry
+ * to an ordered list of measurement entries maintained inside the kernel,
+ * and also update the aggregate integrity value (maintained inside the
+ * configured TPM PCR) over the hashes of the current list of measurement
+ * entries.
+ *
+ * Applications retrieve the current kernel-held measurement list through
+ * the securityfs entries in /sys/kernel/security/ima. The signed aggregate
+ * TPM PCR (called quote) can be retrieved using a TPM user space library
+ * and is used to validate the measurement list.
+ *
+ * Returns 0 on success, error code otherwise
+ */
+int ima_store_template(struct ima_template_entry *entry,
+		       int violation, struct inode *inode)
+{
+	const char *op = "add_template_measure";
+	const char *audit_cause = "hashing_error";
+	int result;
+
+	memset(entry->digest, 0, sizeof(entry->digest));
+	entry->template_name = IMA_TEMPLATE_NAME;
+	entry->template_len = sizeof(entry->template);
+
+	if (!violation) {
+		result = ima_calc_template_hash(entry->template_len,
+						&entry->template,
+						entry->digest);
+		if (result < 0) {
+			integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
+					    entry->template_name, op,
+					    audit_cause, result, 0);
+			return result;
+		}
+	}
+	result = ima_add_template_entry(entry, violation, op, inode);
+	return result;
+}
+
+/*
+ * ima_add_violation - add violation to measurement list.
+ *
+ * Violations are flagged in the measurement list with zero hash values.
+ * By extending the PCR with 0xFF's instead of with zeroes, the PCR
+ * value is invalidated.
+ */
+void ima_add_violation(struct inode *inode, const unsigned char *filename,
+		       const char *op, const char *cause)
+{
+	struct ima_template_entry *entry;
+	int violation = 1;
+	int result;
+
+	/* can overflow, only indicator */
+	atomic_long_inc(&ima_htable.violations);
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		result = -ENOMEM;
+		goto err_out;
+	}
+	memset(&entry->template, 0, sizeof(entry->template));
+	strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
+	result = ima_store_template(entry, violation, inode);
+	if (result < 0)
+		kfree(entry);
+err_out:
+	integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
+			    op, cause, result, 0);
+}
+
+/**
+ * ima_must_measure - measure decision based on policy.
+ * @inode: pointer to inode to measure
+ * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
+ * @function: calling function (PATH_CHECK, BPRM_CHECK, FILE_MMAP)
+ *
+ * The policy is defined in terms of keypairs:
+ * 		subj=, obj=, type=, func=, mask=, fsmagic=
+ *	subj,obj, and type: are LSM specific.
+ * 	func: PATH_CHECK | BPRM_CHECK | FILE_MMAP
+ * 	mask: contains the permission mask
+ *	fsmagic: hex value
+ *
+ * Must be called with iint->mutex held.
+ *
+ * Return 0 to measure. Return 1 if already measured.
+ * For matching a DONT_MEASURE policy, no policy, or other
+ * error, return an error code.
+*/
+int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
+		     int mask, int function)
+{
+	int must_measure;
+
+	if (iint->flags & IMA_MEASURED)
+		return 1;
+
+	must_measure = ima_match_policy(inode, function, mask);
+	return must_measure ? 0 : -EACCES;
+}
+
+/*
+ * ima_collect_measurement - collect file measurement
+ *
+ * Calculate the file hash, if it doesn't already exist,
+ * storing the measurement and i_version in the iint.
+ *
+ * Must be called with iint->mutex held.
+ *
+ * Return 0 on success, error code otherwise
+ */
+int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file)
+{
+	int result = -EEXIST;
+
+	if (!(iint->flags & IMA_MEASURED)) {
+		u64 i_version = file->f_dentry->d_inode->i_version;
+
+		memset(iint->digest, 0, IMA_DIGEST_SIZE);
+		result = ima_calc_hash(file, iint->digest);
+		if (!result)
+			iint->version = i_version;
+	}
+	return result;
+}
+
+/*
+ * ima_store_measurement - store file measurement
+ *
+ * Create an "ima" template and then store the template by calling
+ * ima_store_template.
+ *
+ * We only get here if the inode has not already been measured,
+ * but the measurement could already exist:
+ * 	- multiple copies of the same file on either the same or
+ *	  different filesystems.
+ *	- the inode was previously flushed as well as the iint info,
+ *	  containing the hashing info.
+ *
+ * Must be called with iint->mutex held.
+ */
+void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
+			   const unsigned char *filename)
+{
+	const char *op = "add_template_measure";
+	const char *audit_cause = "ENOMEM";
+	int result = -ENOMEM;
+	struct inode *inode = file->f_dentry->d_inode;
+	struct ima_template_entry *entry;
+	int violation = 0;
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
+				    op, audit_cause, result, 0);
+		return;
+	}
+	memset(&entry->template, 0, sizeof(entry->template));
+	memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE);
+	strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
+
+	result = ima_store_template(entry, violation, inode);
+	if (!result)
+		iint->flags |= IMA_MEASURED;
+	else
+		kfree(entry);
+}
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
new file mode 100644
index 0000000..1e082bb
--- /dev/null
+++ b/security/integrity/ima/ima_audit.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ * Author: Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * File: integrity_audit.c
+ * 	Audit calls for the integrity subsystem
+ */
+
+#include <linux/fs.h>
+#include <linux/audit.h>
+#include "ima.h"
+
+static int ima_audit;
+
+#ifdef CONFIG_IMA_AUDIT
+
+/* ima_audit_setup - enable informational auditing messages */
+static int __init ima_audit_setup(char *str)
+{
+	unsigned long audit;
+	int rc, result = 0;
+	char *op = "ima_audit";
+	char *cause;
+
+	rc = strict_strtoul(str, 0, &audit);
+	if (rc || audit > 1)
+		result = 1;
+	else
+		ima_audit = audit;
+	cause = ima_audit ? "enabled" : "not_enabled";
+	integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
+			    op, cause, result, 0);
+	return 1;
+}
+__setup("ima_audit=", ima_audit_setup);
+#endif
+
+void integrity_audit_msg(int audit_msgno, struct inode *inode,
+			 const unsigned char *fname, const char *op,
+			 const char *cause, int result, int audit_info)
+{
+	struct audit_buffer *ab;
+
+	if (!ima_audit && audit_info == 1) /* Skip informational messages */
+		return;
+
+	ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
+	audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u ses=%u",
+			 current->pid, current->cred->uid,
+			 audit_get_loginuid(current),
+			 audit_get_sessionid(current));
+	audit_log_task_context(ab);
+	switch (audit_msgno) {
+	case AUDIT_INTEGRITY_DATA:
+	case AUDIT_INTEGRITY_METADATA:
+	case AUDIT_INTEGRITY_PCR:
+	case AUDIT_INTEGRITY_STATUS:
+		audit_log_format(ab, " op=%s cause=%s", op, cause);
+		break;
+	case AUDIT_INTEGRITY_HASH:
+		audit_log_format(ab, " op=%s hash=%s", op, cause);
+		break;
+	default:
+		audit_log_format(ab, " op=%s", op);
+	}
+	audit_log_format(ab, " comm=");
+	audit_log_untrustedstring(ab, current->comm);
+	if (fname) {
+		audit_log_format(ab, " name=");
+		audit_log_untrustedstring(ab, fname);
+	}
+	if (inode)
+		audit_log_format(ab, " dev=%s ino=%lu",
+				 inode->i_sb->s_id, inode->i_ino);
+	audit_log_format(ab, " res=%d", !result ? 0 : 1);
+	audit_log_end(ab);
+}
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
new file mode 100644
index 0000000..50d572b
--- /dev/null
+++ b/security/integrity/ima/ima_crypto.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Mimi Zohar <zohar@us.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * File: ima_crypto.c
+ * 	Calculates md5/sha1 file hash, template hash, boot-aggreate hash
+ */
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/err.h>
+#include "ima.h"
+
+static int init_desc(struct hash_desc *desc)
+{
+	int rc;
+
+	desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(desc->tfm)) {
+		pr_info("failed to load %s transform: %ld\n",
+			ima_hash, PTR_ERR(desc->tfm));
+		rc = PTR_ERR(desc->tfm);
+		return rc;
+	}
+	desc->flags = 0;
+	rc = crypto_hash_init(desc);
+	if (rc)
+		crypto_free_hash(desc->tfm);
+	return rc;
+}
+
+/*
+ * Calculate the MD5/SHA1 file digest
+ */
+int ima_calc_hash(struct file *file, char *digest)
+{
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	loff_t i_size;
+	char *rbuf;
+	int rc, offset = 0;
+
+	rc = init_desc(&desc);
+	if (rc != 0)
+		return rc;
+
+	rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!rbuf) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	i_size = i_size_read(file->f_dentry->d_inode);
+	while (offset < i_size) {
+		int rbuf_len;
+
+		rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE);
+		if (rbuf_len < 0) {
+			rc = rbuf_len;
+			break;
+		}
+		offset += rbuf_len;
+		sg_init_one(sg, rbuf, rbuf_len);
+
+		rc = crypto_hash_update(&desc, sg, rbuf_len);
+		if (rc)
+			break;
+	}
+	kfree(rbuf);
+	if (!rc)
+		rc = crypto_hash_final(&desc, digest);
+out:
+	crypto_free_hash(desc.tfm);
+	return rc;
+}
+
+/*
+ * Calculate the hash of a given template
+ */
+int ima_calc_template_hash(int template_len, void *template, char *digest)
+{
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	int rc;
+
+	rc = init_desc(&desc);
+	if (rc != 0)
+		return rc;
+
+	sg_init_one(sg, template, template_len);
+	rc = crypto_hash_update(&desc, sg, template_len);
+	if (!rc)
+		rc = crypto_hash_final(&desc, digest);
+	crypto_free_hash(desc.tfm);
+	return rc;
+}
+
+static void ima_pcrread(int idx, u8 *pcr)
+{
+	if (!ima_used_chip)
+		return;
+
+	if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
+		pr_err("Error Communicating to TPM chip\n");
+}
+
+/*
+ * Calculate the boot aggregate hash
+ */
+int ima_calc_boot_aggregate(char *digest)
+{
+	struct hash_desc desc;
+	struct scatterlist sg;
+	u8 pcr_i[IMA_DIGEST_SIZE];
+	int rc, i;
+
+	rc = init_desc(&desc);
+	if (rc != 0)
+		return rc;
+
+	/* cumulative sha1 over tpm registers 0-7 */
+	for (i = TPM_PCR0; i < TPM_PCR8; i++) {
+		ima_pcrread(i, pcr_i);
+		/* now accumulate with current aggregate */
+		sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE);
+		rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE);
+	}
+	if (!rc)
+		crypto_hash_final(&desc, digest);
+	crypto_free_hash(desc.tfm);
+	return rc;
+}
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
new file mode 100644
index 0000000..ffbe259
--- /dev/null
+++ b/security/integrity/ima/ima_fs.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Kylene Hall <kjhall@us.ibm.com>
+ * Reiner Sailer <sailer@us.ibm.com>
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_fs.c
+ *	implemenents security file system for reporting
+ *	current measurement list and IMA statistics
+ */
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+#include <linux/parser.h>
+
+#include "ima.h"
+
+static int valid_policy = 1;
+#define TMPBUFLEN 12
+static ssize_t ima_show_htable_value(char __user *buf, size_t count,
+				     loff_t *ppos, atomic_long_t *val)
+{
+	char tmpbuf[TMPBUFLEN];
+	ssize_t len;
+
+	len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val));
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
+}
+
+static ssize_t ima_show_htable_violations(struct file *filp,
+					  char __user *buf,
+					  size_t count, loff_t *ppos)
+{
+	return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
+}
+
+static struct file_operations ima_htable_violations_ops = {
+	.read = ima_show_htable_violations
+};
+
+static ssize_t ima_show_measurements_count(struct file *filp,
+					   char __user *buf,
+					   size_t count, loff_t *ppos)
+{
+	return ima_show_htable_value(buf, count, ppos, &ima_htable.len);
+
+}
+
+static struct file_operations ima_measurements_count_ops = {
+	.read = ima_show_measurements_count
+};
+
+/* returns pointer to hlist_node */
+static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
+{
+	loff_t l = *pos;
+	struct ima_queue_entry *qe;
+
+	/* we need a lock since pos could point beyond last element */
+	rcu_read_lock();
+	list_for_each_entry_rcu(qe, &ima_measurements, later) {
+		if (!l--) {
+			rcu_read_unlock();
+			return qe;
+		}
+	}
+	rcu_read_unlock();
+	return NULL;
+}
+
+static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct ima_queue_entry *qe = v;
+
+	/* lock protects when reading beyond last element
+	 * against concurrent list-extension
+	 */
+	rcu_read_lock();
+	qe = list_entry(rcu_dereference(qe->later.next),
+			struct ima_queue_entry, later);
+	rcu_read_unlock();
+	(*pos)++;
+
+	return (&qe->later == &ima_measurements) ? NULL : qe;
+}
+
+static void ima_measurements_stop(struct seq_file *m, void *v)
+{
+}
+
+static void ima_putc(struct seq_file *m, void *data, int datalen)
+{
+	while (datalen--)
+		seq_putc(m, *(char *)data++);
+}
+
+/* print format:
+ *       32bit-le=pcr#
+ *       char[20]=template digest
+ *       32bit-le=template name size
+ *       char[n]=template name
+ *       eventdata[n]=template specific data
+ */
+static int ima_measurements_show(struct seq_file *m, void *v)
+{
+	/* the list never shrinks, so we don't need a lock here */
+	struct ima_queue_entry *qe = v;
+	struct ima_template_entry *e;
+	int namelen;
+	u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+
+	/* get entry */
+	e = qe->entry;
+	if (e == NULL)
+		return -1;
+
+	/*
+	 * 1st: PCRIndex
+	 * PCR used is always the same (config option) in
+	 * little-endian format
+	 */
+	ima_putc(m, &pcr, sizeof pcr);
+
+	/* 2nd: template digest */
+	ima_putc(m, e->digest, IMA_DIGEST_SIZE);
+
+	/* 3rd: template name size */
+	namelen = strlen(e->template_name);
+	ima_putc(m, &namelen, sizeof namelen);
+
+	/* 4th:  template name */
+	ima_putc(m, (void *)e->template_name, namelen);
+
+	/* 5th:  template specific data */
+	ima_template_show(m, (struct ima_template_data *)&e->template,
+			  IMA_SHOW_BINARY);
+	return 0;
+}
+
+static struct seq_operations ima_measurments_seqops = {
+	.start = ima_measurements_start,
+	.next = ima_measurements_next,
+	.stop = ima_measurements_stop,
+	.show = ima_measurements_show
+};
+
+static int ima_measurements_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ima_measurments_seqops);
+}
+
+static struct file_operations ima_measurements_ops = {
+	.open = ima_measurements_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static void ima_print_digest(struct seq_file *m, u8 *digest)
+{
+	int i;
+
+	for (i = 0; i < IMA_DIGEST_SIZE; i++)
+		seq_printf(m, "%02x", *(digest + i));
+}
+
+void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
+{
+	struct ima_template_data *entry = e;
+	int namelen;
+
+	switch (show) {
+	case IMA_SHOW_ASCII:
+		ima_print_digest(m, entry->digest);
+		seq_printf(m, " %s\n", entry->file_name);
+		break;
+	case IMA_SHOW_BINARY:
+		ima_putc(m, entry->digest, IMA_DIGEST_SIZE);
+
+		namelen = strlen(entry->file_name);
+		ima_putc(m, &namelen, sizeof namelen);
+		ima_putc(m, entry->file_name, namelen);
+	default:
+		break;
+	}
+}
+
+/* print in ascii */
+static int ima_ascii_measurements_show(struct seq_file *m, void *v)
+{
+	/* the list never shrinks, so we don't need a lock here */
+	struct ima_queue_entry *qe = v;
+	struct ima_template_entry *e;
+
+	/* get entry */
+	e = qe->entry;
+	if (e == NULL)
+		return -1;
+
+	/* 1st: PCR used (config option) */
+	seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX);
+
+	/* 2nd: SHA1 template hash */
+	ima_print_digest(m, e->digest);
+
+	/* 3th:  template name */
+	seq_printf(m, " %s ", e->template_name);
+
+	/* 4th:  template specific data */
+	ima_template_show(m, (struct ima_template_data *)&e->template,
+			  IMA_SHOW_ASCII);
+	return 0;
+}
+
+static struct seq_operations ima_ascii_measurements_seqops = {
+	.start = ima_measurements_start,
+	.next = ima_measurements_next,
+	.stop = ima_measurements_stop,
+	.show = ima_ascii_measurements_show
+};
+
+static int ima_ascii_measurements_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ima_ascii_measurements_seqops);
+}
+
+static struct file_operations ima_ascii_measurements_ops = {
+	.open = ima_ascii_measurements_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static ssize_t ima_write_policy(struct file *file, const char __user *buf,
+				size_t datalen, loff_t *ppos)
+{
+	char *data;
+	int rc;
+
+	if (datalen >= PAGE_SIZE)
+		return -ENOMEM;
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+	data = kmalloc(datalen + 1, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	if (copy_from_user(data, buf, datalen)) {
+		kfree(data);
+		return -EFAULT;
+	}
+	*(data + datalen) = '\0';
+	rc = ima_parse_add_rule(data);
+	if (rc < 0) {
+		datalen = -EINVAL;
+		valid_policy = 0;
+	}
+
+	kfree(data);
+	return datalen;
+}
+
+static struct dentry *ima_dir;
+static struct dentry *binary_runtime_measurements;
+static struct dentry *ascii_runtime_measurements;
+static struct dentry *runtime_measurements_count;
+static struct dentry *violations;
+static struct dentry *ima_policy;
+
+static atomic_t policy_opencount = ATOMIC_INIT(1);
+/*
+ * ima_open_policy: sequentialize access to the policy file
+ */
+int ima_open_policy(struct inode * inode, struct file * filp)
+{
+	if (atomic_dec_and_test(&policy_opencount))
+		return 0;
+	return -EBUSY;
+}
+
+/*
+ * ima_release_policy - start using the new measure policy rules.
+ *
+ * Initially, ima_measure points to the default policy rules, now
+ * point to the new policy rules, and remove the securityfs policy file,
+ * assuming a valid policy.
+ */
+static int ima_release_policy(struct inode *inode, struct file *file)
+{
+	if (!valid_policy) {
+		ima_delete_rules();
+		valid_policy = 1;
+		atomic_set(&policy_opencount, 1);
+		return 0;
+	}
+	ima_update_policy();
+	securityfs_remove(ima_policy);
+	ima_policy = NULL;
+	return 0;
+}
+
+static struct file_operations ima_measure_policy_ops = {
+	.open = ima_open_policy,
+	.write = ima_write_policy,
+	.release = ima_release_policy
+};
+
+int ima_fs_init(void)
+{
+	ima_dir = securityfs_create_dir("ima", NULL);
+	if (IS_ERR(ima_dir))
+		return -1;
+
+	binary_runtime_measurements =
+	    securityfs_create_file("binary_runtime_measurements",
+				   S_IRUSR | S_IRGRP, ima_dir, NULL,
+				   &ima_measurements_ops);
+	if (IS_ERR(binary_runtime_measurements))
+		goto out;
+
+	ascii_runtime_measurements =
+	    securityfs_create_file("ascii_runtime_measurements",
+				   S_IRUSR | S_IRGRP, ima_dir, NULL,
+				   &ima_ascii_measurements_ops);
+	if (IS_ERR(ascii_runtime_measurements))
+		goto out;
+
+	runtime_measurements_count =
+	    securityfs_create_file("runtime_measurements_count",
+				   S_IRUSR | S_IRGRP, ima_dir, NULL,
+				   &ima_measurements_count_ops);
+	if (IS_ERR(runtime_measurements_count))
+		goto out;
+
+	violations =
+	    securityfs_create_file("violations", S_IRUSR | S_IRGRP,
+				   ima_dir, NULL, &ima_htable_violations_ops);
+	if (IS_ERR(violations))
+		goto out;
+
+	ima_policy = securityfs_create_file("policy",
+					    S_IRUSR | S_IRGRP | S_IWUSR,
+					    ima_dir, NULL,
+					    &ima_measure_policy_ops);
+	if (IS_ERR(ima_policy))
+		goto out;
+
+	return 0;
+out:
+	securityfs_remove(runtime_measurements_count);
+	securityfs_remove(ascii_runtime_measurements);
+	securityfs_remove(binary_runtime_measurements);
+	securityfs_remove(ima_dir);
+	securityfs_remove(ima_policy);
+	return -1;
+}
+
+void __exit ima_fs_cleanup(void)
+{
+	securityfs_remove(violations);
+	securityfs_remove(runtime_measurements_count);
+	securityfs_remove(ascii_runtime_measurements);
+	securityfs_remove(binary_runtime_measurements);
+	securityfs_remove(ima_dir);
+	securityfs_remove(ima_policy);
+}
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
new file mode 100644
index 0000000..ec79f1e
--- /dev/null
+++ b/security/integrity/ima/ima_iint.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ *
+ * Authors:
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_iint.c
+ * 	- implements the IMA hooks: ima_inode_alloc, ima_inode_free
+ *	- cache integrity information associated with an inode
+ *	  using a radix tree.
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/radix-tree.h>
+#include "ima.h"
+
+#define ima_iint_delete ima_inode_free
+
+RADIX_TREE(ima_iint_store, GFP_ATOMIC);
+DEFINE_SPINLOCK(ima_iint_lock);
+
+static struct kmem_cache *iint_cache __read_mostly;
+
+/* ima_iint_find_get - return the iint associated with an inode
+ *
+ * ima_iint_find_get gets a reference to the iint. Caller must
+ * remember to put the iint reference.
+ */
+struct ima_iint_cache *ima_iint_find_get(struct inode *inode)
+{
+	struct ima_iint_cache *iint;
+
+	rcu_read_lock();
+	iint = radix_tree_lookup(&ima_iint_store, (unsigned long)inode);
+	if (!iint)
+		goto out;
+	kref_get(&iint->refcount);
+out:
+	rcu_read_unlock();
+	return iint;
+}
+
+/* Allocate memory for the iint associated with the inode
+ * from the iint_cache slab, initialize the iint, and
+ * insert it into the radix tree.
+ *
+ * On success return a pointer to the iint; on failure return NULL.
+ */
+struct ima_iint_cache *ima_iint_insert(struct inode *inode)
+{
+	struct ima_iint_cache *iint = NULL;
+	int rc = 0;
+
+	if (!ima_initialized)
+		return iint;
+	iint = kmem_cache_alloc(iint_cache, GFP_KERNEL);
+	if (!iint)
+		return iint;
+
+	rc = radix_tree_preload(GFP_KERNEL);
+	if (rc < 0)
+		goto out;
+
+	spin_lock(&ima_iint_lock);
+	rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
+	spin_unlock(&ima_iint_lock);
+out:
+	if (rc < 0) {
+		kmem_cache_free(iint_cache, iint);
+		if (rc == -EEXIST) {
+			spin_lock(&ima_iint_lock);
+			iint = radix_tree_lookup(&ima_iint_store,
+						 (unsigned long)inode);
+			spin_unlock(&ima_iint_lock);
+		} else
+			iint = NULL;
+	}
+	radix_tree_preload_end();
+	return iint;
+}
+
+/**
+ * ima_inode_alloc - allocate an iint associated with an inode
+ * @inode: pointer to the inode
+ *
+ * Return 0 on success, 1 on failure.
+ */
+int ima_inode_alloc(struct inode *inode)
+{
+	struct ima_iint_cache *iint;
+
+	if (!ima_initialized)
+		return 0;
+
+	iint = ima_iint_insert(inode);
+	if (!iint)
+		return 1;
+	return 0;
+}
+
+/* ima_iint_find_insert_get - get the iint associated with an inode
+ *
+ * Most insertions are done at inode_alloc, except those allocated
+ * before late_initcall. When the iint does not exist, allocate it,
+ * initialize and insert it, and increment the iint refcount.
+ *
+ * (Can't initialize at security_initcall before any inodes are
+ * allocated, got to wait at least until proc_init.)
+ *
+ *  Return the iint.
+ */
+struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
+{
+	struct ima_iint_cache *iint = NULL;
+
+	iint = ima_iint_find_get(inode);
+	if (iint)
+		return iint;
+
+	iint = ima_iint_insert(inode);
+	if (iint)
+		kref_get(&iint->refcount);
+
+	return iint;
+}
+EXPORT_SYMBOL_GPL(ima_iint_find_insert_get);
+
+/* iint_free - called when the iint refcount goes to zero */
+void iint_free(struct kref *kref)
+{
+	struct ima_iint_cache *iint = container_of(kref, struct ima_iint_cache,
+						   refcount);
+	iint->version = 0;
+	iint->flags = 0UL;
+	if (iint->readcount != 0) {
+		printk(KERN_INFO "%s: readcount: %ld\n", __FUNCTION__,
+		       iint->readcount);
+		iint->readcount = 0;
+	}
+	if (iint->writecount != 0) {
+		printk(KERN_INFO "%s: writecount: %ld\n", __FUNCTION__,
+		       iint->writecount);
+		iint->writecount = 0;
+	}
+	if (iint->opencount != 0) {
+		printk(KERN_INFO "%s: opencount: %ld\n", __FUNCTION__,
+		       iint->opencount);
+		iint->opencount = 0;
+	}
+	kref_set(&iint->refcount, 1);
+	kmem_cache_free(iint_cache, iint);
+}
+
+void iint_rcu_free(struct rcu_head *rcu_head)
+{
+	struct ima_iint_cache *iint = container_of(rcu_head,
+						   struct ima_iint_cache, rcu);
+	kref_put(&iint->refcount, iint_free);
+}
+
+/**
+ * ima_iint_delete - called on integrity_inode_free
+ * @inode: pointer to the inode
+ *
+ * Free the integrity information(iint) associated with an inode.
+ */
+void ima_iint_delete(struct inode *inode)
+{
+	struct ima_iint_cache *iint;
+
+	if (!ima_initialized)
+		return;
+	spin_lock(&ima_iint_lock);
+	iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
+	spin_unlock(&ima_iint_lock);
+	if (iint)
+		call_rcu(&iint->rcu, iint_rcu_free);
+}
+
+static void init_once(void *foo)
+{
+	struct ima_iint_cache *iint = foo;
+
+	memset(iint, 0, sizeof *iint);
+	iint->version = 0;
+	iint->flags = 0UL;
+	mutex_init(&iint->mutex);
+	iint->readcount = 0;
+	iint->writecount = 0;
+	iint->opencount = 0;
+	kref_set(&iint->refcount, 1);
+}
+
+void ima_iintcache_init(void)
+{
+	iint_cache =
+	    kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
+			      SLAB_PANIC, init_once);
+}
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
new file mode 100644
index 0000000..0b0bb8c
--- /dev/null
+++ b/security/integrity/ima/ima_init.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer      <sailer@watson.ibm.com>
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Mimi Zohar         <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_init.c
+ *             initialization and cleanup functions
+ */
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/err.h>
+#include "ima.h"
+
+/* name for boot aggregate entry */
+static const char *boot_aggregate_name = "boot_aggregate";
+int ima_used_chip;
+
+/* Add the boot aggregate to the IMA measurement list and extend
+ * the PCR register.
+ *
+ * Calculate the boot aggregate, a SHA1 over tpm registers 0-7,
+ * assuming a TPM chip exists, and zeroes if the TPM chip does not
+ * exist.  Add the boot aggregate measurement to the measurement
+ * list and extend the PCR register.
+ *
+ * If a tpm chip does not exist, indicate the core root of trust is
+ * not hardware based by invalidating the aggregate PCR value.
+ * (The aggregate PCR value is invalidated by adding one value to
+ * the measurement list and extending the aggregate PCR value with
+ * a different value.) Violations add a zero entry to the measurement
+ * list and extend the aggregate PCR value with ff...ff's.
+ */
+static void ima_add_boot_aggregate(void)
+{
+	struct ima_template_entry *entry;
+	const char *op = "add_boot_aggregate";
+	const char *audit_cause = "ENOMEM";
+	int result = -ENOMEM;
+	int violation = 1;
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		goto err_out;
+
+	memset(&entry->template, 0, sizeof(entry->template));
+	strncpy(entry->template.file_name, boot_aggregate_name,
+		IMA_EVENT_NAME_LEN_MAX);
+	if (ima_used_chip) {
+		violation = 0;
+		result = ima_calc_boot_aggregate(entry->template.digest);
+		if (result < 0) {
+			audit_cause = "hashing_error";
+			kfree(entry);
+			goto err_out;
+		}
+	}
+	result = ima_store_template(entry, violation, NULL);
+	if (result < 0)
+		kfree(entry);
+	return;
+err_out:
+	integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op,
+			    audit_cause, result, 0);
+}
+
+int ima_init(void)
+{
+	u8 pcr_i[IMA_DIGEST_SIZE];
+	int rc;
+
+	ima_used_chip = 0;
+	rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i);
+	if (rc == 0)
+		ima_used_chip = 1;
+
+	if (!ima_used_chip)
+		pr_info("No TPM chip found, activating TPM-bypass!\n");
+
+	ima_add_boot_aggregate();	/* boot aggregate must be first entry */
+	ima_init_policy();
+
+	return ima_fs_init();
+}
+
+void __exit ima_cleanup(void)
+{
+	ima_fs_cleanup();
+}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
new file mode 100644
index 0000000..f4e7266
--- /dev/null
+++ b/security/integrity/ima/ima_main.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Serge Hallyn <serue@us.ibm.com>
+ * Kylene Hall <kylene@us.ibm.com>
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_main.c
+ *             implements the IMA hooks: ima_bprm_check, ima_file_mmap,
+ *             and ima_path_check.
+ */
+#include <linux/module.h>
+#include <linux/file.h>
+#include <linux/binfmts.h>
+#include <linux/mount.h>
+#include <linux/mman.h>
+
+#include "ima.h"
+
+int ima_initialized;
+
+char *ima_hash = "sha1";
+static int __init hash_setup(char *str)
+{
+	const char *op = "hash_setup";
+	const char *hash = "sha1";
+	int result = 0;
+	int audit_info = 0;
+
+	if (strncmp(str, "md5", 3) == 0) {
+		hash = "md5";
+		ima_hash = str;
+	} else if (strncmp(str, "sha1", 4) != 0) {
+		hash = "invalid_hash_type";
+		result = 1;
+	}
+	integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash,
+			    result, audit_info);
+	return 1;
+}
+__setup("ima_hash=", hash_setup);
+
+/**
+ * ima_file_free - called on __fput()
+ * @file: pointer to file structure being freed
+ *
+ * Flag files that changed, based on i_version;
+ * and decrement the iint readcount/writecount.
+ */
+void ima_file_free(struct file *file)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct ima_iint_cache *iint;
+
+	if (!ima_initialized || !S_ISREG(inode->i_mode))
+		return;
+	iint = ima_iint_find_get(inode);
+	if (!iint)
+		return;
+
+	mutex_lock(&iint->mutex);
+	if (iint->opencount <= 0) {
+		printk(KERN_INFO
+		       "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n",
+		       __FUNCTION__, file->f_dentry->d_name.name,
+		       iint->readcount, iint->writecount,
+		       iint->opencount, atomic_long_read(&file->f_count));
+		if (!(iint->flags & IMA_IINT_DUMP_STACK)) {
+			dump_stack();
+			iint->flags |= IMA_IINT_DUMP_STACK;
+		}
+	}
+	iint->opencount--;
+
+	if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+		iint->readcount--;
+
+	if (file->f_mode & FMODE_WRITE) {
+		iint->writecount--;
+		if (iint->writecount == 0) {
+			if (iint->version != inode->i_version)
+				iint->flags &= ~IMA_MEASURED;
+		}
+	}
+	mutex_unlock(&iint->mutex);
+	kref_put(&iint->refcount, iint_free);
+}
+
+/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
+ *
+ * When opening a file for read, if the file is already open for write,
+ * the file could change, resulting in a file measurement error.
+ *
+ * Opening a file for write, if the file is already open for read, results
+ * in a time of measure, time of use (ToMToU) error.
+ *
+ * In either case invalidate the PCR.
+ */
+enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
+static void ima_read_write_check(enum iint_pcr_error error,
+				 struct ima_iint_cache *iint,
+				 struct inode *inode,
+				 const unsigned char *filename)
+{
+	switch (error) {
+	case TOMTOU:
+		if (iint->readcount > 0)
+			ima_add_violation(inode, filename, "invalid_pcr",
+					  "ToMToU");
+		break;
+	case OPEN_WRITERS:
+		if (iint->writecount > 0)
+			ima_add_violation(inode, filename, "invalid_pcr",
+					  "open_writers");
+		break;
+	}
+}
+
+static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
+				const unsigned char *filename)
+{
+	int rc = 0;
+
+	if (IS_ERR(file)) {
+		pr_info("%s dentry_open failed\n", filename);
+		return rc;
+	}
+	iint->opencount++;
+	iint->readcount++;
+
+	rc = ima_collect_measurement(iint, file);
+	if (!rc)
+		ima_store_measurement(iint, file, filename);
+	return rc;
+}
+
+/**
+ * ima_path_check - based on policy, collect/store measurement.
+ * @path: contains a pointer to the path to be measured
+ * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
+ *
+ * Measure the file being open for readonly, based on the
+ * ima_must_measure() policy decision.
+ *
+ * Keep read/write counters for all files, but only
+ * invalidate the PCR for measured files:
+ * 	- Opening a file for write when already open for read,
+ *	  results in a time of measure, time of use (ToMToU) error.
+ *	- Opening a file for read when already open for write,
+ * 	  could result in a file measurement error.
+ *
+ * Return 0 on success, an error code on failure.
+ * (Based on the results of appraise_measurement().)
+ */
+int ima_path_check(struct path *path, int mask)
+{
+	struct inode *inode = path->dentry->d_inode;
+	struct ima_iint_cache *iint;
+	struct file *file = NULL;
+	int rc;
+
+	if (!ima_initialized || !S_ISREG(inode->i_mode))
+		return 0;
+	iint = ima_iint_find_insert_get(inode);
+	if (!iint)
+		return 0;
+
+	mutex_lock(&iint->mutex);
+	iint->opencount++;
+	if ((mask & MAY_WRITE) || (mask == 0))
+		iint->writecount++;
+	else if (mask & (MAY_READ | MAY_EXEC))
+		iint->readcount++;
+
+	rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
+	if (rc < 0)
+		goto out;
+
+	if ((mask & MAY_WRITE) || (mask == 0))
+		ima_read_write_check(TOMTOU, iint, inode,
+				     path->dentry->d_name.name);
+
+	if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ)
+		goto out;
+
+	ima_read_write_check(OPEN_WRITERS, iint, inode,
+			     path->dentry->d_name.name);
+	if (!(iint->flags & IMA_MEASURED)) {
+		struct dentry *dentry = dget(path->dentry);
+		struct vfsmount *mnt = mntget(path->mnt);
+
+		file = dentry_open(dentry, mnt, O_RDONLY, current->cred);
+		rc = get_path_measurement(iint, file, dentry->d_name.name);
+	}
+out:
+	mutex_unlock(&iint->mutex);
+	if (file)
+		fput(file);
+	kref_put(&iint->refcount, iint_free);
+	return 0;
+}
+
+static int process_measurement(struct file *file, const unsigned char *filename,
+			       int mask, int function)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct ima_iint_cache *iint;
+	int rc;
+
+	if (!ima_initialized || !S_ISREG(inode->i_mode))
+		return 0;
+	iint = ima_iint_find_insert_get(inode);
+	if (!iint)
+		return -ENOMEM;
+
+	mutex_lock(&iint->mutex);
+	rc = ima_must_measure(iint, inode, mask, function);
+	if (rc != 0)
+		goto out;
+
+	rc = ima_collect_measurement(iint, file);
+	if (!rc)
+		ima_store_measurement(iint, file, filename);
+out:
+	mutex_unlock(&iint->mutex);
+	kref_put(&iint->refcount, iint_free);
+	return rc;
+}
+
+static void opencount_get(struct file *file)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct ima_iint_cache *iint;
+
+	if (!ima_initialized || !S_ISREG(inode->i_mode))
+		return;
+	iint = ima_iint_find_insert_get(inode);
+	if (!iint)
+		return;
+	mutex_lock(&iint->mutex);
+	iint->opencount++;
+	mutex_unlock(&iint->mutex);
+}
+
+/**
+ * ima_file_mmap - based on policy, collect/store measurement.
+ * @file: pointer to the file to be measured (May be NULL)
+ * @prot: contains the protection that will be applied by the kernel.
+ *
+ * Measure files being mmapped executable based on the ima_must_measure()
+ * policy decision.
+ *
+ * Return 0 on success, an error code on failure.
+ * (Based on the results of appraise_measurement().)
+ */
+int ima_file_mmap(struct file *file, unsigned long prot)
+{
+	int rc;
+
+	if (!file)
+		return 0;
+	if (prot & PROT_EXEC)
+		rc = process_measurement(file, file->f_dentry->d_name.name,
+					 MAY_EXEC, FILE_MMAP);
+	return 0;
+}
+
+/*
+ * ima_shm_check - IPC shm and shmat create/fput a file
+ *
+ * Maintain the opencount for these files to prevent unnecessary
+ * imbalance messages.
+ */
+void ima_shm_check(struct file *file)
+{
+	opencount_get(file);
+	return;
+}
+
+/**
+ * ima_bprm_check - based on policy, collect/store measurement.
+ * @bprm: contains the linux_binprm structure
+ *
+ * The OS protects against an executable file, already open for write,
+ * from being executed in deny_write_access() and an executable file,
+ * already open for execute, from being modified in get_write_access().
+ * So we can be certain that what we verify and measure here is actually
+ * what is being executed.
+ *
+ * Return 0 on success, an error code on failure.
+ * (Based on the results of appraise_measurement().)
+ */
+int ima_bprm_check(struct linux_binprm *bprm)
+{
+	int rc;
+
+	rc = process_measurement(bprm->file, bprm->filename,
+				 MAY_EXEC, BPRM_CHECK);
+	return 0;
+}
+
+static int __init init_ima(void)
+{
+	int error;
+
+	ima_iintcache_init();
+	error = ima_init();
+	ima_initialized = 1;
+	return error;
+}
+
+static void __exit cleanup_ima(void)
+{
+	ima_cleanup();
+}
+
+late_initcall(init_ima);	/* Start IMA after the TPM is available */
+
+MODULE_DESCRIPTION("Integrity Measurement Architecture");
+MODULE_LICENSE("GPL");
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
new file mode 100644
index 0000000..b5291ad
--- /dev/null
+++ b/security/integrity/ima/ima_policy.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ * Author: Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * ima_policy.c
+ * 	- initialize default measure policy rules
+ *
+ */
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/security.h>
+#include <linux/magic.h>
+#include <linux/parser.h>
+
+#include "ima.h"
+
+/* flags definitions */
+#define IMA_FUNC 	0x0001
+#define IMA_MASK 	0x0002
+#define IMA_FSMAGIC	0x0004
+#define IMA_UID		0x0008
+
+enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE };
+
+#define MAX_LSM_RULES 6
+enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
+	LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
+};
+
+struct ima_measure_rule_entry {
+	struct list_head list;
+	enum ima_action action;
+	unsigned int flags;
+	enum ima_hooks func;
+	int mask;
+	unsigned long fsmagic;
+	uid_t uid;
+	struct {
+		void *rule;	/* LSM file metadata specific */
+		int type;	/* audit type */
+	} lsm[MAX_LSM_RULES];
+};
+
+/* Without LSM specific knowledge, the default policy can only be
+ * written in terms of .action, .func, .mask, .fsmagic, and .uid
+ */
+static struct ima_measure_rule_entry default_rules[] = {
+	{.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,
+	 .flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,
+	 .flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = 0xF97CFF8C,.flags = IMA_FSMAGIC},
+	{.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
+	 .flags = IMA_FUNC | IMA_MASK},
+	{.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
+	 .flags = IMA_FUNC | IMA_MASK},
+	{.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0,
+	 .flags = IMA_FUNC | IMA_MASK | IMA_UID}
+};
+
+static LIST_HEAD(measure_default_rules);
+static LIST_HEAD(measure_policy_rules);
+static struct list_head *ima_measure;
+
+static DEFINE_MUTEX(ima_measure_mutex);
+
+/**
+ * ima_match_rules - determine whether an inode matches the measure rule.
+ * @rule: a pointer to a rule
+ * @inode: a pointer to an inode
+ * @func: LIM hook identifier
+ * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
+ *
+ * Returns true on rule match, false on failure.
+ */
+static bool ima_match_rules(struct ima_measure_rule_entry *rule,
+			    struct inode *inode, enum ima_hooks func, int mask)
+{
+	struct task_struct *tsk = current;
+	int i;
+
+	if ((rule->flags & IMA_FUNC) && rule->func != func)
+		return false;
+	if ((rule->flags & IMA_MASK) && rule->mask != mask)
+		return false;
+	if ((rule->flags & IMA_FSMAGIC)
+	    && rule->fsmagic != inode->i_sb->s_magic)
+		return false;
+	if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
+		return false;
+	for (i = 0; i < MAX_LSM_RULES; i++) {
+		int rc;
+		u32 osid, sid;
+
+		if (!rule->lsm[i].rule)
+			continue;
+
+		switch (i) {
+		case LSM_OBJ_USER:
+		case LSM_OBJ_ROLE:
+		case LSM_OBJ_TYPE:
+			security_inode_getsecid(inode, &osid);
+			rc = security_filter_rule_match(osid,
+							rule->lsm[i].type,
+							AUDIT_EQUAL,
+							rule->lsm[i].rule,
+							NULL);
+			break;
+		case LSM_SUBJ_USER:
+		case LSM_SUBJ_ROLE:
+		case LSM_SUBJ_TYPE:
+			security_task_getsecid(tsk, &sid);
+			rc = security_filter_rule_match(sid,
+							rule->lsm[i].type,
+							AUDIT_EQUAL,
+							rule->lsm[i].rule,
+							NULL);
+		default:
+			break;
+		}
+		if (!rc)
+			return false;
+	}
+	return true;
+}
+
+/**
+ * ima_match_policy - decision based on LSM and other conditions
+ * @inode: pointer to an inode for which the policy decision is being made
+ * @func: IMA hook identifier
+ * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
+ *
+ * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
+ * conditions.
+ *
+ * (There is no need for locking when walking the policy list,
+ * as elements in the list are never deleted, nor does the list
+ * change.)
+ */
+int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask)
+{
+	struct ima_measure_rule_entry *entry;
+
+	list_for_each_entry(entry, ima_measure, list) {
+		bool rc;
+
+		rc = ima_match_rules(entry, inode, func, mask);
+		if (rc)
+			return entry->action;
+	}
+	return 0;
+}
+
+/**
+ * ima_init_policy - initialize the default measure rules.
+ *
+ * ima_measure points to either the measure_default_rules or the
+ * the new measure_policy_rules.
+ */
+void ima_init_policy(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(default_rules); i++)
+		list_add_tail(&default_rules[i].list, &measure_default_rules);
+	ima_measure = &measure_default_rules;
+}
+
+/**
+ * ima_update_policy - update default_rules with new measure rules
+ *
+ * Called on file .release to update the default rules with a complete new
+ * policy.  Once updated, the policy is locked, no additional rules can be
+ * added to the policy.
+ */
+void ima_update_policy(void)
+{
+	const char *op = "policy_update";
+	const char *cause = "already exists";
+	int result = 1;
+	int audit_info = 0;
+
+	if (ima_measure == &measure_default_rules) {
+		ima_measure = &measure_policy_rules;
+		cause = "complete";
+		result = 0;
+	}
+	integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
+			    NULL, op, cause, result, audit_info);
+}
+
+enum {
+	Opt_err = -1,
+	Opt_measure = 1, Opt_dont_measure,
+	Opt_obj_user, Opt_obj_role, Opt_obj_type,
+	Opt_subj_user, Opt_subj_role, Opt_subj_type,
+	Opt_func, Opt_mask, Opt_fsmagic, Opt_uid
+};
+
+static match_table_t policy_tokens = {
+	{Opt_measure, "measure"},
+	{Opt_dont_measure, "dont_measure"},
+	{Opt_obj_user, "obj_user=%s"},
+	{Opt_obj_role, "obj_role=%s"},
+	{Opt_obj_type, "obj_type=%s"},
+	{Opt_subj_user, "subj_user=%s"},
+	{Opt_subj_role, "subj_role=%s"},
+	{Opt_subj_type, "subj_type=%s"},
+	{Opt_func, "func=%s"},
+	{Opt_mask, "mask=%s"},
+	{Opt_fsmagic, "fsmagic=%s"},
+	{Opt_uid, "uid=%s"},
+	{Opt_err, NULL}
+};
+
+static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
+			     char *args, int lsm_rule, int audit_type)
+{
+	int result;
+
+	entry->lsm[lsm_rule].type = audit_type;
+	result = security_filter_rule_init(entry->lsm[lsm_rule].type,
+					   AUDIT_EQUAL, args,
+					   &entry->lsm[lsm_rule].rule);
+	return result;
+}
+
+static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
+{
+	struct audit_buffer *ab;
+	char *p;
+	int result = 0;
+
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
+
+	entry->action = -1;
+	while ((p = strsep(&rule, " \n")) != NULL) {
+		substring_t args[MAX_OPT_ARGS];
+		int token;
+		unsigned long lnum;
+
+		if (result < 0)
+			break;
+		if (!*p)
+			continue;
+		token = match_token(p, policy_tokens, args);
+		switch (token) {
+		case Opt_measure:
+			audit_log_format(ab, "%s ", "measure");
+			entry->action = MEASURE;
+			break;
+		case Opt_dont_measure:
+			audit_log_format(ab, "%s ", "dont_measure");
+			entry->action = DONT_MEASURE;
+			break;
+		case Opt_func:
+			audit_log_format(ab, "func=%s ", args[0].from);
+			if (strcmp(args[0].from, "PATH_CHECK") == 0)
+				entry->func = PATH_CHECK;
+			else if (strcmp(args[0].from, "FILE_MMAP") == 0)
+				entry->func = FILE_MMAP;
+			else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
+				entry->func = BPRM_CHECK;
+			else
+				result = -EINVAL;
+			if (!result)
+				entry->flags |= IMA_FUNC;
+			break;
+		case Opt_mask:
+			audit_log_format(ab, "mask=%s ", args[0].from);
+			if ((strcmp(args[0].from, "MAY_EXEC")) == 0)
+				entry->mask = MAY_EXEC;
+			else if (strcmp(args[0].from, "MAY_WRITE") == 0)
+				entry->mask = MAY_WRITE;
+			else if (strcmp(args[0].from, "MAY_READ") == 0)
+				entry->mask = MAY_READ;
+			else if (strcmp(args[0].from, "MAY_APPEND") == 0)
+				entry->mask = MAY_APPEND;
+			else
+				result = -EINVAL;
+			if (!result)
+				entry->flags |= IMA_MASK;
+			break;
+		case Opt_fsmagic:
+			audit_log_format(ab, "fsmagic=%s ", args[0].from);
+			result = strict_strtoul(args[0].from, 16,
+						&entry->fsmagic);
+			if (!result)
+				entry->flags |= IMA_FSMAGIC;
+			break;
+		case Opt_uid:
+			audit_log_format(ab, "uid=%s ", args[0].from);
+			result = strict_strtoul(args[0].from, 10, &lnum);
+			if (!result) {
+				entry->uid = (uid_t) lnum;
+				if (entry->uid != lnum)
+					result = -EINVAL;
+				else
+					entry->flags |= IMA_UID;
+			}
+			break;
+		case Opt_obj_user:
+			audit_log_format(ab, "obj_user=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_OBJ_USER,
+						   AUDIT_OBJ_USER);
+			break;
+		case Opt_obj_role:
+			audit_log_format(ab, "obj_role=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_OBJ_ROLE,
+						   AUDIT_OBJ_ROLE);
+			break;
+		case Opt_obj_type:
+			audit_log_format(ab, "obj_type=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_OBJ_TYPE,
+						   AUDIT_OBJ_TYPE);
+			break;
+		case Opt_subj_user:
+			audit_log_format(ab, "subj_user=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_SUBJ_USER,
+						   AUDIT_SUBJ_USER);
+			break;
+		case Opt_subj_role:
+			audit_log_format(ab, "subj_role=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_SUBJ_ROLE,
+						   AUDIT_SUBJ_ROLE);
+			break;
+		case Opt_subj_type:
+			audit_log_format(ab, "subj_type=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_SUBJ_TYPE,
+						   AUDIT_SUBJ_TYPE);
+			break;
+		case Opt_err:
+			audit_log_format(ab, "UNKNOWN=%s ", p);
+			break;
+		}
+	}
+	if (entry->action == UNKNOWN)
+		result = -EINVAL;
+
+	audit_log_format(ab, "res=%d", !result ? 0 : 1);
+	audit_log_end(ab);
+	return result;
+}
+
+/**
+ * ima_parse_add_rule - add a rule to measure_policy_rules
+ * @rule - ima measurement policy rule
+ *
+ * Uses a mutex to protect the policy list from multiple concurrent writers.
+ * Returns 0 on success, an error code on failure.
+ */
+int ima_parse_add_rule(char *rule)
+{
+	const char *op = "update_policy";
+	struct ima_measure_rule_entry *entry;
+	int result = 0;
+	int audit_info = 0;
+
+	/* Prevent installed policy from changing */
+	if (ima_measure != &measure_default_rules) {
+		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
+				    NULL, op, "already exists",
+				    -EACCES, audit_info);
+		return -EACCES;
+	}
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
+				    NULL, op, "-ENOMEM", -ENOMEM, audit_info);
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&entry->list);
+
+	result = ima_parse_rule(rule, entry);
+	if (!result) {
+		mutex_lock(&ima_measure_mutex);
+		list_add_tail(&entry->list, &measure_policy_rules);
+		mutex_unlock(&ima_measure_mutex);
+	} else {
+		kfree(entry);
+		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
+				    NULL, op, "invalid policy", result,
+				    audit_info);
+	}
+	return result;
+}
+
+/* ima_delete_rules called to cleanup invalid policy */
+void ima_delete_rules(void)
+{
+	struct ima_measure_rule_entry *entry, *tmp;
+
+	mutex_lock(&ima_measure_mutex);
+	list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+	mutex_unlock(&ima_measure_mutex);
+}
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
new file mode 100644
index 0000000..7ec9431
--- /dev/null
+++ b/security/integrity/ima/ima_queue.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Serge Hallyn <serue@us.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_queue.c
+ *       Implements queues that store template measurements and
+ *       maintains aggregate over the stored measurements
+ *       in the pre-configured TPM PCR (if available).
+ *       The measurement list is append-only. No entry is
+ *       ever removed or changed during the boot-cycle.
+ */
+#include <linux/module.h>
+#include <linux/rculist.h>
+#include "ima.h"
+
+LIST_HEAD(ima_measurements);	/* list of all measurements */
+
+/* key: inode (before secure-hashing a file) */
+struct ima_h_table ima_htable = {
+	.len = ATOMIC_LONG_INIT(0),
+	.violations = ATOMIC_LONG_INIT(0),
+	.queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT
+};
+
+/* mutex protects atomicity of extending measurement list
+ * and extending the TPM PCR aggregate. Since tpm_extend can take
+ * long (and the tpm driver uses a mutex), we can't use the spinlock.
+ */
+static DEFINE_MUTEX(ima_extend_list_mutex);
+
+/* lookup up the digest value in the hash table, and return the entry */
+static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value)
+{
+	struct ima_queue_entry *qe, *ret = NULL;
+	unsigned int key;
+	struct hlist_node *pos;
+	int rc;
+
+	key = ima_hash_key(digest_value);
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(qe, pos, &ima_htable.queue[key], hnext) {
+		rc = memcmp(qe->entry->digest, digest_value, IMA_DIGEST_SIZE);
+		if (rc == 0) {
+			ret = qe;
+			break;
+		}
+	}
+	rcu_read_unlock();
+	return ret;
+}
+
+/* ima_add_template_entry helper function:
+ * - Add template entry to measurement list and hash table.
+ *
+ * (Called with ima_extend_list_mutex held.)
+ */
+static int ima_add_digest_entry(struct ima_template_entry *entry)
+{
+	struct ima_queue_entry *qe;
+	unsigned int key;
+
+	qe = kmalloc(sizeof(*qe), GFP_KERNEL);
+	if (qe == NULL) {
+		pr_err("OUT OF MEMORY ERROR creating queue entry.\n");
+		return -ENOMEM;
+	}
+	qe->entry = entry;
+
+	INIT_LIST_HEAD(&qe->later);
+	list_add_tail_rcu(&qe->later, &ima_measurements);
+
+	atomic_long_inc(&ima_htable.len);
+	key = ima_hash_key(entry->digest);
+	hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
+	return 0;
+}
+
+static int ima_pcr_extend(const u8 *hash)
+{
+	int result = 0;
+
+	if (!ima_used_chip)
+		return result;
+
+	result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
+	if (result != 0)
+		pr_err("Error Communicating to TPM chip\n");
+	return result;
+}
+
+/* Add template entry to the measurement list and hash table,
+ * and extend the pcr.
+ */
+int ima_add_template_entry(struct ima_template_entry *entry, int violation,
+			   const char *op, struct inode *inode)
+{
+	u8 digest[IMA_DIGEST_SIZE];
+	const char *audit_cause = "hash_added";
+	int audit_info = 1;
+	int result = 0;
+
+	mutex_lock(&ima_extend_list_mutex);
+	if (!violation) {
+		memcpy(digest, entry->digest, sizeof digest);
+		if (ima_lookup_digest_entry(digest)) {
+			audit_cause = "hash_exists";
+			goto out;
+		}
+	}
+
+	result = ima_add_digest_entry(entry);
+	if (result < 0) {
+		audit_cause = "ENOMEM";
+		audit_info = 0;
+		goto out;
+	}
+
+	if (violation)		/* invalidate pcr */
+		memset(digest, 0xff, sizeof digest);
+
+	result = ima_pcr_extend(digest);
+	if (result != 0) {
+		audit_cause = "TPM error";
+		audit_info = 0;
+	}
+out:
+	mutex_unlock(&ima_extend_list_mutex);
+	integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, entry->template_name,
+			    op, audit_cause, result, audit_info);
+	return result;
+}
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 81932ab..9fb679c 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -53,6 +53,7 @@
 	atomic_t		nkeys;		/* number of keys */
 	atomic_t		nikeys;		/* number of instantiated keys */
 	uid_t			uid;
+	struct user_namespace	*user_ns;
 	int			qnkeys;		/* number of keys allocated to this user */
 	int			qnbytes;	/* number of bytes allocated to this user */
 };
@@ -61,7 +62,8 @@
 extern spinlock_t	key_user_lock;
 extern struct key_user	root_key_user;
 
-extern struct key_user *key_user_lookup(uid_t uid);
+extern struct key_user *key_user_lookup(uid_t uid,
+					struct user_namespace *user_ns);
 extern void key_user_put(struct key_user *user);
 
 /*
diff --git a/security/keys/key.c b/security/keys/key.c
index f76c8a5..4a1297d 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -18,6 +18,7 @@
 #include <linux/workqueue.h>
 #include <linux/random.h>
 #include <linux/err.h>
+#include <linux/user_namespace.h>
 #include "internal.h"
 
 static struct kmem_cache	*key_jar;
@@ -60,7 +61,7 @@
  * get the key quota record for a user, allocating a new record if one doesn't
  * already exist
  */
-struct key_user *key_user_lookup(uid_t uid)
+struct key_user *key_user_lookup(uid_t uid, struct user_namespace *user_ns)
 {
 	struct key_user *candidate = NULL, *user;
 	struct rb_node *parent = NULL;
@@ -79,6 +80,10 @@
 			p = &(*p)->rb_left;
 		else if (uid > user->uid)
 			p = &(*p)->rb_right;
+		else if (user_ns < user->user_ns)
+			p = &(*p)->rb_left;
+		else if (user_ns > user->user_ns)
+			p = &(*p)->rb_right;
 		else
 			goto found;
 	}
@@ -106,6 +111,7 @@
 	atomic_set(&candidate->nkeys, 0);
 	atomic_set(&candidate->nikeys, 0);
 	candidate->uid = uid;
+	candidate->user_ns = get_user_ns(user_ns);
 	candidate->qnkeys = 0;
 	candidate->qnbytes = 0;
 	spin_lock_init(&candidate->lock);
@@ -136,6 +142,7 @@
 	if (atomic_dec_and_lock(&user->usage, &key_user_lock)) {
 		rb_erase(&user->node, &key_user_tree);
 		spin_unlock(&key_user_lock);
+		put_user_ns(user->user_ns);
 
 		kfree(user);
 	}
@@ -234,7 +241,7 @@
 	quotalen = desclen + type->def_datalen;
 
 	/* get hold of the key tracking for this user */
-	user = key_user_lookup(uid);
+	user = key_user_lookup(uid, cred->user->user_ns);
 	if (!user)
 		goto no_memory_1;
 
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index b1ec3b4..7f09fb8 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -726,7 +726,7 @@
 	/* change the UID */
 	if (uid != (uid_t) -1 && uid != key->uid) {
 		ret = -ENOMEM;
-		newowner = key_user_lookup(uid);
+		newowner = key_user_lookup(uid, current_user_ns());
 		if (!newowner)
 			goto error_put;
 
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index ed85157..3dba81c 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -539,6 +539,9 @@
 				    &keyring_name_hash[bucket],
 				    type_data.link
 				    ) {
+			if (keyring->user->user_ns != current_user_ns())
+				continue;
+
 			if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
 				continue;
 
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 5d9fc7b..0ed802c 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -35,6 +35,9 @@
 
 	key = key_ref_to_ptr(key_ref);
 
+	if (key->user->user_ns != cred->user->user_ns)
+		goto use_other_perms;
+
 	/* use the second 8-bits of permissions for keys the caller owns */
 	if (key->uid == cred->fsuid) {
 		kperm = key->perm >> 16;
@@ -56,6 +59,8 @@
 		}
 	}
 
+use_other_perms:
+
 	/* otherwise use the least-significant 8-bits */
 	kperm = key->perm;
 
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 7f508de..769f9bd 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -91,6 +91,28 @@
  */
 #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
 
+static struct rb_node *__key_serial_next(struct rb_node *n)
+{
+	while (n) {
+		struct key *key = rb_entry(n, struct key, serial_node);
+		if (key->user->user_ns == current_user_ns())
+			break;
+		n = rb_next(n);
+	}
+	return n;
+}
+
+static struct rb_node *key_serial_next(struct rb_node *n)
+{
+	return __key_serial_next(rb_next(n));
+}
+
+static struct rb_node *key_serial_first(struct rb_root *r)
+{
+	struct rb_node *n = rb_first(r);
+	return __key_serial_next(n);
+}
+
 static int proc_keys_open(struct inode *inode, struct file *file)
 {
 	return seq_open(file, &proc_keys_ops);
@@ -104,10 +126,10 @@
 
 	spin_lock(&key_serial_lock);
 
-	_p = rb_first(&key_serial_tree);
+	_p = key_serial_first(&key_serial_tree);
 	while (pos > 0 && _p) {
 		pos--;
-		_p = rb_next(_p);
+		_p = key_serial_next(_p);
 	}
 
 	return _p;
@@ -117,7 +139,7 @@
 static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos)
 {
 	(*_pos)++;
-	return rb_next((struct rb_node *) v);
+	return key_serial_next((struct rb_node *) v);
 
 }
 
@@ -203,6 +225,27 @@
 
 #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */
 
+static struct rb_node *__key_user_next(struct rb_node *n)
+{
+	while (n) {
+		struct key_user *user = rb_entry(n, struct key_user, node);
+		if (user->user_ns == current_user_ns())
+			break;
+		n = rb_next(n);
+	}
+	return n;
+}
+
+static struct rb_node *key_user_next(struct rb_node *n)
+{
+	return __key_user_next(rb_next(n));
+}
+
+static struct rb_node *key_user_first(struct rb_root *r)
+{
+	struct rb_node *n = rb_first(r);
+	return __key_user_next(n);
+}
 /*****************************************************************************/
 /*
  * implement "/proc/key-users" to provides a list of the key users
@@ -220,10 +263,10 @@
 
 	spin_lock(&key_user_lock);
 
-	_p = rb_first(&key_user_tree);
+	_p = key_user_first(&key_user_tree);
 	while (pos > 0 && _p) {
 		pos--;
-		_p = rb_next(_p);
+		_p = key_user_next(_p);
 	}
 
 	return _p;
@@ -233,7 +276,7 @@
 static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos)
 {
 	(*_pos)++;
-	return rb_next((struct rb_node *) v);
+	return key_user_next((struct rb_node *) v);
 
 }
 
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 2f5d89e..276d278 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/user_namespace.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -34,6 +35,7 @@
 	.nkeys		= ATOMIC_INIT(2),
 	.nikeys		= ATOMIC_INIT(2),
 	.uid		= 0,
+	.user_ns	= &init_user_ns,
 };
 
 /*****************************************************************************/
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 0e04f72..22a3158 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -365,7 +365,7 @@
 
 	kenter("");
 
-	user = key_user_lookup(current_fsuid());
+	user = key_user_lookup(current_fsuid(), current_user_ns());
 	if (!user)
 		return ERR_PTR(-ENOMEM);
 
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index eb41f43..7f9b5fa 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -88,17 +88,16 @@
 	u32			tsid;
 	u16			tclass;
 	struct av_decision	avd;
-	atomic_t		used;	/* used recently */
 };
 
 struct avc_node {
 	struct avc_entry	ae;
-	struct list_head	list;
+	struct hlist_node	list; /* anchored in avc_cache->slots[i] */
 	struct rcu_head		rhead;
 };
 
 struct avc_cache {
-	struct list_head	slots[AVC_CACHE_SLOTS];
+	struct hlist_head	slots[AVC_CACHE_SLOTS]; /* head for avc_node->list */
 	spinlock_t		slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
 	atomic_t		lru_hint;	/* LRU hint for reclaim scan */
 	atomic_t		active_nodes;
@@ -234,7 +233,7 @@
 	int i;
 
 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
-		INIT_LIST_HEAD(&avc_cache.slots[i]);
+		INIT_HLIST_HEAD(&avc_cache.slots[i]);
 		spin_lock_init(&avc_cache.slots_lock[i]);
 	}
 	atomic_set(&avc_cache.active_nodes, 0);
@@ -250,16 +249,20 @@
 {
 	int i, chain_len, max_chain_len, slots_used;
 	struct avc_node *node;
+	struct hlist_head *head;
 
 	rcu_read_lock();
 
 	slots_used = 0;
 	max_chain_len = 0;
 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
-		if (!list_empty(&avc_cache.slots[i])) {
+		head = &avc_cache.slots[i];
+		if (!hlist_empty(head)) {
+			struct hlist_node *next;
+
 			slots_used++;
 			chain_len = 0;
-			list_for_each_entry_rcu(node, &avc_cache.slots[i], list)
+			hlist_for_each_entry_rcu(node, next, head, list)
 				chain_len++;
 			if (chain_len > max_chain_len)
 				max_chain_len = chain_len;
@@ -283,7 +286,7 @@
 
 static void avc_node_delete(struct avc_node *node)
 {
-	list_del_rcu(&node->list);
+	hlist_del_rcu(&node->list);
 	call_rcu(&node->rhead, avc_node_free);
 	atomic_dec(&avc_cache.active_nodes);
 }
@@ -297,7 +300,7 @@
 
 static void avc_node_replace(struct avc_node *new, struct avc_node *old)
 {
-	list_replace_rcu(&old->list, &new->list);
+	hlist_replace_rcu(&old->list, &new->list);
 	call_rcu(&old->rhead, avc_node_free);
 	atomic_dec(&avc_cache.active_nodes);
 }
@@ -307,29 +310,31 @@
 	struct avc_node *node;
 	int hvalue, try, ecx;
 	unsigned long flags;
+	struct hlist_head *head;
+	struct hlist_node *next;
+	spinlock_t *lock;
 
 	for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
 		hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
+		head = &avc_cache.slots[hvalue];
+		lock = &avc_cache.slots_lock[hvalue];
 
-		if (!spin_trylock_irqsave(&avc_cache.slots_lock[hvalue], flags))
+		if (!spin_trylock_irqsave(lock, 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 */
-				avc_node_delete(node);
-				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;
-				}
+		hlist_for_each_entry(node, next, head, list) {
+			avc_node_delete(node);
+			avc_cache_stats_incr(reclaims);
+			ecx++;
+			if (ecx >= AVC_CACHE_RECLAIM) {
+				rcu_read_unlock();
+				spin_unlock_irqrestore(lock, flags);
+				goto out;
 			}
 		}
 		rcu_read_unlock();
-		spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
+		spin_unlock_irqrestore(lock, flags);
 	}
 out:
 	return ecx;
@@ -344,8 +349,7 @@
 		goto out;
 
 	INIT_RCU_HEAD(&node->rhead);
-	INIT_LIST_HEAD(&node->list);
-	atomic_set(&node->ae.used, 1);
+	INIT_HLIST_NODE(&node->list);
 	avc_cache_stats_incr(allocations);
 
 	if (atomic_inc_return(&avc_cache.active_nodes) > avc_cache_threshold)
@@ -355,21 +359,24 @@
 	return node;
 }
 
-static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae)
+static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd)
 {
 	node->ae.ssid = ssid;
 	node->ae.tsid = tsid;
 	node->ae.tclass = tclass;
-	memcpy(&node->ae.avd, &ae->avd, sizeof(node->ae.avd));
+	memcpy(&node->ae.avd, avd, sizeof(node->ae.avd));
 }
 
 static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
 {
 	struct avc_node *node, *ret = NULL;
 	int hvalue;
+	struct hlist_head *head;
+	struct hlist_node *next;
 
 	hvalue = avc_hash(ssid, tsid, tclass);
-	list_for_each_entry_rcu(node, &avc_cache.slots[hvalue], list) {
+	head = &avc_cache.slots[hvalue];
+	hlist_for_each_entry_rcu(node, next, head, list) {
 		if (ssid == node->ae.ssid &&
 		    tclass == node->ae.tclass &&
 		    tsid == node->ae.tsid) {
@@ -378,15 +385,6 @@
 		}
 	}
 
-	if (ret == NULL) {
-		/* cache miss */
-		goto out;
-	}
-
-	/* cache hit */
-	if (atomic_read(&ret->ae.used) != 1)
-		atomic_set(&ret->ae.used, 1);
-out:
 	return ret;
 }
 
@@ -395,30 +393,25 @@
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
- * @requested: requested permissions, interpreted based on @tclass
  *
  * Look up an AVC entry that is valid for the
- * @requested permissions between the SID pair
  * (@ssid, @tsid), interpreting the permissions
  * based on @tclass.  If a valid AVC entry exists,
  * then this function return the avc_node.
  * Otherwise, this function returns NULL.
  */
-static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass, u32 requested)
+static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass)
 {
 	struct avc_node *node;
 
 	avc_cache_stats_incr(lookups);
 	node = avc_search_node(ssid, tsid, tclass);
 
-	if (node && ((node->ae.avd.decided & requested) == requested)) {
+	if (node)
 		avc_cache_stats_incr(hits);
-		goto out;
-	}
+	else
+		avc_cache_stats_incr(misses);
 
-	node = NULL;
-	avc_cache_stats_incr(misses);
-out:
 	return node;
 }
 
@@ -449,34 +442,41 @@
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
- * @ae: AVC entry
+ * @avd: resulting av decision
  *
  * Insert an AVC entry for the SID pair
  * (@ssid, @tsid) and class @tclass.
  * The access vectors and the sequence number are
  * normally provided by the security server in
  * response to a security_compute_av() call.  If the
- * sequence number @ae->avd.seqno is not less than the latest
+ * sequence number @avd->seqno is not less than the latest
  * revocation notification, then the function copies
  * the access vectors into a cache entry, returns
  * avc_node inserted. Otherwise, this function returns NULL.
  */
-static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae)
+static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd)
 {
 	struct avc_node *pos, *node = NULL;
 	int hvalue;
 	unsigned long flag;
 
-	if (avc_latest_notif_update(ae->avd.seqno, 1))
+	if (avc_latest_notif_update(avd->seqno, 1))
 		goto out;
 
 	node = avc_alloc_node();
 	if (node) {
-		hvalue = avc_hash(ssid, tsid, tclass);
-		avc_node_populate(node, ssid, tsid, tclass, ae);
+		struct hlist_head *head;
+		struct hlist_node *next;
+		spinlock_t *lock;
 
-		spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
-		list_for_each_entry(pos, &avc_cache.slots[hvalue], list) {
+		hvalue = avc_hash(ssid, tsid, tclass);
+		avc_node_populate(node, ssid, tsid, tclass, avd);
+
+		head = &avc_cache.slots[hvalue];
+		lock = &avc_cache.slots_lock[hvalue];
+
+		spin_lock_irqsave(lock, flag);
+		hlist_for_each_entry(pos, next, head, list) {
 			if (pos->ae.ssid == ssid &&
 			    pos->ae.tsid == tsid &&
 			    pos->ae.tclass == tclass) {
@@ -484,9 +484,9 @@
 				goto found;
 			}
 		}
-		list_add_rcu(&node->list, &avc_cache.slots[hvalue]);
+		hlist_add_head_rcu(&node->list, head);
 found:
-		spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
+		spin_unlock_irqrestore(lock, flag);
 	}
 out:
 	return node;
@@ -742,17 +742,22 @@
  * @event : Updating event
  * @perms : Permission mask bits
  * @ssid,@tsid,@tclass : identifier of an AVC entry
+ * @seqno : sequence number when decision was made
  *
  * if a valid AVC entry doesn't exist,this function returns -ENOENT.
  * if kmalloc() called internal returns NULL, this function returns -ENOMEM.
  * otherwise, this function update the AVC entry. The original AVC-entry object
  * will release later by RCU.
  */
-static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass)
+static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass,
+			   u32 seqno)
 {
 	int hvalue, rc = 0;
 	unsigned long flag;
 	struct avc_node *pos, *node, *orig = NULL;
+	struct hlist_head *head;
+	struct hlist_node *next;
+	spinlock_t *lock;
 
 	node = avc_alloc_node();
 	if (!node) {
@@ -762,12 +767,17 @@
 
 	/* Lock the target slot */
 	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) {
+	head = &avc_cache.slots[hvalue];
+	lock = &avc_cache.slots_lock[hvalue];
+
+	spin_lock_irqsave(lock, flag);
+
+	hlist_for_each_entry(pos, next, head, list) {
 		if (ssid == pos->ae.ssid &&
 		    tsid == pos->ae.tsid &&
-		    tclass == pos->ae.tclass){
+		    tclass == pos->ae.tclass &&
+		    seqno == pos->ae.avd.seqno){
 			orig = pos;
 			break;
 		}
@@ -783,7 +793,7 @@
 	 * Copy and replace original node.
 	 */
 
-	avc_node_populate(node, ssid, tsid, tclass, &orig->ae);
+	avc_node_populate(node, ssid, tsid, tclass, &orig->ae.avd);
 
 	switch (event) {
 	case AVC_CALLBACK_GRANT:
@@ -808,7 +818,7 @@
 	}
 	avc_node_replace(node, orig);
 out_unlock:
-	spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
+	spin_unlock_irqrestore(lock, flag);
 out:
 	return rc;
 }
@@ -823,18 +833,24 @@
 	int i, rc = 0, tmprc;
 	unsigned long flag;
 	struct avc_node *node;
+	struct hlist_head *head;
+	struct hlist_node *next;
+	spinlock_t *lock;
 
 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
-		spin_lock_irqsave(&avc_cache.slots_lock[i], flag);
+		head = &avc_cache.slots[i];
+		lock = &avc_cache.slots_lock[i];
+
+		spin_lock_irqsave(lock, 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)
+		hlist_for_each_entry(node, next, head, list)
 			avc_node_delete(node);
 		rcu_read_unlock();
-		spin_unlock_irqrestore(&avc_cache.slots_lock[i], flag);
+		spin_unlock_irqrestore(lock, flag);
 	}
 
 	for (c = avc_callbacks; c; c = c->next) {
@@ -875,10 +891,10 @@
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
 			 u16 tclass, u32 requested,
 			 unsigned flags,
-			 struct av_decision *avd)
+			 struct av_decision *in_avd)
 {
 	struct avc_node *node;
-	struct avc_entry entry, *p_ae;
+	struct av_decision avd_entry, *avd;
 	int rc = 0;
 	u32 denied;
 
@@ -886,29 +902,34 @@
 
 	rcu_read_lock();
 
-	node = avc_lookup(ssid, tsid, tclass, requested);
+	node = avc_lookup(ssid, tsid, tclass);
 	if (!node) {
 		rcu_read_unlock();
-		rc = security_compute_av(ssid, tsid, tclass, requested, &entry.avd);
+
+		if (in_avd)
+			avd = in_avd;
+		else
+			avd = &avd_entry;
+
+		rc = security_compute_av(ssid, tsid, tclass, requested, avd);
 		if (rc)
 			goto out;
 		rcu_read_lock();
-		node = avc_insert(ssid, tsid, tclass, &entry);
+		node = avc_insert(ssid, tsid, tclass, avd);
+	} else {
+		if (in_avd)
+			memcpy(in_avd, &node->ae.avd, sizeof(*in_avd));
+		avd = &node->ae.avd;
 	}
 
-	p_ae = node ? &node->ae : &entry;
-
-	if (avd)
-		memcpy(avd, &p_ae->avd, sizeof(*avd));
-
-	denied = requested & ~(p_ae->avd.allowed);
+	denied = requested & ~(avd->allowed);
 
 	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);
+					tsid, tclass, avd->seqno);
 		else
 			rc = -EACCES;
 	}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 0081597..7c52ba2 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -89,7 +89,7 @@
 #define XATTR_SELINUX_SUFFIX "selinux"
 #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
 
-#define NUM_SEL_MNT_OPTS 4
+#define NUM_SEL_MNT_OPTS 5
 
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
@@ -353,6 +353,7 @@
 	Opt_fscontext = 2,
 	Opt_defcontext = 3,
 	Opt_rootcontext = 4,
+	Opt_labelsupport = 5,
 };
 
 static const match_table_t tokens = {
@@ -360,6 +361,7 @@
 	{Opt_fscontext, FSCONTEXT_STR "%s"},
 	{Opt_defcontext, DEFCONTEXT_STR "%s"},
 	{Opt_rootcontext, ROOTCONTEXT_STR "%s"},
+	{Opt_labelsupport, LABELSUPP_STR},
 	{Opt_error, NULL},
 };
 
@@ -431,7 +433,7 @@
 		}
 	}
 
-	sbsec->initialized = 1;
+	sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
 
 	if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
 		printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
@@ -441,6 +443,12 @@
 		       sb->s_id, sb->s_type->name,
 		       labeling_behaviors[sbsec->behavior-1]);
 
+	if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
+	    sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
+	    sbsec->behavior == SECURITY_FS_USE_NONE ||
+	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
+		sbsec->flags &= ~SE_SBLABELSUPP;
+
 	/* Initialize the root inode. */
 	rc = inode_doinit_with_dentry(root_inode, root);
 
@@ -487,23 +495,22 @@
 
 	security_init_mnt_opts(opts);
 
-	if (!sbsec->initialized)
+	if (!(sbsec->flags & SE_SBINITIALIZED))
 		return -EINVAL;
 
 	if (!ss_initialized)
 		return -EINVAL;
 
-	/*
-	 * if we ever use sbsec flags for anything other than tracking mount
-	 * settings this is going to need a mask
-	 */
-	tmp = sbsec->flags;
+	tmp = sbsec->flags & SE_MNTMASK;
 	/* count the number of mount options for this sb */
 	for (i = 0; i < 8; i++) {
 		if (tmp & 0x01)
 			opts->num_mnt_opts++;
 		tmp >>= 1;
 	}
+	/* Check if the Label support flag is set */
+	if (sbsec->flags & SE_SBLABELSUPP)
+		opts->num_mnt_opts++;
 
 	opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
 	if (!opts->mnt_opts) {
@@ -549,6 +556,10 @@
 		opts->mnt_opts[i] = context;
 		opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
 	}
+	if (sbsec->flags & SE_SBLABELSUPP) {
+		opts->mnt_opts[i] = NULL;
+		opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
+	}
 
 	BUG_ON(i != opts->num_mnt_opts);
 
@@ -562,8 +573,10 @@
 static int bad_option(struct superblock_security_struct *sbsec, char flag,
 		      u32 old_sid, u32 new_sid)
 {
+	char mnt_flags = sbsec->flags & SE_MNTMASK;
+
 	/* check if the old mount command had the same options */
-	if (sbsec->initialized)
+	if (sbsec->flags & SE_SBINITIALIZED)
 		if (!(sbsec->flags & flag) ||
 		    (old_sid != new_sid))
 			return 1;
@@ -571,8 +584,8 @@
 	/* check if we were passed the same options twice,
 	 * aka someone passed context=a,context=b
 	 */
-	if (!sbsec->initialized)
-		if (sbsec->flags & flag)
+	if (!(sbsec->flags & SE_SBINITIALIZED))
+		if (mnt_flags & flag)
 			return 1;
 	return 0;
 }
@@ -626,7 +639,7 @@
 	 * this sb does not set any security options.  (The first options
 	 * will be used for both mounts)
 	 */
-	if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
+	if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
 	    && (num_opts == 0))
 		goto out;
 
@@ -637,6 +650,9 @@
 	 */
 	for (i = 0; i < num_opts; i++) {
 		u32 sid;
+
+		if (flags[i] == SE_SBLABELSUPP)
+			continue;
 		rc = security_context_to_sid(mount_options[i],
 					     strlen(mount_options[i]), &sid);
 		if (rc) {
@@ -690,19 +706,19 @@
 		}
 	}
 
-	if (sbsec->initialized) {
+	if (sbsec->flags & SE_SBINITIALIZED) {
 		/* previously mounted with options, but not on this attempt? */
-		if (sbsec->flags && !num_opts)
+		if ((sbsec->flags & SE_MNTMASK) && !num_opts)
 			goto out_double_mount;
 		rc = 0;
 		goto out;
 	}
 
 	if (strcmp(sb->s_type->name, "proc") == 0)
-		sbsec->proc = 1;
+		sbsec->flags |= SE_SBPROC;
 
 	/* Determine the labeling behavior to use for this filesystem type. */
-	rc = security_fs_use(sbsec->proc ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
+	rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
 	if (rc) {
 		printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
 		       __func__, sb->s_type->name, rc);
@@ -806,10 +822,10 @@
 	}
 
 	/* how can we clone if the old one wasn't set up?? */
-	BUG_ON(!oldsbsec->initialized);
+	BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
 
 	/* if fs is reusing a sb, just let its options stand... */
-	if (newsbsec->initialized)
+	if (newsbsec->flags & SE_SBINITIALIZED)
 		return;
 
 	mutex_lock(&newsbsec->lock);
@@ -917,7 +933,8 @@
 				goto out_err;
 			}
 			break;
-
+		case Opt_labelsupport:
+			break;
 		default:
 			rc = -EINVAL;
 			printk(KERN_WARNING "SELinux:  unknown mount option\n");
@@ -999,7 +1016,12 @@
 	char *prefix;
 
 	for (i = 0; i < opts->num_mnt_opts; i++) {
-		char *has_comma = strchr(opts->mnt_opts[i], ',');
+		char *has_comma;
+
+		if (opts->mnt_opts[i])
+			has_comma = strchr(opts->mnt_opts[i], ',');
+		else
+			has_comma = NULL;
 
 		switch (opts->mnt_opts_flags[i]) {
 		case CONTEXT_MNT:
@@ -1014,6 +1036,10 @@
 		case DEFCONTEXT_MNT:
 			prefix = DEFCONTEXT_STR;
 			break;
+		case SE_SBLABELSUPP:
+			seq_putc(m, ',');
+			seq_puts(m, LABELSUPP_STR);
+			continue;
 		default:
 			BUG();
 		};
@@ -1209,7 +1235,7 @@
 		goto out_unlock;
 
 	sbsec = inode->i_sb->s_security;
-	if (!sbsec->initialized) {
+	if (!(sbsec->flags & SE_SBINITIALIZED)) {
 		/* Defer initialization until selinux_complete_init,
 		   after the initial policy is loaded and the security
 		   server is ready to handle calls. */
@@ -1237,19 +1263,26 @@
 			dentry = d_find_alias(inode);
 		}
 		if (!dentry) {
-			printk(KERN_WARNING "SELinux: %s:  no dentry for dev=%s "
-			       "ino=%ld\n", __func__, inode->i_sb->s_id,
-			       inode->i_ino);
+			/*
+			 * this is can be hit on boot when a file is accessed
+			 * before the policy is loaded.  When we load policy we
+			 * may find inodes that have no dentry on the
+			 * sbsec->isec_head list.  No reason to complain as these
+			 * will get fixed up the next time we go through
+			 * inode_doinit with a dentry, before these inodes could
+			 * be used again by userspace.
+			 */
 			goto out_unlock;
 		}
 
 		len = INITCONTEXTLEN;
-		context = kmalloc(len, GFP_NOFS);
+		context = kmalloc(len+1, GFP_NOFS);
 		if (!context) {
 			rc = -ENOMEM;
 			dput(dentry);
 			goto out_unlock;
 		}
+		context[len] = '\0';
 		rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
 					   context, len);
 		if (rc == -ERANGE) {
@@ -1262,12 +1295,13 @@
 			}
 			kfree(context);
 			len = rc;
-			context = kmalloc(len, GFP_NOFS);
+			context = kmalloc(len+1, GFP_NOFS);
 			if (!context) {
 				rc = -ENOMEM;
 				dput(dentry);
 				goto out_unlock;
 			}
+			context[len] = '\0';
 			rc = inode->i_op->getxattr(dentry,
 						   XATTR_NAME_SELINUX,
 						   context, len);
@@ -1289,10 +1323,19 @@
 							     sbsec->def_sid,
 							     GFP_NOFS);
 			if (rc) {
-				printk(KERN_WARNING "SELinux: %s:  context_to_sid(%s) "
-				       "returned %d for dev=%s ino=%ld\n",
-				       __func__, context, -rc,
-				       inode->i_sb->s_id, inode->i_ino);
+				char *dev = inode->i_sb->s_id;
+				unsigned long ino = inode->i_ino;
+
+				if (rc == -EINVAL) {
+					if (printk_ratelimit())
+						printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
+							"context=%s.  This indicates you may need to relabel the inode or the "
+							"filesystem in question.\n", ino, dev, context);
+				} else {
+					printk(KERN_WARNING "SELinux: %s:  context_to_sid(%s) "
+					       "returned %d for dev=%s ino=%ld\n",
+					       __func__, context, -rc, dev, ino);
+				}
 				kfree(context);
 				/* Leave with the unlabeled SID */
 				rc = 0;
@@ -1326,7 +1369,7 @@
 		/* Default to the fs superblock SID. */
 		isec->sid = sbsec->sid;
 
-		if (sbsec->proc && !S_ISLNK(inode->i_mode)) {
+		if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
 			struct proc_inode *proci = PROC_I(inode);
 			if (proci->pde) {
 				isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -1587,7 +1630,7 @@
 	if (rc)
 		return rc;
 
-	if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) {
+	if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
 		rc = security_transition_sid(sid, dsec->sid, tclass, &newsid);
 		if (rc)
 			return rc;
@@ -1801,6 +1844,8 @@
 			av |= FIFO_FILE__OPEN;
 		else if (S_ISDIR(mode))
 			av |= DIR__OPEN;
+		else if (S_ISSOCK(mode))
+			av |= SOCK_FILE__OPEN;
 		else
 			printk(KERN_ERR "SELinux: WARNING: inside %s with "
 				"unknown mode:%o\n", __func__, mode);
@@ -1815,7 +1860,7 @@
 {
 	int rc;
 
-	rc = secondary_ops->ptrace_may_access(child, mode);
+	rc = cap_ptrace_may_access(child, mode);
 	if (rc)
 		return rc;
 
@@ -1832,7 +1877,7 @@
 {
 	int rc;
 
-	rc = secondary_ops->ptrace_traceme(parent);
+	rc = cap_ptrace_traceme(parent);
 	if (rc)
 		return rc;
 
@@ -1848,7 +1893,7 @@
 	if (error)
 		return error;
 
-	return secondary_ops->capget(target, effective, inheritable, permitted);
+	return cap_capget(target, effective, inheritable, permitted);
 }
 
 static int selinux_capset(struct cred *new, const struct cred *old,
@@ -1858,7 +1903,7 @@
 {
 	int error;
 
-	error = secondary_ops->capset(new, old,
+	error = cap_capset(new, old,
 				      effective, inheritable, permitted);
 	if (error)
 		return error;
@@ -1866,12 +1911,22 @@
 	return cred_has_perm(old, new, PROCESS__SETCAP);
 }
 
+/*
+ * (This comment used to live with the selinux_task_setuid hook,
+ * which was removed).
+ *
+ * Since setuid only affects the current process, and since the SELinux
+ * controls are not based on the Linux identity attributes, SELinux does not
+ * need to control this operation.  However, SELinux does control the use of
+ * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
+ */
+
 static int selinux_capable(struct task_struct *tsk, const struct cred *cred,
 			   int cap, int audit)
 {
 	int rc;
 
-	rc = secondary_ops->capable(tsk, cred, cap, audit);
+	rc = cap_capable(tsk, cred, cap, audit);
 	if (rc)
 		return rc;
 
@@ -1997,7 +2052,7 @@
 {
 	int rc;
 
-	rc = secondary_ops->syslog(type);
+	rc = cap_syslog(type);
 	if (rc)
 		return rc;
 
@@ -2028,10 +2083,6 @@
  * mapping. 0 means there is enough memory for the allocation to
  * succeed and -ENOMEM implies there is not.
  *
- * Note that secondary_ops->capable and task_has_perm_noaudit return 0
- * if the capability is granted, but __vm_enough_memory requires 1 if
- * the capability is granted.
- *
  * Do not audit the selinux permission check, as this is applied to all
  * processes that allocate mappings.
  */
@@ -2058,7 +2109,7 @@
 	struct inode *inode = bprm->file->f_path.dentry->d_inode;
 	int rc;
 
-	rc = secondary_ops->bprm_set_creds(bprm);
+	rc = cap_bprm_set_creds(bprm);
 	if (rc)
 		return rc;
 
@@ -2156,11 +2207,6 @@
 	return 0;
 }
 
-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)
 {
 	const struct cred *cred = current_cred();
@@ -2180,7 +2226,7 @@
 					PROCESS__NOATSECURE, NULL);
 	}
 
-	return (atsecure || secondary_ops->bprm_secureexec(bprm));
+	return (atsecure || cap_bprm_secureexec(bprm));
 }
 
 extern struct vfsmount *selinuxfs_mount;
@@ -2290,8 +2336,6 @@
 	struct rlimit *rlim, *initrlim;
 	int rc, i;
 
-	secondary_ops->bprm_committing_creds(bprm);
-
 	new_tsec = bprm->cred->security;
 	if (new_tsec->sid == new_tsec->osid)
 		return;
@@ -2337,8 +2381,6 @@
 	int rc, i;
 	unsigned long flags;
 
-	secondary_ops->bprm_committed_creds(bprm);
-
 	osid = tsec->osid;
 	sid = tsec->sid;
 
@@ -2400,7 +2442,8 @@
 	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));
+		match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
+		match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
 }
 
 static inline void take_option(char **to, char *from, int *first, int len)
@@ -2513,11 +2556,6 @@
 			 void *data)
 {
 	const struct cred *cred = current_cred();
-	int rc;
-
-	rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
-	if (rc)
-		return rc;
 
 	if (flags & MS_REMOUNT)
 		return superblock_has_perm(cred, path->mnt->mnt_sb,
@@ -2530,11 +2568,6 @@
 static int selinux_umount(struct vfsmount *mnt, int flags)
 {
 	const struct cred *cred = current_cred();
-	int rc;
-
-	rc = secondary_ops->sb_umount(mnt, flags);
-	if (rc)
-		return rc;
 
 	return superblock_has_perm(cred, mnt->mnt_sb,
 				   FILESYSTEM__UNMOUNT, NULL);
@@ -2570,7 +2603,7 @@
 	sid = tsec->sid;
 	newsid = tsec->create_sid;
 
-	if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) {
+	if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
 		rc = security_transition_sid(sid, dsec->sid,
 					     inode_mode_to_security_class(inode->i_mode),
 					     &newsid);
@@ -2585,14 +2618,14 @@
 	}
 
 	/* Possibly defer initialization to selinux_complete_init. */
-	if (sbsec->initialized) {
+	if (sbsec->flags & SE_SBINITIALIZED) {
 		struct inode_security_struct *isec = inode->i_security;
 		isec->sclass = inode_mode_to_security_class(inode->i_mode);
 		isec->sid = newsid;
 		isec->initialized = 1;
 	}
 
-	if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
+	if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
 		return -EOPNOTSUPP;
 
 	if (name) {
@@ -2622,21 +2655,11 @@
 
 static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
 {
-	int rc;
-
-	rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
-	if (rc)
-		return rc;
 	return may_link(dir, old_dentry, MAY_LINK);
 }
 
 static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
 {
-	int rc;
-
-	rc = secondary_ops->inode_unlink(dir, dentry);
-	if (rc)
-		return rc;
 	return may_link(dir, dentry, MAY_UNLINK);
 }
 
@@ -2657,12 +2680,6 @@
 
 static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 {
-	int rc;
-
-	rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
-	if (rc)
-		return rc;
-
 	return may_create(dir, dentry, inode_mode_to_security_class(mode));
 }
 
@@ -2682,22 +2699,13 @@
 static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
 {
 	const struct cred *cred = current_cred();
-	int rc;
 
-	rc = secondary_ops->inode_follow_link(dentry, nameidata);
-	if (rc)
-		return rc;
 	return dentry_has_perm(cred, NULL, dentry, FILE__READ);
 }
 
 static int selinux_inode_permission(struct inode *inode, int mask)
 {
 	const struct cred *cred = current_cred();
-	int rc;
-
-	rc = secondary_ops->inode_permission(inode, mask);
-	if (rc)
-		return rc;
 
 	if (!mask) {
 		/* No permission to check.  Existence test. */
@@ -2711,11 +2719,6 @@
 static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 {
 	const struct cred *cred = current_cred();
-	int rc;
-
-	rc = secondary_ops->inode_setattr(dentry, iattr);
-	if (rc)
-		return rc;
 
 	if (iattr->ia_valid & ATTR_FORCE)
 		return 0;
@@ -2769,7 +2772,7 @@
 		return selinux_inode_setotherxattr(dentry, name);
 
 	sbsec = inode->i_sb->s_security;
-	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
+	if (!(sbsec->flags & SE_SBLABELSUPP))
 		return -EOPNOTSUPP;
 
 	if (!is_owner_or_cap(inode))
@@ -2931,16 +2934,6 @@
 	return len;
 }
 
-static int selinux_inode_need_killpriv(struct dentry *dentry)
-{
-	return secondary_ops->inode_need_killpriv(dentry);
-}
-
-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;
@@ -3078,18 +3071,13 @@
 				 unsigned long prot)
 {
 	const struct cred *cred = current_cred();
-	int rc;
-
-	rc = secondary_ops->file_mprotect(vma, reqprot, prot);
-	if (rc)
-		return rc;
 
 	if (selinux_checkreqprot)
 		prot = reqprot;
 
 #ifndef CONFIG_PPC32
 	if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
-		rc = 0;
+		int rc = 0;
 		if (vma->vm_start >= vma->vm_mm->start_brk &&
 		    vma->vm_end <= vma->vm_mm->brk) {
 			rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
@@ -3239,12 +3227,6 @@
 
 static int selinux_task_create(unsigned long clone_flags)
 {
-	int rc;
-
-	rc = secondary_ops->task_create(clone_flags);
-	if (rc)
-		return rc;
-
 	return current_has_perm(current, PROCESS__FORK);
 }
 
@@ -3278,14 +3260,6 @@
 }
 
 /*
- * commit new credentials
- */
-static void selinux_cred_commit(struct cred *new, const struct cred *old)
-{
-	secondary_ops->cred_commit(new, old);
-}
-
-/*
  * set the security data for a kernel service
  * - all the creation contexts are set to unlabelled
  */
@@ -3329,29 +3303,6 @@
 	return 0;
 }
 
-static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
-{
-	/* Since setuid only affects the current process, and
-	   since the SELinux controls are not based on the Linux
-	   identity attributes, SELinux does not need to control
-	   this operation.  However, SELinux does control the use
-	   of the CAP_SETUID and CAP_SETGID capabilities using the
-	   capable hook. */
-	return 0;
-}
-
-static int selinux_task_fix_setuid(struct cred *new, const struct cred *old,
-				   int flags)
-{
-	return secondary_ops->task_fix_setuid(new, old, flags);
-}
-
-static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
-{
-	/* See the comment for setuid above. */
-	return 0;
-}
-
 static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
 {
 	return current_has_perm(p, PROCESS__SETPGID);
@@ -3372,17 +3323,11 @@
 	*secid = task_sid(p);
 }
 
-static int selinux_task_setgroups(struct group_info *group_info)
-{
-	/* See the comment for setuid above. */
-	return 0;
-}
-
 static int selinux_task_setnice(struct task_struct *p, int nice)
 {
 	int rc;
 
-	rc = secondary_ops->task_setnice(p, nice);
+	rc = cap_task_setnice(p, nice);
 	if (rc)
 		return rc;
 
@@ -3393,7 +3338,7 @@
 {
 	int rc;
 
-	rc = secondary_ops->task_setioprio(p, ioprio);
+	rc = cap_task_setioprio(p, ioprio);
 	if (rc)
 		return rc;
 
@@ -3408,11 +3353,6 @@
 static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
 {
 	struct rlimit *old_rlim = current->signal->rlim + resource;
-	int rc;
-
-	rc = secondary_ops->task_setrlimit(resource, new_rlim);
-	if (rc)
-		return rc;
 
 	/* Control the ability to change the hard limit (whether
 	   lowering or raising it), so that the hard limit can
@@ -3428,7 +3368,7 @@
 {
 	int rc;
 
-	rc = secondary_ops->task_setscheduler(p, policy, lp);
+	rc = cap_task_setscheduler(p, policy, lp);
 	if (rc)
 		return rc;
 
@@ -3451,10 +3391,6 @@
 	u32 perm;
 	int rc;
 
-	rc = secondary_ops->task_kill(p, info, sig, secid);
-	if (rc)
-		return rc;
-
 	if (!sig)
 		perm = PROCESS__SIGNULL; /* null signal; existence test */
 	else
@@ -3467,18 +3403,6 @@
 	return rc;
 }
 
-static int selinux_task_prctl(int option,
-			      unsigned long arg2,
-			      unsigned long arg3,
-			      unsigned long arg4,
-			      unsigned long arg5)
-{
-	/* The current prctl operations do not appear to require
-	   any SELinux controls since they merely observe or modify
-	   the state of the current process. */
-	return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5);
-}
-
 static int selinux_task_wait(struct task_struct *p)
 {
 	return task_has_perm(p, current, PROCESS__SIGCHLD);
@@ -4047,10 +3971,6 @@
 	struct avc_audit_data ad;
 	int err;
 
-	err = secondary_ops->unix_stream_connect(sock, other, newsk);
-	if (err)
-		return err;
-
 	isec = SOCK_INODE(sock)->i_security;
 	other_isec = SOCK_INODE(other)->i_security;
 
@@ -4844,7 +4764,7 @@
 {
 	int err;
 
-	err = secondary_ops->netlink_send(sk, skb);
+	err = cap_netlink_send(sk, skb);
 	if (err)
 		return err;
 
@@ -4859,7 +4779,7 @@
 	int err;
 	struct avc_audit_data ad;
 
-	err = secondary_ops->netlink_recv(skb, capability);
+	err = cap_netlink_recv(skb, capability);
 	if (err)
 		return err;
 
@@ -5167,11 +5087,6 @@
 			     char __user *shmaddr, int shmflg)
 {
 	u32 perms;
-	int rc;
-
-	rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
-	if (rc)
-		return rc;
 
 	if (shmflg & SHM_RDONLY)
 		perms = SHM__READ;
@@ -5581,7 +5496,6 @@
 	.netlink_recv =			selinux_netlink_recv,
 
 	.bprm_set_creds =		selinux_bprm_set_creds,
-	.bprm_check_security =		selinux_bprm_check_security,
 	.bprm_committing_creds =	selinux_bprm_committing_creds,
 	.bprm_committed_creds =		selinux_bprm_committed_creds,
 	.bprm_secureexec =		selinux_bprm_secureexec,
@@ -5623,8 +5537,6 @@
 	.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,
@@ -5644,17 +5556,12 @@
 	.task_create =			selinux_task_create,
 	.cred_free =			selinux_cred_free,
 	.cred_prepare =			selinux_cred_prepare,
-	.cred_commit =			selinux_cred_commit,
 	.kernel_act_as =		selinux_kernel_act_as,
 	.kernel_create_files_as =	selinux_kernel_create_files_as,
-	.task_setuid =			selinux_task_setuid,
-	.task_fix_setuid =		selinux_task_fix_setuid,
-	.task_setgid =			selinux_task_setgid,
 	.task_setpgid =			selinux_task_setpgid,
 	.task_getpgid =			selinux_task_getpgid,
 	.task_getsid =			selinux_task_getsid,
 	.task_getsecid =		selinux_task_getsecid,
-	.task_setgroups =		selinux_task_setgroups,
 	.task_setnice =			selinux_task_setnice,
 	.task_setioprio =		selinux_task_setioprio,
 	.task_getioprio =		selinux_task_getioprio,
@@ -5664,7 +5571,6 @@
 	.task_movememory =		selinux_task_movememory,
 	.task_kill =			selinux_task_kill,
 	.task_wait =			selinux_task_wait,
-	.task_prctl =			selinux_task_prctl,
 	.task_to_inode =		selinux_task_to_inode,
 
 	.ipc_permission =		selinux_ipc_permission,
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index c0c8854..31df1d7 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -24,6 +24,7 @@
    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_SOCK_FILE, SOCK_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")
@@ -152,6 +153,7 @@
    S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write")
    S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_RELAY, "nlmsg_relay")
    S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv")
+   S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT, "nlmsg_tty_audit")
    S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read")
    S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write")
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 0ba79fe..d645192 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -174,6 +174,7 @@
 #define SOCK_FILE__SWAPON                         0x00004000UL
 #define SOCK_FILE__QUOTAON                        0x00008000UL
 #define SOCK_FILE__MOUNTON                        0x00010000UL
+#define SOCK_FILE__OPEN                           0x00020000UL
 #define FIFO_FILE__IOCTL                          0x00000001UL
 #define FIFO_FILE__READ                           0x00000002UL
 #define FIFO_FILE__WRITE                          0x00000004UL
@@ -707,6 +708,7 @@
 #define NETLINK_AUDIT_SOCKET__NLMSG_WRITE         0x00800000UL
 #define NETLINK_AUDIT_SOCKET__NLMSG_RELAY         0x01000000UL
 #define NETLINK_AUDIT_SOCKET__NLMSG_READPRIV      0x02000000UL
+#define NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT     0x04000000UL
 #define NETLINK_IP6FW_SOCKET__IOCTL               0x00000001UL
 #define NETLINK_IP6FW_SOCKET__READ                0x00000002UL
 #define NETLINK_IP6FW_SOCKET__WRITE               0x00000004UL
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 3cc4516..c4e0623 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -60,9 +60,7 @@
 	u32 def_sid;			/* default SID for labeling */
 	u32 mntpoint_sid;		/* SECURITY_FS_USE_MNTPOINT context for files */
 	unsigned int behavior;		/* labeling behavior */
-	unsigned char initialized;	/* initialization flag */
 	unsigned char flags;		/* which mount options were specified */
-	unsigned char proc;		/* proc fs */
 	struct mutex lock;
 	struct list_head isec_head;
 	spinlock_t isec_lock;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 7244737..5c3434f 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -37,15 +37,23 @@
 #define POLICYDB_VERSION_MAX	POLICYDB_VERSION_BOUNDARY
 #endif
 
+/* Mask for just the mount related flags */
+#define SE_MNTMASK	0x0f
+/* Super block security struct flags for mount options */
 #define CONTEXT_MNT	0x01
 #define FSCONTEXT_MNT	0x02
 #define ROOTCONTEXT_MNT	0x04
 #define DEFCONTEXT_MNT	0x08
+/* Non-mount related flags */
+#define SE_SBINITIALIZED	0x10
+#define SE_SBPROC		0x20
+#define SE_SBLABELSUPP	0x40
 
 #define CONTEXT_STR	"context="
 #define FSCONTEXT_STR	"fscontext="
 #define ROOTCONTEXT_STR	"rootcontext="
 #define DEFCONTEXT_STR	"defcontext="
+#define LABELSUPP_STR "seclabel"
 
 struct netlbl_lsm_secattr;
 
@@ -80,7 +88,6 @@
 #define SEL_VEC_MAX 32
 struct av_decision {
 	u32 allowed;
-	u32 decided;
 	u32 auditallow;
 	u32 auditdeny;
 	u32 seqno;
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 4ed7bab..c6875fd 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -113,7 +113,7 @@
 	{ AUDIT_USER,		NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
 	{ AUDIT_SIGNAL_INFO,	NETLINK_AUDIT_SOCKET__NLMSG_READ     },
 	{ AUDIT_TTY_GET,	NETLINK_AUDIT_SOCKET__NLMSG_READ     },
-	{ AUDIT_TTY_SET,	NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
+	{ AUDIT_TTY_SET,	NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT	},
 };
 
 
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 01ec6d2..d3c8b98 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -595,7 +595,7 @@
 
 	length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
 			  "%x %x %x %x %u",
-			  avd.allowed, avd.decided,
+			  avd.allowed, 0xffffffff,
 			  avd.auditallow, avd.auditdeny,
 			  avd.seqno);
 out2:
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index c65e4fe..deeec6c 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -407,7 +407,6 @@
 	 * Initialize the access vectors to the default values.
 	 */
 	avd->allowed = 0;
-	avd->decided = 0xffffffff;
 	avd->auditallow = 0;
 	avd->auditdeny = 0xffffffff;
 	avd->seqno = latest_granting;
@@ -743,7 +742,6 @@
 
 	if (!ss_initialized) {
 		avd->allowed = 0xffffffff;
-		avd->decided = 0xffffffff;
 		avd->auditallow = 0;
 		avd->auditdeny = 0xffffffff;
 		avd->seqno = latest_granting;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 2e0b83e..cfa19ca 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -162,8 +162,8 @@
 
 /**
  * smk_curacc - determine if current has a specific access to an object
- * @object_label: a pointer to the object's Smack label
- * @request: the access requested, in "MAY" format
+ * @obj_label: a pointer to the object's Smack label
+ * @mode: the access requested, in "MAY" format
  *
  * This function checks the current subject label/object label pair
  * in the access rule list and returns 0 if the access is permitted,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 0278bc0..84b62b5 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -91,6 +91,7 @@
 /**
  * smack_ptrace_may_access - Smack approval on PTRACE_ATTACH
  * @ctp: child task pointer
+ * @mode: ptrace attachment mode
  *
  * Returns 0 if access is OK, an error code otherwise
  *
@@ -203,9 +204,8 @@
 
 /**
  * smack_sb_copy_data - copy mount options data for processing
- * @type: file system type
  * @orig: where to start
- * @smackopts
+ * @smackopts: mount options string
  *
  * Returns 0 on success or -ENOMEM on error.
  *
@@ -331,7 +331,7 @@
 /**
  * smack_sb_mount - Smack check for mounting
  * @dev_name: unused
- * @nd: mount point
+ * @path: mount point
  * @type: unused
  * @flags: unused
  * @data: unused
@@ -370,7 +370,7 @@
 
 /**
  * smack_inode_alloc_security - allocate an inode blob
- * @inode - the inode in need of a blob
+ * @inode: the inode in need of a blob
  *
  * Returns 0 if it gets a blob, -ENOMEM otherwise
  */
@@ -384,7 +384,7 @@
 
 /**
  * smack_inode_free_security - free an inode blob
- * @inode - the inode with a blob
+ * @inode: the inode with a blob
  *
  * Clears the blob pointer in inode
  */
@@ -538,7 +538,6 @@
  * smack_inode_permission - Smack version of permission()
  * @inode: the inode in question
  * @mask: the access requested
- * @nd: unused
  *
  * This is the important Smack hook.
  *
@@ -701,8 +700,7 @@
  * @inode: the object
  * @name: attribute name
  * @buffer: where to put the result
- * @size: size of the buffer
- * @err: unused
+ * @alloc: unused
  *
  * Returns the size of the attribute or an error code
  */
@@ -864,7 +862,7 @@
 /**
  * smack_file_lock - Smack check on file locking
  * @file: the object
- * @cmd unused
+ * @cmd: unused
  *
  * Returns 0 if current has write access, error code otherwise
  */
@@ -1003,8 +1001,8 @@
 	return 0;
 }
 
-/*
- * commit new credentials
+/**
+ * smack_cred_commit - commit new credentials
  * @new: the new credentials
  * @old: the original credentials
  */
@@ -1014,8 +1012,8 @@
 
 /**
  * smack_kernel_act_as - Set the subjective context in a set of credentials
- * @new points to the set of credentials to be modified.
- * @secid specifies the security ID to be set
+ * @new: points to the set of credentials to be modified.
+ * @secid: specifies the security ID to be set
  *
  * Set the security data for a kernel service.
  */
@@ -1032,8 +1030,8 @@
 
 /**
  * smack_kernel_create_files_as - Set the file creation label in a set of creds
- * @new points to the set of credentials to be modified
- * @inode points to the inode to use as a reference
+ * @new: points to the set of credentials to be modified
+ * @inode: points to the inode to use as a reference
  *
  * Set the file creation context in a set of credentials to the same
  * as the objective context of the specified inode
@@ -1242,7 +1240,7 @@
 /**
  * smack_task_to_inode - copy task smack into the inode blob
  * @p: task to copy from
- * inode: inode to copy to
+ * @inode: inode to copy to
  *
  * Sets the smack pointer in the inode security blob
  */
@@ -1260,7 +1258,7 @@
  * smack_sk_alloc_security - Allocate a socket blob
  * @sk: the socket
  * @family: unused
- * @priority: memory allocation priority
+ * @gfp_flags: memory allocation flags
  *
  * Assign Smack pointers to current
  *
@@ -1498,58 +1496,31 @@
  * looks for host based access restrictions
  *
  * This version will only be appropriate for really small
- * sets of single label hosts. Because of the masking
- * it cannot shortcut out on the first match. There are
- * numerious ways to address the problem, but none of them
- * have been applied here.
+ * sets of single label hosts.
  *
  * Returns the label of the far end or NULL if it's not special.
  */
 static char *smack_host_label(struct sockaddr_in *sip)
 {
 	struct smk_netlbladdr *snp;
-	char *bestlabel = NULL;
 	struct in_addr *siap = &sip->sin_addr;
-	struct in_addr *liap;
-	struct in_addr *miap;
-	struct in_addr bestmask;
 
 	if (siap->s_addr == 0)
 		return NULL;
 
-	bestmask.s_addr = 0;
-
 	for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
-		liap = &snp->smk_host.sin_addr;
-		miap = &snp->smk_mask;
 		/*
-		 * If the addresses match after applying the list entry mask
-		 * the entry matches the address. If it doesn't move along to
-		 * the next entry.
+		 * we break after finding the first match because
+		 * the list is sorted from longest to shortest mask
+		 * so we have found the most specific match
 		 */
-		if ((liap->s_addr & miap->s_addr) !=
-		    (siap->s_addr & miap->s_addr))
-			continue;
-		/*
-		 * If the list entry mask identifies a single address
-		 * it can't get any more specific.
-		 */
-		if (miap->s_addr == 0xffffffff)
+		if ((&snp->smk_host.sin_addr)->s_addr  ==
+			(siap->s_addr & (&snp->smk_mask)->s_addr)) {
 			return snp->smk_label;
-		/*
-		 * If the list entry mask is less specific than the best
-		 * already found this entry is uninteresting.
-		 */
-		if ((miap->s_addr | bestmask.s_addr) == bestmask.s_addr)
-			continue;
-		/*
-		 * This is better than any entry found so far.
-		 */
-		bestmask.s_addr = miap->s_addr;
-		bestlabel = snp->smk_label;
+		}
 	}
 
-	return bestlabel;
+	return NULL;
 }
 
 /**
@@ -2001,7 +1972,7 @@
 
 /**
  * smack_ipc_getsecid - Extract smack security id
- * @ipcp: the object permissions
+ * @ipp: the object permissions
  * @secid: where result will be saved
  */
 static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
@@ -2278,7 +2249,7 @@
 /**
  * smack_socket_sendmsg - Smack check based on destination host
  * @sock: the socket
- * @msghdr: the message
+ * @msg: the message
  * @size: the size of the message
  *
  * Return 0 if the current subject can write to the destination
@@ -2319,8 +2290,7 @@
 
 
 /**
- * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat
- * 	pair to smack
+ * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack
  * @sap: netlabel secattr
  * @sip: where to put the result
  *
@@ -2441,7 +2411,7 @@
  * @sock: the socket
  * @optval: user's destination
  * @optlen: size thereof
- * @len: max thereoe
+ * @len: max thereof
  *
  * returns zero on success, an error code otherwise
  */
@@ -2776,7 +2746,7 @@
 
 #endif /* CONFIG_AUDIT */
 
-/*
+/**
  * smack_secid_to_secctx - return the smack label for a secid
  * @secid: incoming integer
  * @secdata: destination
@@ -2793,7 +2763,7 @@
 	return 0;
 }
 
-/*
+/**
  * smack_secctx_to_secid - return the secid for a smack label
  * @secdata: smack label
  * @seclen: how long result is
@@ -2807,11 +2777,10 @@
 	return 0;
 }
 
-/*
+/**
  * smack_release_secctx - don't do anything.
- * @key_ref: unused
- * @context: unused
- * @perm: unused
+ * @secdata: unused
+ * @seclen: unused
  *
  * Exists to make sure nothing gets done, and properly
  */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 8e42800..a1b57e4 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -245,7 +245,7 @@
 
 /**
  * smk_write_load - write() for /smack/load
- * @filp: file pointer, not actually used
+ * @file: file pointer, not actually used
  * @buf: where to get the data from
  * @count: bytes sent
  * @ppos: where to start - must be 0
@@ -402,6 +402,7 @@
 
 /**
  * smk_unlbl_ambient - initialize the unlabeled domain
+ * @oldambient: previous domain string
  */
 static void smk_unlbl_ambient(char *oldambient)
 {
@@ -513,7 +514,7 @@
 
 /**
  * smk_write_cipso - write() for /smack/cipso
- * @filp: file pointer, not actually used
+ * @file: file pointer, not actually used
  * @buf: where to get the data from
  * @count: bytes sent
  * @ppos: where to start
@@ -650,10 +651,6 @@
 
 	return skp;
 }
-/*
-#define BEMASK	0x80000000
-*/
-#define BEMASK	0x00000001
 #define BEBITS	(sizeof(__be32) * 8)
 
 /*
@@ -663,12 +660,10 @@
 {
 	struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
 	unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
-	__be32 bebits;
-	int maskn = 0;
+	int maskn;
+	u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
 
-	for (bebits = BEMASK; bebits != 0; maskn++, bebits <<= 1)
-		if ((skp->smk_mask.s_addr & bebits) == 0)
-			break;
+	for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
 
 	seq_printf(s, "%u.%u.%u.%u/%d %s\n",
 		hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
@@ -702,8 +697,44 @@
 }
 
 /**
+ * smk_netlbladdr_insert
+ * @new : netlabel to insert
+ *
+ * This helper insert netlabel in the smack_netlbladdrs list
+ * sorted by netmask length (longest to smallest)
+ */
+static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
+{
+	struct smk_netlbladdr *m;
+
+	if (smack_netlbladdrs == NULL) {
+		smack_netlbladdrs = new;
+		return;
+	}
+
+	/* the comparison '>' is a bit hacky, but works */
+	if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) {
+		new->smk_next = smack_netlbladdrs;
+		smack_netlbladdrs = new;
+		return;
+	}
+	for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) {
+		if (m->smk_next == NULL) {
+			m->smk_next = new;
+			return;
+		}
+		if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) {
+			new->smk_next = m->smk_next;
+			m->smk_next = new;
+			return;
+		}
+	}
+}
+
+
+/**
  * smk_write_netlbladdr - write() for /smack/netlabel
- * @filp: file pointer, not actually used
+ * @file: file pointer, not actually used
  * @buf: where to get the data from
  * @count: bytes sent
  * @ppos: where to start
@@ -724,8 +755,9 @@
 	struct netlbl_audit audit_info;
 	struct in_addr mask;
 	unsigned int m;
-	__be32 bebits = BEMASK;
+	u32 mask_bits = (1<<31);
 	__be32 nsa;
+	u32 temp_mask;
 
 	/*
 	 * Must have privilege.
@@ -761,10 +793,13 @@
 	if (sp == NULL)
 		return -EINVAL;
 
-	for (mask.s_addr = 0; m > 0; m--) {
-		mask.s_addr |= bebits;
-		bebits <<= 1;
+	for (temp_mask = 0; m > 0; m--) {
+		temp_mask |= mask_bits;
+		mask_bits >>= 1;
 	}
+	mask.s_addr = cpu_to_be32(temp_mask);
+
+	newname.sin_addr.s_addr &= mask.s_addr;
 	/*
 	 * Only allow one writer at a time. Writes should be
 	 * quite rare and small in any case.
@@ -772,6 +807,7 @@
 	mutex_lock(&smk_netlbladdr_lock);
 
 	nsa = newname.sin_addr.s_addr;
+	/* try to find if the prefix is already in the list */
 	for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
 		if (skp->smk_host.sin_addr.s_addr == nsa &&
 		    skp->smk_mask.s_addr == mask.s_addr)
@@ -787,9 +823,8 @@
 			rc = 0;
 			skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
 			skp->smk_mask.s_addr = mask.s_addr;
-			skp->smk_next = smack_netlbladdrs;
 			skp->smk_label = sp;
-			smack_netlbladdrs = skp;
+			smk_netlbladdr_insert(skp);
 		}
 	} else {
 		rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
@@ -850,7 +885,7 @@
 
 /**
  * smk_write_doi - write() for /smack/doi
- * @filp: file pointer, not actually used
+ * @file: file pointer, not actually used
  * @buf: where to get the data from
  * @count: bytes sent
  * @ppos: where to start
@@ -915,7 +950,7 @@
 
 /**
  * smk_write_direct - write() for /smack/direct
- * @filp: file pointer, not actually used
+ * @file: file pointer, not actually used
  * @buf: where to get the data from
  * @count: bytes sent
  * @ppos: where to start
@@ -990,7 +1025,7 @@
 
 /**
  * smk_write_ambient - write() for /smack/ambient
- * @filp: file pointer, not actually used
+ * @file: file pointer, not actually used
  * @buf: where to get the data from
  * @count: bytes sent
  * @ppos: where to start
@@ -1065,7 +1100,7 @@
 
 /**
  * smk_write_onlycap - write() for /smack/onlycap
- * @filp: file pointer, not actually used
+ * @file: file pointer, not actually used
  * @buf: where to get the data from
  * @count: bytes sent
  * @ppos: where to start
diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig
new file mode 100644
index 0000000..c8f3857
--- /dev/null
+++ b/security/tomoyo/Kconfig
@@ -0,0 +1,11 @@
+config SECURITY_TOMOYO
+	bool "TOMOYO Linux Support"
+	depends on SECURITY
+	select SECURITYFS
+	select SECURITY_PATH
+	default n
+	help
+	  This selects TOMOYO Linux, pathname-based access control.
+	  Required userspace tools and further information may be
+	  found at <http://tomoyo.sourceforge.jp/>.
+	  If you are unsure how to answer this question, answer N.
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
new file mode 100644
index 0000000..10ccd68
--- /dev/null
+++ b/security/tomoyo/Makefile
@@ -0,0 +1 @@
+obj-y = common.o realpath.o tomoyo.o domain.o file.o
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
new file mode 100644
index 0000000..92cea65
--- /dev/null
+++ b/security/tomoyo/common.c
@@ -0,0 +1,2206 @@
+/*
+ * security/tomoyo/common.c
+ *
+ * Common functions for TOMOYO.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#include <linux/uaccess.h>
+#include <linux/security.h>
+#include <linux/hardirq.h>
+#include "realpath.h"
+#include "common.h"
+#include "tomoyo.h"
+
+/* Has loading policy done? */
+bool tomoyo_policy_loaded;
+
+/* String table for functionality that takes 4 modes. */
+static const char *tomoyo_mode_4[4] = {
+	"disabled", "learning", "permissive", "enforcing"
+};
+/* String table for functionality that takes 2 modes. */
+static const char *tomoyo_mode_2[4] = {
+	"disabled", "enabled", "enabled", "enabled"
+};
+
+/* Table for profile. */
+static struct {
+	const char *keyword;
+	unsigned int current_value;
+	const unsigned int max_value;
+} tomoyo_control_array[TOMOYO_MAX_CONTROL_INDEX] = {
+	[TOMOYO_MAC_FOR_FILE]     = { "MAC_FOR_FILE",        0,       3 },
+	[TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", 2048, INT_MAX },
+	[TOMOYO_VERBOSE]          = { "TOMOYO_VERBOSE",      1,       1 },
+};
+
+/* Profile table. Memory is allocated as needed. */
+static struct tomoyo_profile {
+	unsigned int value[TOMOYO_MAX_CONTROL_INDEX];
+	const struct tomoyo_path_info *comment;
+} *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
+
+/* Permit policy management by non-root user? */
+static bool tomoyo_manage_by_non_root;
+
+/* Utility functions. */
+
+/* Open operation for /sys/kernel/security/tomoyo/ interface. */
+static int tomoyo_open_control(const u8 type, struct file *file);
+/* Close /sys/kernel/security/tomoyo/ interface. */
+static int tomoyo_close_control(struct file *file);
+/* Read operation for /sys/kernel/security/tomoyo/ interface. */
+static int tomoyo_read_control(struct file *file, char __user *buffer,
+			       const int buffer_len);
+/* Write operation for /sys/kernel/security/tomoyo/ interface. */
+static int tomoyo_write_control(struct file *file, const char __user *buffer,
+				const int buffer_len);
+
+/**
+ * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value.
+ *
+ * @str: Pointer to the string.
+ *
+ * Returns true if @str is a \ooo style octal value, false otherwise.
+ *
+ * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
+ * This function verifies that \ooo is in valid range.
+ */
+static inline bool tomoyo_is_byte_range(const char *str)
+{
+	return *str >= '0' && *str++ <= '3' &&
+		*str >= '0' && *str++ <= '7' &&
+		*str >= '0' && *str <= '7';
+}
+
+/**
+ * tomoyo_is_alphabet_char - Check whether the character is an alphabet.
+ *
+ * @c: The character to check.
+ *
+ * Returns true if @c is an alphabet character, false otherwise.
+ */
+static inline bool tomoyo_is_alphabet_char(const char c)
+{
+	return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+}
+
+/**
+ * tomoyo_make_byte - Make byte value from three octal characters.
+ *
+ * @c1: The first character.
+ * @c2: The second character.
+ * @c3: The third character.
+ *
+ * Returns byte value.
+ */
+static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
+{
+	return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
+}
+
+/**
+ * tomoyo_str_starts - Check whether the given string starts with the given keyword.
+ *
+ * @src:  Pointer to pointer to the string.
+ * @find: Pointer to the keyword.
+ *
+ * Returns true if @src starts with @find, false otherwise.
+ *
+ * The @src is updated to point the first character after the @find
+ * if @src starts with @find.
+ */
+static bool tomoyo_str_starts(char **src, const char *find)
+{
+	const int len = strlen(find);
+	char *tmp = *src;
+
+	if (strncmp(tmp, find, len))
+		return false;
+	tmp += len;
+	*src = tmp;
+	return true;
+}
+
+/**
+ * tomoyo_normalize_line - Format string.
+ *
+ * @buffer: The line to normalize.
+ *
+ * Leading and trailing whitespaces are removed.
+ * Multiple whitespaces are packed into single space.
+ *
+ * Returns nothing.
+ */
+static void tomoyo_normalize_line(unsigned char *buffer)
+{
+	unsigned char *sp = buffer;
+	unsigned char *dp = buffer;
+	bool first = true;
+
+	while (tomoyo_is_invalid(*sp))
+		sp++;
+	while (*sp) {
+		if (!first)
+			*dp++ = ' ';
+		first = false;
+		while (tomoyo_is_valid(*sp))
+			*dp++ = *sp++;
+		while (tomoyo_is_invalid(*sp))
+			sp++;
+	}
+	*dp = '\0';
+}
+
+/**
+ * tomoyo_is_correct_path - Validate a pathname.
+ * @filename:     The pathname to check.
+ * @start_type:   Should the pathname start with '/'?
+ *                1 = must / -1 = must not / 0 = don't care
+ * @pattern_type: Can the pathname contain a wildcard?
+ *                1 = must / -1 = must not / 0 = don't care
+ * @end_type:     Should the pathname end with '/'?
+ *                1 = must / -1 = must not / 0 = don't care
+ * @function:     The name of function calling me.
+ *
+ * Check whether the given filename follows the naming rules.
+ * Returns true if @filename follows the naming rules, false otherwise.
+ */
+bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
+			    const s8 pattern_type, const s8 end_type,
+			    const char *function)
+{
+	bool contains_pattern = false;
+	unsigned char c;
+	unsigned char d;
+	unsigned char e;
+	const char *original_filename = filename;
+
+	if (!filename)
+		goto out;
+	c = *filename;
+	if (start_type == 1) { /* Must start with '/' */
+		if (c != '/')
+			goto out;
+	} else if (start_type == -1) { /* Must not start with '/' */
+		if (c == '/')
+			goto out;
+	}
+	if (c)
+		c = *(filename + strlen(filename) - 1);
+	if (end_type == 1) { /* Must end with '/' */
+		if (c != '/')
+			goto out;
+	} else if (end_type == -1) { /* Must not end with '/' */
+		if (c == '/')
+			goto out;
+	}
+	while ((c = *filename++) != '\0') {
+		if (c == '\\') {
+			switch ((c = *filename++)) {
+			case '\\':  /* "\\" */
+				continue;
+			case '$':   /* "\$" */
+			case '+':   /* "\+" */
+			case '?':   /* "\?" */
+			case '*':   /* "\*" */
+			case '@':   /* "\@" */
+			case 'x':   /* "\x" */
+			case 'X':   /* "\X" */
+			case 'a':   /* "\a" */
+			case 'A':   /* "\A" */
+			case '-':   /* "\-" */
+				if (pattern_type == -1)
+					break; /* Must not contain pattern */
+				contains_pattern = true;
+				continue;
+			case '0':   /* "\ooo" */
+			case '1':
+			case '2':
+			case '3':
+				d = *filename++;
+				if (d < '0' || d > '7')
+					break;
+				e = *filename++;
+				if (e < '0' || e > '7')
+					break;
+				c = tomoyo_make_byte(c, d, e);
+				if (tomoyo_is_invalid(c))
+					continue; /* pattern is not \000 */
+			}
+			goto out;
+		} else if (tomoyo_is_invalid(c)) {
+			goto out;
+		}
+	}
+	if (pattern_type == 1) { /* Must contain pattern */
+		if (!contains_pattern)
+			goto out;
+	}
+	return true;
+ out:
+	printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
+	       original_filename);
+	return false;
+}
+
+/**
+ * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
+ * @domainname:   The domainname to check.
+ * @function:     The name of function calling me.
+ *
+ * Returns true if @domainname follows the naming rules, false otherwise.
+ */
+bool tomoyo_is_correct_domain(const unsigned char *domainname,
+			      const char *function)
+{
+	unsigned char c;
+	unsigned char d;
+	unsigned char e;
+	const char *org_domainname = domainname;
+
+	if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
+				   TOMOYO_ROOT_NAME_LEN))
+		goto out;
+	domainname += TOMOYO_ROOT_NAME_LEN;
+	if (!*domainname)
+		return true;
+	do {
+		if (*domainname++ != ' ')
+			goto out;
+		if (*domainname++ != '/')
+			goto out;
+		while ((c = *domainname) != '\0' && c != ' ') {
+			domainname++;
+			if (c == '\\') {
+				c = *domainname++;
+				switch ((c)) {
+				case '\\':  /* "\\" */
+					continue;
+				case '0':   /* "\ooo" */
+				case '1':
+				case '2':
+				case '3':
+					d = *domainname++;
+					if (d < '0' || d > '7')
+						break;
+					e = *domainname++;
+					if (e < '0' || e > '7')
+						break;
+					c = tomoyo_make_byte(c, d, e);
+					if (tomoyo_is_invalid(c))
+						/* pattern is not \000 */
+						continue;
+				}
+				goto out;
+			} else if (tomoyo_is_invalid(c)) {
+				goto out;
+			}
+		}
+	} while (*domainname);
+	return true;
+ out:
+	printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function,
+	       org_domainname);
+	return false;
+}
+
+/**
+ * tomoyo_is_domain_def - Check whether the given token can be a domainname.
+ *
+ * @buffer: The token to check.
+ *
+ * Returns true if @buffer possibly be a domainname, false otherwise.
+ */
+bool tomoyo_is_domain_def(const unsigned char *buffer)
+{
+	return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN);
+}
+
+/**
+ * tomoyo_find_domain - Find a domain by the given name.
+ *
+ * @domainname: The domainname to find.
+ *
+ * Caller must call down_read(&tomoyo_domain_list_lock); or
+ * down_write(&tomoyo_domain_list_lock); .
+ *
+ * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
+ */
+struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
+{
+	struct tomoyo_domain_info *domain;
+	struct tomoyo_path_info name;
+
+	name.name = domainname;
+	tomoyo_fill_path_info(&name);
+	list_for_each_entry(domain, &tomoyo_domain_list, list) {
+		if (!domain->is_deleted &&
+		    !tomoyo_pathcmp(&name, domain->domainname))
+			return domain;
+	}
+	return NULL;
+}
+
+/**
+ * tomoyo_path_depth - Evaluate the number of '/' in a string.
+ *
+ * @pathname: The string to evaluate.
+ *
+ * Returns path depth of the string.
+ *
+ * I score 2 for each of the '/' in the @pathname
+ * and score 1 if the @pathname ends with '/'.
+ */
+static int tomoyo_path_depth(const char *pathname)
+{
+	int i = 0;
+
+	if (pathname) {
+		const char *ep = pathname + strlen(pathname);
+		if (pathname < ep--) {
+			if (*ep != '/')
+				i++;
+			while (pathname <= ep)
+				if (*ep-- == '/')
+					i += 2;
+		}
+	}
+	return i;
+}
+
+/**
+ * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
+ *
+ * @filename: The string to evaluate.
+ *
+ * Returns the initial length without a pattern in @filename.
+ */
+static int tomoyo_const_part_length(const char *filename)
+{
+	char c;
+	int len = 0;
+
+	if (!filename)
+		return 0;
+	while ((c = *filename++) != '\0') {
+		if (c != '\\') {
+			len++;
+			continue;
+		}
+		c = *filename++;
+		switch (c) {
+		case '\\':  /* "\\" */
+			len += 2;
+			continue;
+		case '0':   /* "\ooo" */
+		case '1':
+		case '2':
+		case '3':
+			c = *filename++;
+			if (c < '0' || c > '7')
+				break;
+			c = *filename++;
+			if (c < '0' || c > '7')
+				break;
+			len += 4;
+			continue;
+		}
+		break;
+	}
+	return len;
+}
+
+/**
+ * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members.
+ *
+ * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
+ *
+ * The caller sets "struct tomoyo_path_info"->name.
+ */
+void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
+{
+	const char *name = ptr->name;
+	const int len = strlen(name);
+
+	ptr->total_len = len;
+	ptr->const_len = tomoyo_const_part_length(name);
+	ptr->is_dir = len && (name[len - 1] == '/');
+	ptr->is_patterned = (ptr->const_len < len);
+	ptr->hash = full_name_hash(name, len);
+	ptr->depth = tomoyo_path_depth(name);
+}
+
+/**
+ * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character
+ * and "\-" pattern.
+ *
+ * @filename:     The start of string to check.
+ * @filename_end: The end of string to check.
+ * @pattern:      The start of pattern to compare.
+ * @pattern_end:  The end of pattern to compare.
+ *
+ * Returns true if @filename matches @pattern, false otherwise.
+ */
+static bool tomoyo_file_matches_to_pattern2(const char *filename,
+					    const char *filename_end,
+					    const char *pattern,
+					    const char *pattern_end)
+{
+	while (filename < filename_end && pattern < pattern_end) {
+		char c;
+		if (*pattern != '\\') {
+			if (*filename++ != *pattern++)
+				return false;
+			continue;
+		}
+		c = *filename;
+		pattern++;
+		switch (*pattern) {
+			int i;
+			int j;
+		case '?':
+			if (c == '/') {
+				return false;
+			} else if (c == '\\') {
+				if (filename[1] == '\\')
+					filename++;
+				else if (tomoyo_is_byte_range(filename + 1))
+					filename += 3;
+				else
+					return false;
+			}
+			break;
+		case '\\':
+			if (c != '\\')
+				return false;
+			if (*++filename != '\\')
+				return false;
+			break;
+		case '+':
+			if (!isdigit(c))
+				return false;
+			break;
+		case 'x':
+			if (!isxdigit(c))
+				return false;
+			break;
+		case 'a':
+			if (!tomoyo_is_alphabet_char(c))
+				return false;
+			break;
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+			if (c == '\\' && tomoyo_is_byte_range(filename + 1)
+			    && strncmp(filename + 1, pattern, 3) == 0) {
+				filename += 3;
+				pattern += 2;
+				break;
+			}
+			return false; /* Not matched. */
+		case '*':
+		case '@':
+			for (i = 0; i <= filename_end - filename; i++) {
+				if (tomoyo_file_matches_to_pattern2(
+						    filename + i, filename_end,
+						    pattern + 1, pattern_end))
+					return true;
+				c = filename[i];
+				if (c == '.' && *pattern == '@')
+					break;
+				if (c != '\\')
+					continue;
+				if (filename[i + 1] == '\\')
+					i++;
+				else if (tomoyo_is_byte_range(filename + i + 1))
+					i += 3;
+				else
+					break; /* Bad pattern. */
+			}
+			return false; /* Not matched. */
+		default:
+			j = 0;
+			c = *pattern;
+			if (c == '$') {
+				while (isdigit(filename[j]))
+					j++;
+			} else if (c == 'X') {
+				while (isxdigit(filename[j]))
+					j++;
+			} else if (c == 'A') {
+				while (tomoyo_is_alphabet_char(filename[j]))
+					j++;
+			}
+			for (i = 1; i <= j; i++) {
+				if (tomoyo_file_matches_to_pattern2(
+						    filename + i, filename_end,
+						    pattern + 1, pattern_end))
+					return true;
+			}
+			return false; /* Not matched or bad pattern. */
+		}
+		filename++;
+		pattern++;
+	}
+	while (*pattern == '\\' &&
+	       (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
+		pattern += 2;
+	return filename == filename_end && pattern == pattern_end;
+}
+
+/**
+ * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character.
+ *
+ * @filename:     The start of string to check.
+ * @filename_end: The end of string to check.
+ * @pattern:      The start of pattern to compare.
+ * @pattern_end:  The end of pattern to compare.
+ *
+ * Returns true if @filename matches @pattern, false otherwise.
+ */
+static bool tomoyo_file_matches_to_pattern(const char *filename,
+					   const char *filename_end,
+					   const char *pattern,
+					   const char *pattern_end)
+{
+	const char *pattern_start = pattern;
+	bool first = true;
+	bool result;
+
+	while (pattern < pattern_end - 1) {
+		/* Split at "\-" pattern. */
+		if (*pattern++ != '\\' || *pattern++ != '-')
+			continue;
+		result = tomoyo_file_matches_to_pattern2(filename,
+							 filename_end,
+							 pattern_start,
+							 pattern - 2);
+		if (first)
+			result = !result;
+		if (result)
+			return false;
+		first = false;
+		pattern_start = pattern;
+	}
+	result = tomoyo_file_matches_to_pattern2(filename, filename_end,
+						 pattern_start, pattern_end);
+	return first ? result : !result;
+}
+
+/**
+ * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
+ * @filename: The filename to check.
+ * @pattern:  The pattern to compare.
+ *
+ * Returns true if matches, false otherwise.
+ *
+ * The following patterns are available.
+ *   \\     \ itself.
+ *   \ooo   Octal representation of a byte.
+ *   \*     More than or equals to 0 character other than '/'.
+ *   \@     More than or equals to 0 character other than '/' or '.'.
+ *   \?     1 byte character other than '/'.
+ *   \$     More than or equals to 1 decimal digit.
+ *   \+     1 decimal digit.
+ *   \X     More than or equals to 1 hexadecimal digit.
+ *   \x     1 hexadecimal digit.
+ *   \A     More than or equals to 1 alphabet character.
+ *   \a     1 alphabet character.
+ *   \-     Subtraction operator.
+ */
+bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
+				 const struct tomoyo_path_info *pattern)
+{
+	/*
+	  if (!filename || !pattern)
+	  return false;
+	*/
+	const char *f = filename->name;
+	const char *p = pattern->name;
+	const int len = pattern->const_len;
+
+	/* If @pattern doesn't contain pattern, I can use strcmp(). */
+	if (!pattern->is_patterned)
+		return !tomoyo_pathcmp(filename, pattern);
+	/* Dont compare if the number of '/' differs. */
+	if (filename->depth != pattern->depth)
+		return false;
+	/* Compare the initial length without patterns. */
+	if (strncmp(f, p, len))
+		return false;
+	f += len;
+	p += len;
+	/* Main loop. Compare each directory component. */
+	while (*f && *p) {
+		const char *f_delimiter = strchr(f, '/');
+		const char *p_delimiter = strchr(p, '/');
+		if (!f_delimiter)
+			f_delimiter = f + strlen(f);
+		if (!p_delimiter)
+			p_delimiter = p + strlen(p);
+		if (!tomoyo_file_matches_to_pattern(f, f_delimiter,
+						    p, p_delimiter))
+			return false;
+		f = f_delimiter;
+		if (*f)
+			f++;
+		p = p_delimiter;
+		if (*p)
+			p++;
+	}
+	/* Ignore trailing "\*" and "\@" in @pattern. */
+	while (*p == '\\' &&
+	       (*(p + 1) == '*' || *(p + 1) == '@'))
+		p += 2;
+	return !*f && !*p;
+}
+
+/**
+ * tomoyo_io_printf - Transactional printf() to "struct tomoyo_io_buffer" structure.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @fmt:  The printf()'s format string, followed by parameters.
+ *
+ * Returns true if output was written, false otherwise.
+ *
+ * The snprintf() will truncate, but tomoyo_io_printf() won't.
+ */
+bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
+{
+	va_list args;
+	int len;
+	int pos = head->read_avail;
+	int size = head->readbuf_size - pos;
+
+	if (size <= 0)
+		return false;
+	va_start(args, fmt);
+	len = vsnprintf(head->read_buf + pos, size, fmt, args);
+	va_end(args);
+	if (pos + len >= head->readbuf_size)
+		return false;
+	head->read_avail += len;
+	return true;
+}
+
+/**
+ * tomoyo_get_exe - Get tomoyo_realpath() of current process.
+ *
+ * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
+ *
+ * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
+ * if this function didn't return NULL.
+ */
+static const char *tomoyo_get_exe(void)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	const char *cp = NULL;
+
+	if (!mm)
+		return NULL;
+	down_read(&mm->mmap_sem);
+	for (vma = mm->mmap; vma; vma = vma->vm_next) {
+		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
+			cp = tomoyo_realpath_from_path(&vma->vm_file->f_path);
+			break;
+		}
+	}
+	up_read(&mm->mmap_sem);
+	return cp;
+}
+
+/**
+ * tomoyo_get_msg - Get warning message.
+ *
+ * @is_enforce: Is it enforcing mode?
+ *
+ * Returns "ERROR" or "WARNING".
+ */
+const char *tomoyo_get_msg(const bool is_enforce)
+{
+	if (is_enforce)
+		return "ERROR";
+	else
+		return "WARNING";
+}
+
+/**
+ * tomoyo_check_flags - Check mode for specified functionality.
+ *
+ * @domain: Pointer to "struct tomoyo_domain_info".
+ * @index:  The functionality to check mode.
+ *
+ * TOMOYO checks only process context.
+ * This code disables TOMOYO's enforcement in case the function is called from
+ * interrupt context.
+ */
+unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
+				const u8 index)
+{
+	const u8 profile = domain->profile;
+
+	if (WARN_ON(in_interrupt()))
+		return 0;
+	return tomoyo_policy_loaded && index < TOMOYO_MAX_CONTROL_INDEX
+#if TOMOYO_MAX_PROFILES != 256
+		&& profile < TOMOYO_MAX_PROFILES
+#endif
+		&& tomoyo_profile_ptr[profile] ?
+		tomoyo_profile_ptr[profile]->value[index] : 0;
+}
+
+/**
+ * tomoyo_verbose_mode - Check whether TOMOYO is verbose mode.
+ *
+ * @domain: Pointer to "struct tomoyo_domain_info".
+ *
+ * Returns true if domain policy violation warning should be printed to
+ * console.
+ */
+bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
+{
+	return tomoyo_check_flags(domain, TOMOYO_VERBOSE) != 0;
+}
+
+/**
+ * tomoyo_domain_quota_is_ok - Check for domain's quota.
+ *
+ * @domain: Pointer to "struct tomoyo_domain_info".
+ *
+ * Returns true if the domain is not exceeded quota, false otherwise.
+ */
+bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
+{
+	unsigned int count = 0;
+	struct tomoyo_acl_info *ptr;
+
+	if (!domain)
+		return true;
+	down_read(&tomoyo_domain_acl_info_list_lock);
+	list_for_each_entry(ptr, &domain->acl_info_list, list) {
+		if (ptr->type & TOMOYO_ACL_DELETED)
+			continue;
+		switch (tomoyo_acl_type2(ptr)) {
+			struct tomoyo_single_path_acl_record *acl1;
+			struct tomoyo_double_path_acl_record *acl2;
+			u16 perm;
+		case TOMOYO_TYPE_SINGLE_PATH_ACL:
+			acl1 = container_of(ptr,
+				    struct tomoyo_single_path_acl_record,
+					    head);
+			perm = acl1->perm;
+			if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL))
+				count++;
+			if (perm &
+			    ((1 << TOMOYO_TYPE_READ_ACL) |
+			     (1 << TOMOYO_TYPE_WRITE_ACL)))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_CREATE_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_UNLINK_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_MKDIR_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_RMDIR_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_MKFIFO_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_MKSOCK_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_MKBLOCK_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_MKCHAR_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_TRUNCATE_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_SYMLINK_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_REWRITE_ACL))
+				count++;
+			break;
+		case TOMOYO_TYPE_DOUBLE_PATH_ACL:
+			acl2 = container_of(ptr,
+				    struct tomoyo_double_path_acl_record,
+					    head);
+			perm = acl2->perm;
+			if (perm & (1 << TOMOYO_TYPE_LINK_ACL))
+				count++;
+			if (perm & (1 << TOMOYO_TYPE_RENAME_ACL))
+				count++;
+			break;
+		}
+	}
+	up_read(&tomoyo_domain_acl_info_list_lock);
+	if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
+		return true;
+	if (!domain->quota_warned) {
+		domain->quota_warned = true;
+		printk(KERN_WARNING "TOMOYO-WARNING: "
+		       "Domain '%s' has so many ACLs to hold. "
+		       "Stopped learning mode.\n", domain->domainname->name);
+	}
+	return false;
+}
+
+/**
+ * tomoyo_find_or_assign_new_profile - Create a new profile.
+ *
+ * @profile: Profile number to create.
+ *
+ * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise.
+ */
+static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
+								int profile)
+{
+	static DEFINE_MUTEX(lock);
+	struct tomoyo_profile *ptr = NULL;
+	int i;
+
+	if (profile >= TOMOYO_MAX_PROFILES)
+		return NULL;
+	/***** EXCLUSIVE SECTION START *****/
+	mutex_lock(&lock);
+	ptr = tomoyo_profile_ptr[profile];
+	if (ptr)
+		goto ok;
+	ptr = tomoyo_alloc_element(sizeof(*ptr));
+	if (!ptr)
+		goto ok;
+	for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
+		ptr->value[i] = tomoyo_control_array[i].current_value;
+	mb(); /* Avoid out-of-order execution. */
+	tomoyo_profile_ptr[profile] = ptr;
+ ok:
+	mutex_unlock(&lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return ptr;
+}
+
+/**
+ * tomoyo_write_profile - Write to profile table.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
+{
+	char *data = head->write_buf;
+	unsigned int i;
+	unsigned int value;
+	char *cp;
+	struct tomoyo_profile *profile;
+	unsigned long num;
+
+	cp = strchr(data, '-');
+	if (cp)
+		*cp = '\0';
+	if (strict_strtoul(data, 10, &num))
+		return -EINVAL;
+	if (cp)
+		data = cp + 1;
+	profile = tomoyo_find_or_assign_new_profile(num);
+	if (!profile)
+		return -EINVAL;
+	cp = strchr(data, '=');
+	if (!cp)
+		return -EINVAL;
+	*cp = '\0';
+	if (!strcmp(data, "COMMENT")) {
+		profile->comment = tomoyo_save_name(cp + 1);
+		return 0;
+	}
+	for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
+		if (strcmp(data, tomoyo_control_array[i].keyword))
+			continue;
+		if (sscanf(cp + 1, "%u", &value) != 1) {
+			int j;
+			const char **modes;
+			switch (i) {
+			case TOMOYO_VERBOSE:
+				modes = tomoyo_mode_2;
+				break;
+			default:
+				modes = tomoyo_mode_4;
+				break;
+			}
+			for (j = 0; j < 4; j++) {
+				if (strcmp(cp + 1, modes[j]))
+					continue;
+				value = j;
+				break;
+			}
+			if (j == 4)
+				return -EINVAL;
+		} else if (value > tomoyo_control_array[i].max_value) {
+			value = tomoyo_control_array[i].max_value;
+		}
+		profile->value[i] = value;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+/**
+ * tomoyo_read_profile - Read from profile table.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0.
+ */
+static int tomoyo_read_profile(struct tomoyo_io_buffer *head)
+{
+	static const int total = TOMOYO_MAX_CONTROL_INDEX + 1;
+	int step;
+
+	if (head->read_eof)
+		return 0;
+	for (step = head->read_step; step < TOMOYO_MAX_PROFILES * total;
+	     step++) {
+		const u8 index = step / total;
+		u8 type = step % total;
+		const struct tomoyo_profile *profile
+			= tomoyo_profile_ptr[index];
+		head->read_step = step;
+		if (!profile)
+			continue;
+		if (!type) { /* Print profile' comment tag. */
+			if (!tomoyo_io_printf(head, "%u-COMMENT=%s\n",
+					      index, profile->comment ?
+					      profile->comment->name : ""))
+				break;
+			continue;
+		}
+		type--;
+		if (type < TOMOYO_MAX_CONTROL_INDEX) {
+			const unsigned int value = profile->value[type];
+			const char **modes = NULL;
+			const char *keyword
+				= tomoyo_control_array[type].keyword;
+			switch (tomoyo_control_array[type].max_value) {
+			case 3:
+				modes = tomoyo_mode_4;
+				break;
+			case 1:
+				modes = tomoyo_mode_2;
+				break;
+			}
+			if (modes) {
+				if (!tomoyo_io_printf(head, "%u-%s=%s\n", index,
+						      keyword, modes[value]))
+					break;
+			} else {
+				if (!tomoyo_io_printf(head, "%u-%s=%u\n", index,
+						      keyword, value))
+					break;
+			}
+		}
+	}
+	if (step == TOMOYO_MAX_PROFILES * total)
+		head->read_eof = true;
+	return 0;
+}
+
+/* Structure for policy manager. */
+struct tomoyo_policy_manager_entry {
+	struct list_head list;
+	/* A path to program or a domainname. */
+	const struct tomoyo_path_info *manager;
+	bool is_domain;  /* True if manager is a domainname. */
+	bool is_deleted; /* True if this entry is deleted. */
+};
+
+/* The list for "struct tomoyo_policy_manager_entry". */
+static LIST_HEAD(tomoyo_policy_manager_list);
+static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
+
+/**
+ * tomoyo_update_manager_entry - Add a manager entry.
+ *
+ * @manager:   The path to manager or the domainnamme.
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_update_manager_entry(const char *manager,
+				       const bool is_delete)
+{
+	struct tomoyo_policy_manager_entry *new_entry;
+	struct tomoyo_policy_manager_entry *ptr;
+	const struct tomoyo_path_info *saved_manager;
+	int error = -ENOMEM;
+	bool is_domain = false;
+
+	if (tomoyo_is_domain_def(manager)) {
+		if (!tomoyo_is_correct_domain(manager, __func__))
+			return -EINVAL;
+		is_domain = true;
+	} else {
+		if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__))
+			return -EINVAL;
+	}
+	saved_manager = tomoyo_save_name(manager);
+	if (!saved_manager)
+		return -ENOMEM;
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_policy_manager_list_lock);
+	list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
+		if (ptr->manager != saved_manager)
+			continue;
+		ptr->is_deleted = is_delete;
+		error = 0;
+		goto out;
+	}
+	if (is_delete) {
+		error = -ENOENT;
+		goto out;
+	}
+	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
+	if (!new_entry)
+		goto out;
+	new_entry->manager = saved_manager;
+	new_entry->is_domain = is_domain;
+	list_add_tail(&new_entry->list, &tomoyo_policy_manager_list);
+	error = 0;
+ out:
+	up_write(&tomoyo_policy_manager_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return error;
+}
+
+/**
+ * tomoyo_write_manager_policy - Write manager policy.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
+{
+	char *data = head->write_buf;
+	bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
+
+	if (!strcmp(data, "manage_by_non_root")) {
+		tomoyo_manage_by_non_root = !is_delete;
+		return 0;
+	}
+	return tomoyo_update_manager_entry(data, is_delete);
+}
+
+/**
+ * tomoyo_read_manager_policy - Read manager policy.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0.
+ */
+static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
+{
+	struct list_head *pos;
+	bool done = true;
+
+	if (head->read_eof)
+		return 0;
+	down_read(&tomoyo_policy_manager_list_lock);
+	list_for_each_cookie(pos, head->read_var2,
+			     &tomoyo_policy_manager_list) {
+		struct tomoyo_policy_manager_entry *ptr;
+		ptr = list_entry(pos, struct tomoyo_policy_manager_entry,
+				 list);
+		if (ptr->is_deleted)
+			continue;
+		if (!tomoyo_io_printf(head, "%s\n", ptr->manager->name)) {
+			done = false;
+			break;
+		}
+	}
+	up_read(&tomoyo_policy_manager_list_lock);
+	head->read_eof = done;
+	return 0;
+}
+
+/**
+ * tomoyo_is_policy_manager - Check whether the current process is a policy manager.
+ *
+ * Returns true if the current process is permitted to modify policy
+ * via /sys/kernel/security/tomoyo/ interface.
+ */
+static bool tomoyo_is_policy_manager(void)
+{
+	struct tomoyo_policy_manager_entry *ptr;
+	const char *exe;
+	const struct task_struct *task = current;
+	const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname;
+	bool found = false;
+
+	if (!tomoyo_policy_loaded)
+		return true;
+	if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
+		return false;
+	down_read(&tomoyo_policy_manager_list_lock);
+	list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
+		if (!ptr->is_deleted && ptr->is_domain
+		    && !tomoyo_pathcmp(domainname, ptr->manager)) {
+			found = true;
+			break;
+		}
+	}
+	up_read(&tomoyo_policy_manager_list_lock);
+	if (found)
+		return true;
+	exe = tomoyo_get_exe();
+	if (!exe)
+		return false;
+	down_read(&tomoyo_policy_manager_list_lock);
+	list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
+		if (!ptr->is_deleted && !ptr->is_domain
+		    && !strcmp(exe, ptr->manager->name)) {
+			found = true;
+			break;
+		}
+	}
+	up_read(&tomoyo_policy_manager_list_lock);
+	if (!found) { /* Reduce error messages. */
+		static pid_t last_pid;
+		const pid_t pid = current->pid;
+		if (last_pid != pid) {
+			printk(KERN_WARNING "%s ( %s ) is not permitted to "
+			       "update policies.\n", domainname->name, exe);
+			last_pid = pid;
+		}
+	}
+	tomoyo_free(exe);
+	return found;
+}
+
+/**
+ * tomoyo_is_select_one - Parse select command.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @data: String to parse.
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
+				 const char *data)
+{
+	unsigned int pid;
+	struct tomoyo_domain_info *domain = NULL;
+
+	if (sscanf(data, "pid=%u", &pid) == 1) {
+		struct task_struct *p;
+		/***** CRITICAL SECTION START *****/
+		read_lock(&tasklist_lock);
+		p = find_task_by_vpid(pid);
+		if (p)
+			domain = tomoyo_real_domain(p);
+		read_unlock(&tasklist_lock);
+		/***** CRITICAL SECTION END *****/
+	} else if (!strncmp(data, "domain=", 7)) {
+		if (tomoyo_is_domain_def(data + 7)) {
+			down_read(&tomoyo_domain_list_lock);
+			domain = tomoyo_find_domain(data + 7);
+			up_read(&tomoyo_domain_list_lock);
+		}
+	} else
+		return false;
+	head->write_var1 = domain;
+	/* Accessing read_buf is safe because head->io_sem is held. */
+	if (!head->read_buf)
+		return true; /* Do nothing if open(O_WRONLY). */
+	head->read_avail = 0;
+	tomoyo_io_printf(head, "# select %s\n", data);
+	head->read_single_domain = true;
+	head->read_eof = !domain;
+	if (domain) {
+		struct tomoyo_domain_info *d;
+		head->read_var1 = NULL;
+		down_read(&tomoyo_domain_list_lock);
+		list_for_each_entry(d, &tomoyo_domain_list, list) {
+			if (d == domain)
+				break;
+			head->read_var1 = &d->list;
+		}
+		up_read(&tomoyo_domain_list_lock);
+		head->read_var2 = NULL;
+		head->read_bit = 0;
+		head->read_step = 0;
+		if (domain->is_deleted)
+			tomoyo_io_printf(head, "# This is a deleted domain.\n");
+	}
+	return true;
+}
+
+/**
+ * tomoyo_write_domain_policy - Write domain policy.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
+{
+	char *data = head->write_buf;
+	struct tomoyo_domain_info *domain = head->write_var1;
+	bool is_delete = false;
+	bool is_select = false;
+	bool is_undelete = false;
+	unsigned int profile;
+
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE))
+		is_delete = true;
+	else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_SELECT))
+		is_select = true;
+	else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_UNDELETE))
+		is_undelete = true;
+	if (is_select && tomoyo_is_select_one(head, data))
+		return 0;
+	/* Don't allow updating policies by non manager programs. */
+	if (!tomoyo_is_policy_manager())
+		return -EPERM;
+	if (tomoyo_is_domain_def(data)) {
+		domain = NULL;
+		if (is_delete)
+			tomoyo_delete_domain(data);
+		else if (is_select) {
+			down_read(&tomoyo_domain_list_lock);
+			domain = tomoyo_find_domain(data);
+			up_read(&tomoyo_domain_list_lock);
+		} else if (is_undelete)
+			domain = tomoyo_undelete_domain(data);
+		else
+			domain = tomoyo_find_or_assign_new_domain(data, 0);
+		head->write_var1 = domain;
+		return 0;
+	}
+	if (!domain)
+		return -EINVAL;
+
+	if (sscanf(data, TOMOYO_KEYWORD_USE_PROFILE "%u", &profile) == 1
+	    && profile < TOMOYO_MAX_PROFILES) {
+		if (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded)
+			domain->profile = (u8) profile;
+		return 0;
+	}
+	if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
+		tomoyo_set_domain_flag(domain, is_delete,
+			       TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
+		return 0;
+	}
+	return tomoyo_write_file_policy(data, domain, is_delete);
+}
+
+/**
+ * tomoyo_print_single_path_acl - Print a single path ACL entry.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @ptr:  Pointer to "struct tomoyo_single_path_acl_record".
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head,
+					 struct tomoyo_single_path_acl_record *
+					 ptr)
+{
+	int pos;
+	u8 bit;
+	const char *atmark = "";
+	const char *filename;
+	const u16 perm = ptr->perm;
+
+	filename = ptr->filename->name;
+	for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION;
+	     bit++) {
+		const char *msg;
+		if (!(perm & (1 << bit)))
+			continue;
+		/* Print "read/write" instead of "read" and "write". */
+		if ((bit == TOMOYO_TYPE_READ_ACL ||
+		     bit == TOMOYO_TYPE_WRITE_ACL)
+		    && (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
+			continue;
+		msg = tomoyo_sp2keyword(bit);
+		pos = head->read_avail;
+		if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg,
+				      atmark, filename))
+			goto out;
+	}
+	head->read_bit = 0;
+	return true;
+ out:
+	head->read_bit = bit;
+	head->read_avail = pos;
+	return false;
+}
+
+/**
+ * tomoyo_print_double_path_acl - Print a double path ACL entry.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @ptr:  Pointer to "struct tomoyo_double_path_acl_record".
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
+					 struct tomoyo_double_path_acl_record *
+					 ptr)
+{
+	int pos;
+	const char *atmark1 = "";
+	const char *atmark2 = "";
+	const char *filename1;
+	const char *filename2;
+	const u8 perm = ptr->perm;
+	u8 bit;
+
+	filename1 = ptr->filename1->name;
+	filename2 = ptr->filename2->name;
+	for (bit = head->read_bit; bit < TOMOYO_MAX_DOUBLE_PATH_OPERATION;
+	     bit++) {
+		const char *msg;
+		if (!(perm & (1 << bit)))
+			continue;
+		msg = tomoyo_dp2keyword(bit);
+		pos = head->read_avail;
+		if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg,
+				      atmark1, filename1, atmark2, filename2))
+			goto out;
+	}
+	head->read_bit = 0;
+	return true;
+ out:
+	head->read_bit = bit;
+	head->read_avail = pos;
+	return false;
+}
+
+/**
+ * tomoyo_print_entry - Print an ACL entry.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @ptr:  Pointer to an ACL entry.
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
+			       struct tomoyo_acl_info *ptr)
+{
+	const u8 acl_type = tomoyo_acl_type2(ptr);
+
+	if (acl_type & TOMOYO_ACL_DELETED)
+		return true;
+	if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) {
+		struct tomoyo_single_path_acl_record *acl
+			= container_of(ptr,
+				       struct tomoyo_single_path_acl_record,
+				       head);
+		return tomoyo_print_single_path_acl(head, acl);
+	}
+	if (acl_type == TOMOYO_TYPE_DOUBLE_PATH_ACL) {
+		struct tomoyo_double_path_acl_record *acl
+			= container_of(ptr,
+				       struct tomoyo_double_path_acl_record,
+				       head);
+		return tomoyo_print_double_path_acl(head, acl);
+	}
+	BUG(); /* This must not happen. */
+	return false;
+}
+
+/**
+ * tomoyo_read_domain_policy - Read domain policy.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0.
+ */
+static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
+{
+	struct list_head *dpos;
+	struct list_head *apos;
+	bool done = true;
+
+	if (head->read_eof)
+		return 0;
+	if (head->read_step == 0)
+		head->read_step = 1;
+	down_read(&tomoyo_domain_list_lock);
+	list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
+		struct tomoyo_domain_info *domain;
+		const char *quota_exceeded = "";
+		const char *transition_failed = "";
+		const char *ignore_global_allow_read = "";
+		domain = list_entry(dpos, struct tomoyo_domain_info, list);
+		if (head->read_step != 1)
+			goto acl_loop;
+		if (domain->is_deleted && !head->read_single_domain)
+			continue;
+		/* Print domainname and flags. */
+		if (domain->quota_warned)
+			quota_exceeded = "quota_exceeded\n";
+		if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED)
+			transition_failed = "transition_failed\n";
+		if (domain->flags &
+		    TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
+			ignore_global_allow_read
+				= TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
+		if (!tomoyo_io_printf(head,
+				      "%s\n" TOMOYO_KEYWORD_USE_PROFILE "%u\n"
+				      "%s%s%s\n", domain->domainname->name,
+				      domain->profile, quota_exceeded,
+				      transition_failed,
+				      ignore_global_allow_read)) {
+			done = false;
+			break;
+		}
+		head->read_step = 2;
+acl_loop:
+		if (head->read_step == 3)
+			goto tail_mark;
+		/* Print ACL entries in the domain. */
+		down_read(&tomoyo_domain_acl_info_list_lock);
+		list_for_each_cookie(apos, head->read_var2,
+				      &domain->acl_info_list) {
+			struct tomoyo_acl_info *ptr
+				= list_entry(apos, struct tomoyo_acl_info,
+					      list);
+			if (!tomoyo_print_entry(head, ptr)) {
+				done = false;
+				break;
+			}
+		}
+		up_read(&tomoyo_domain_acl_info_list_lock);
+		if (!done)
+			break;
+		head->read_step = 3;
+tail_mark:
+		if (!tomoyo_io_printf(head, "\n")) {
+			done = false;
+			break;
+		}
+		head->read_step = 1;
+		if (head->read_single_domain)
+			break;
+	}
+	up_read(&tomoyo_domain_list_lock);
+	head->read_eof = done;
+	return 0;
+}
+
+/**
+ * tomoyo_write_domain_profile - Assign profile for specified domain.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0 on success, -EINVAL otherwise.
+ *
+ * This is equivalent to doing
+ *
+ *     ( echo "select " $domainname; echo "use_profile " $profile ) |
+ *     /usr/lib/ccs/loadpolicy -d
+ */
+static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
+{
+	char *data = head->write_buf;
+	char *cp = strchr(data, ' ');
+	struct tomoyo_domain_info *domain;
+	unsigned long profile;
+
+	if (!cp)
+		return -EINVAL;
+	*cp = '\0';
+	down_read(&tomoyo_domain_list_lock);
+	domain = tomoyo_find_domain(cp + 1);
+	up_read(&tomoyo_domain_list_lock);
+	if (strict_strtoul(data, 10, &profile))
+		return -EINVAL;
+	if (domain && profile < TOMOYO_MAX_PROFILES
+	    && (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded))
+		domain->profile = (u8) profile;
+	return 0;
+}
+
+/**
+ * tomoyo_read_domain_profile - Read only domainname and profile.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns list of profile number and domainname pairs.
+ *
+ * This is equivalent to doing
+ *
+ *     grep -A 1 '^<kernel>' /sys/kernel/security/tomoyo/domain_policy |
+ *     awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
+ *     domainname = $0; } else if ( $1 == "use_profile" ) {
+ *     print $2 " " domainname; domainname = ""; } } ; '
+ */
+static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
+{
+	struct list_head *pos;
+	bool done = true;
+
+	if (head->read_eof)
+		return 0;
+	down_read(&tomoyo_domain_list_lock);
+	list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
+		struct tomoyo_domain_info *domain;
+		domain = list_entry(pos, struct tomoyo_domain_info, list);
+		if (domain->is_deleted)
+			continue;
+		if (!tomoyo_io_printf(head, "%u %s\n", domain->profile,
+				      domain->domainname->name)) {
+			done = false;
+			break;
+		}
+	}
+	up_read(&tomoyo_domain_list_lock);
+	head->read_eof = done;
+	return 0;
+}
+
+/**
+ * tomoyo_write_pid: Specify PID to obtain domainname.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0.
+ */
+static int tomoyo_write_pid(struct tomoyo_io_buffer *head)
+{
+	unsigned long pid;
+	/* No error check. */
+	strict_strtoul(head->write_buf, 10, &pid);
+	head->read_step = (int) pid;
+	head->read_eof = false;
+	return 0;
+}
+
+/**
+ * tomoyo_read_pid - Get domainname of the specified PID.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns the domainname which the specified PID is in on success,
+ * empty string otherwise.
+ * The PID is specified by tomoyo_write_pid() so that the user can obtain
+ * using read()/write() interface rather than sysctl() interface.
+ */
+static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
+{
+	if (head->read_avail == 0 && !head->read_eof) {
+		const int pid = head->read_step;
+		struct task_struct *p;
+		struct tomoyo_domain_info *domain = NULL;
+		/***** CRITICAL SECTION START *****/
+		read_lock(&tasklist_lock);
+		p = find_task_by_vpid(pid);
+		if (p)
+			domain = tomoyo_real_domain(p);
+		read_unlock(&tasklist_lock);
+		/***** CRITICAL SECTION END *****/
+		if (domain)
+			tomoyo_io_printf(head, "%d %u %s", pid, domain->profile,
+					 domain->domainname->name);
+		head->read_eof = true;
+	}
+	return 0;
+}
+
+/**
+ * tomoyo_write_exception_policy - Write exception policy.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
+{
+	char *data = head->write_buf;
+	bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
+
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_KEEP_DOMAIN))
+		return tomoyo_write_domain_keeper_policy(data, false,
+							 is_delete);
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_KEEP_DOMAIN))
+		return tomoyo_write_domain_keeper_policy(data, true, is_delete);
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_INITIALIZE_DOMAIN))
+		return tomoyo_write_domain_initializer_policy(data, false,
+							      is_delete);
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN))
+		return tomoyo_write_domain_initializer_policy(data, true,
+							      is_delete);
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALIAS))
+		return tomoyo_write_alias_policy(data, is_delete);
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_READ))
+		return tomoyo_write_globally_readable_policy(data, is_delete);
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_FILE_PATTERN))
+		return tomoyo_write_pattern_policy(data, is_delete);
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE))
+		return tomoyo_write_no_rewrite_policy(data, is_delete);
+	return -EINVAL;
+}
+
+/**
+ * tomoyo_read_exception_policy - Read exception policy.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0 on success, -EINVAL otherwise.
+ */
+static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
+{
+	if (!head->read_eof) {
+		switch (head->read_step) {
+		case 0:
+			head->read_var2 = NULL;
+			head->read_step = 1;
+		case 1:
+			if (!tomoyo_read_domain_keeper_policy(head))
+				break;
+			head->read_var2 = NULL;
+			head->read_step = 2;
+		case 2:
+			if (!tomoyo_read_globally_readable_policy(head))
+				break;
+			head->read_var2 = NULL;
+			head->read_step = 3;
+		case 3:
+			head->read_var2 = NULL;
+			head->read_step = 4;
+		case 4:
+			if (!tomoyo_read_domain_initializer_policy(head))
+				break;
+			head->read_var2 = NULL;
+			head->read_step = 5;
+		case 5:
+			if (!tomoyo_read_alias_policy(head))
+				break;
+			head->read_var2 = NULL;
+			head->read_step = 6;
+		case 6:
+			head->read_var2 = NULL;
+			head->read_step = 7;
+		case 7:
+			if (!tomoyo_read_file_pattern(head))
+				break;
+			head->read_var2 = NULL;
+			head->read_step = 8;
+		case 8:
+			if (!tomoyo_read_no_rewrite_policy(head))
+				break;
+			head->read_var2 = NULL;
+			head->read_step = 9;
+		case 9:
+			head->read_eof = true;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+/* path to policy loader */
+static const char *tomoyo_loader = "/sbin/tomoyo-init";
+
+/**
+ * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists.
+ *
+ * Returns true if /sbin/tomoyo-init exists, false otherwise.
+ */
+static bool tomoyo_policy_loader_exists(void)
+{
+	/*
+	 * Don't activate MAC if the policy loader doesn't exist.
+	 * If the initrd includes /sbin/init but real-root-dev has not
+	 * mounted on / yet, activating MAC will block the system since
+	 * policies are not loaded yet.
+	 * Thus, let do_execve() call this function everytime.
+	 */
+	struct nameidata nd;
+
+	if (path_lookup(tomoyo_loader, LOOKUP_FOLLOW, &nd)) {
+		printk(KERN_INFO "Not activating Mandatory Access Control now "
+		       "since %s doesn't exist.\n", tomoyo_loader);
+		return false;
+	}
+	path_put(&nd.path);
+	return true;
+}
+
+/**
+ * tomoyo_load_policy - Run external policy loader to load policy.
+ *
+ * @filename: The program about to start.
+ *
+ * This function checks whether @filename is /sbin/init , and if so
+ * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init
+ * and then continues invocation of /sbin/init.
+ * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and
+ * writes to /sys/kernel/security/tomoyo/ interfaces.
+ *
+ * Returns nothing.
+ */
+void tomoyo_load_policy(const char *filename)
+{
+	char *argv[2];
+	char *envp[3];
+
+	if (tomoyo_policy_loaded)
+		return;
+	/*
+	 * Check filename is /sbin/init or /sbin/tomoyo-start.
+	 * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't
+	 * be passed.
+	 * You can create /sbin/tomoyo-start by
+	 * "ln -s /bin/true /sbin/tomoyo-start".
+	 */
+	if (strcmp(filename, "/sbin/init") &&
+	    strcmp(filename, "/sbin/tomoyo-start"))
+		return;
+	if (!tomoyo_policy_loader_exists())
+		return;
+
+	printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
+	       tomoyo_loader);
+	argv[0] = (char *) tomoyo_loader;
+	argv[1] = NULL;
+	envp[0] = "HOME=/";
+	envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+	envp[2] = NULL;
+	call_usermodehelper(argv[0], argv, envp, 1);
+
+	printk(KERN_INFO "TOMOYO: 2.2.0-pre   2009/02/01\n");
+	printk(KERN_INFO "Mandatory Access Control activated.\n");
+	tomoyo_policy_loaded = true;
+	{ /* Check all profiles currently assigned to domains are defined. */
+		struct tomoyo_domain_info *domain;
+		down_read(&tomoyo_domain_list_lock);
+		list_for_each_entry(domain, &tomoyo_domain_list, list) {
+			const u8 profile = domain->profile;
+			if (tomoyo_profile_ptr[profile])
+				continue;
+			panic("Profile %u (used by '%s') not defined.\n",
+			      profile, domain->domainname->name);
+		}
+		up_read(&tomoyo_domain_list_lock);
+	}
+}
+
+/**
+ * tomoyo_read_version: Get version.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns version information.
+ */
+static int tomoyo_read_version(struct tomoyo_io_buffer *head)
+{
+	if (!head->read_eof) {
+		tomoyo_io_printf(head, "2.2.0-pre");
+		head->read_eof = true;
+	}
+	return 0;
+}
+
+/**
+ * tomoyo_read_self_domain - Get the current process's domainname.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns the current process's domainname.
+ */
+static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
+{
+	if (!head->read_eof) {
+		/*
+		 * tomoyo_domain()->domainname != NULL
+		 * because every process belongs to a domain and
+		 * the domain's name cannot be NULL.
+		 */
+		tomoyo_io_printf(head, "%s", tomoyo_domain()->domainname->name);
+		head->read_eof = true;
+	}
+	return 0;
+}
+
+/**
+ * tomoyo_open_control - open() for /sys/kernel/security/tomoyo/ interface.
+ *
+ * @type: Type of interface.
+ * @file: Pointer to "struct file".
+ *
+ * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
+ */
+static int tomoyo_open_control(const u8 type, struct file *file)
+{
+	struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head));
+
+	if (!head)
+		return -ENOMEM;
+	mutex_init(&head->io_sem);
+	switch (type) {
+	case TOMOYO_DOMAINPOLICY:
+		/* /sys/kernel/security/tomoyo/domain_policy */
+		head->write = tomoyo_write_domain_policy;
+		head->read = tomoyo_read_domain_policy;
+		break;
+	case TOMOYO_EXCEPTIONPOLICY:
+		/* /sys/kernel/security/tomoyo/exception_policy */
+		head->write = tomoyo_write_exception_policy;
+		head->read = tomoyo_read_exception_policy;
+		break;
+	case TOMOYO_SELFDOMAIN:
+		/* /sys/kernel/security/tomoyo/self_domain */
+		head->read = tomoyo_read_self_domain;
+		break;
+	case TOMOYO_DOMAIN_STATUS:
+		/* /sys/kernel/security/tomoyo/.domain_status */
+		head->write = tomoyo_write_domain_profile;
+		head->read = tomoyo_read_domain_profile;
+		break;
+	case TOMOYO_PROCESS_STATUS:
+		/* /sys/kernel/security/tomoyo/.process_status */
+		head->write = tomoyo_write_pid;
+		head->read = tomoyo_read_pid;
+		break;
+	case TOMOYO_VERSION:
+		/* /sys/kernel/security/tomoyo/version */
+		head->read = tomoyo_read_version;
+		head->readbuf_size = 128;
+		break;
+	case TOMOYO_MEMINFO:
+		/* /sys/kernel/security/tomoyo/meminfo */
+		head->write = tomoyo_write_memory_quota;
+		head->read = tomoyo_read_memory_counter;
+		head->readbuf_size = 512;
+		break;
+	case TOMOYO_PROFILE:
+		/* /sys/kernel/security/tomoyo/profile */
+		head->write = tomoyo_write_profile;
+		head->read = tomoyo_read_profile;
+		break;
+	case TOMOYO_MANAGER:
+		/* /sys/kernel/security/tomoyo/manager */
+		head->write = tomoyo_write_manager_policy;
+		head->read = tomoyo_read_manager_policy;
+		break;
+	}
+	if (!(file->f_mode & FMODE_READ)) {
+		/*
+		 * No need to allocate read_buf since it is not opened
+		 * for reading.
+		 */
+		head->read = NULL;
+	} else {
+		if (!head->readbuf_size)
+			head->readbuf_size = 4096 * 2;
+		head->read_buf = tomoyo_alloc(head->readbuf_size);
+		if (!head->read_buf) {
+			tomoyo_free(head);
+			return -ENOMEM;
+		}
+	}
+	if (!(file->f_mode & FMODE_WRITE)) {
+		/*
+		 * No need to allocate write_buf since it is not opened
+		 * for writing.
+		 */
+		head->write = NULL;
+	} else if (head->write) {
+		head->writebuf_size = 4096 * 2;
+		head->write_buf = tomoyo_alloc(head->writebuf_size);
+		if (!head->write_buf) {
+			tomoyo_free(head->read_buf);
+			tomoyo_free(head);
+			return -ENOMEM;
+		}
+	}
+	file->private_data = head;
+	/*
+	 * Call the handler now if the file is
+	 * /sys/kernel/security/tomoyo/self_domain
+	 * so that the user can use
+	 * cat < /sys/kernel/security/tomoyo/self_domain"
+	 * to know the current process's domainname.
+	 */
+	if (type == TOMOYO_SELFDOMAIN)
+		tomoyo_read_control(file, NULL, 0);
+	return 0;
+}
+
+/**
+ * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
+ *
+ * @file:       Pointer to "struct file".
+ * @buffer:     Poiner to buffer to write to.
+ * @buffer_len: Size of @buffer.
+ *
+ * Returns bytes read on success, negative value otherwise.
+ */
+static int tomoyo_read_control(struct file *file, char __user *buffer,
+			       const int buffer_len)
+{
+	int len = 0;
+	struct tomoyo_io_buffer *head = file->private_data;
+	char *cp;
+
+	if (!head->read)
+		return -ENOSYS;
+	if (mutex_lock_interruptible(&head->io_sem))
+		return -EINTR;
+	/* Call the policy handler. */
+	len = head->read(head);
+	if (len < 0)
+		goto out;
+	/* Write to buffer. */
+	len = head->read_avail;
+	if (len > buffer_len)
+		len = buffer_len;
+	if (!len)
+		goto out;
+	/* head->read_buf changes by some functions. */
+	cp = head->read_buf;
+	if (copy_to_user(buffer, cp, len)) {
+		len = -EFAULT;
+		goto out;
+	}
+	head->read_avail -= len;
+	memmove(cp, cp + len, head->read_avail);
+ out:
+	mutex_unlock(&head->io_sem);
+	return len;
+}
+
+/**
+ * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface.
+ *
+ * @file:       Pointer to "struct file".
+ * @buffer:     Pointer to buffer to read from.
+ * @buffer_len: Size of @buffer.
+ *
+ * Returns @buffer_len on success, negative value otherwise.
+ */
+static int tomoyo_write_control(struct file *file, const char __user *buffer,
+				const int buffer_len)
+{
+	struct tomoyo_io_buffer *head = file->private_data;
+	int error = buffer_len;
+	int avail_len = buffer_len;
+	char *cp0 = head->write_buf;
+
+	if (!head->write)
+		return -ENOSYS;
+	if (!access_ok(VERIFY_READ, buffer, buffer_len))
+		return -EFAULT;
+	/* Don't allow updating policies by non manager programs. */
+	if (head->write != tomoyo_write_pid &&
+	    head->write != tomoyo_write_domain_policy &&
+	    !tomoyo_is_policy_manager())
+		return -EPERM;
+	if (mutex_lock_interruptible(&head->io_sem))
+		return -EINTR;
+	/* Read a line and dispatch it to the policy handler. */
+	while (avail_len > 0) {
+		char c;
+		if (head->write_avail >= head->writebuf_size - 1) {
+			error = -ENOMEM;
+			break;
+		} else if (get_user(c, buffer)) {
+			error = -EFAULT;
+			break;
+		}
+		buffer++;
+		avail_len--;
+		cp0[head->write_avail++] = c;
+		if (c != '\n')
+			continue;
+		cp0[head->write_avail - 1] = '\0';
+		head->write_avail = 0;
+		tomoyo_normalize_line(cp0);
+		head->write(head);
+	}
+	mutex_unlock(&head->io_sem);
+	return error;
+}
+
+/**
+ * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface.
+ *
+ * @file: Pointer to "struct file".
+ *
+ * Releases memory and returns 0.
+ */
+static int tomoyo_close_control(struct file *file)
+{
+	struct tomoyo_io_buffer *head = file->private_data;
+
+	/* Release memory used for policy I/O. */
+	tomoyo_free(head->read_buf);
+	head->read_buf = NULL;
+	tomoyo_free(head->write_buf);
+	head->write_buf = NULL;
+	tomoyo_free(head);
+	head = NULL;
+	file->private_data = NULL;
+	return 0;
+}
+
+/**
+ * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry.
+ *
+ * @acl_type:  Type of ACL entry.
+ *
+ * Returns pointer to the ACL entry on success, NULL otherwise.
+ */
+void *tomoyo_alloc_acl_element(const u8 acl_type)
+{
+	int len;
+	struct tomoyo_acl_info *ptr;
+
+	switch (acl_type) {
+	case TOMOYO_TYPE_SINGLE_PATH_ACL:
+		len = sizeof(struct tomoyo_single_path_acl_record);
+		break;
+	case TOMOYO_TYPE_DOUBLE_PATH_ACL:
+		len = sizeof(struct tomoyo_double_path_acl_record);
+		break;
+	default:
+		return NULL;
+	}
+	ptr = tomoyo_alloc_element(len);
+	if (!ptr)
+		return NULL;
+	ptr->type = acl_type;
+	return ptr;
+}
+
+/**
+ * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
+ *
+ * @inode: Pointer to "struct inode".
+ * @file:  Pointer to "struct file".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_open(struct inode *inode, struct file *file)
+{
+	const int key = ((u8 *) file->f_path.dentry->d_inode->i_private)
+		- ((u8 *) NULL);
+	return tomoyo_open_control(key, file);
+}
+
+/**
+ * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface.
+ *
+ * @inode: Pointer to "struct inode".
+ * @file:  Pointer to "struct file".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_release(struct inode *inode, struct file *file)
+{
+	return tomoyo_close_control(file);
+}
+
+/**
+ * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface.
+ *
+ * @file:  Pointer to "struct file".
+ * @buf:   Pointer to buffer.
+ * @count: Size of @buf.
+ * @ppos:  Unused.
+ *
+ * Returns bytes read on success, negative value otherwise.
+ */
+static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
+			   loff_t *ppos)
+{
+	return tomoyo_read_control(file, buf, count);
+}
+
+/**
+ * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface.
+ *
+ * @file:  Pointer to "struct file".
+ * @buf:   Pointer to buffer.
+ * @count: Size of @buf.
+ * @ppos:  Unused.
+ *
+ * Returns @count on success, negative value otherwise.
+ */
+static ssize_t tomoyo_write(struct file *file, const char __user *buf,
+			    size_t count, loff_t *ppos)
+{
+	return tomoyo_write_control(file, buf, count);
+}
+
+/* Operations for /sys/kernel/security/tomoyo/ interface. */
+static const struct file_operations tomoyo_operations = {
+	.open    = tomoyo_open,
+	.release = tomoyo_release,
+	.read    = tomoyo_read,
+	.write   = tomoyo_write,
+};
+
+/**
+ * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory.
+ *
+ * @name:   The name of the interface file.
+ * @mode:   The permission of the interface file.
+ * @parent: The parent directory.
+ * @key:    Type of interface.
+ *
+ * Returns nothing.
+ */
+static void __init tomoyo_create_entry(const char *name, const mode_t mode,
+				       struct dentry *parent, const u8 key)
+{
+	securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
+			       &tomoyo_operations);
+}
+
+/**
+ * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface.
+ *
+ * Returns 0.
+ */
+static int __init tomoyo_initerface_init(void)
+{
+	struct dentry *tomoyo_dir;
+
+	/* Don't create securityfs entries unless registered. */
+	if (current_cred()->security != &tomoyo_kernel_domain)
+		return 0;
+
+	tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
+	tomoyo_create_entry("domain_policy",    0600, tomoyo_dir,
+			    TOMOYO_DOMAINPOLICY);
+	tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
+			    TOMOYO_EXCEPTIONPOLICY);
+	tomoyo_create_entry("self_domain",      0400, tomoyo_dir,
+			    TOMOYO_SELFDOMAIN);
+	tomoyo_create_entry(".domain_status",   0600, tomoyo_dir,
+			    TOMOYO_DOMAIN_STATUS);
+	tomoyo_create_entry(".process_status",  0600, tomoyo_dir,
+			    TOMOYO_PROCESS_STATUS);
+	tomoyo_create_entry("meminfo",          0600, tomoyo_dir,
+			    TOMOYO_MEMINFO);
+	tomoyo_create_entry("profile",          0600, tomoyo_dir,
+			    TOMOYO_PROFILE);
+	tomoyo_create_entry("manager",          0600, tomoyo_dir,
+			    TOMOYO_MANAGER);
+	tomoyo_create_entry("version",          0400, tomoyo_dir,
+			    TOMOYO_VERSION);
+	return 0;
+}
+
+fs_initcall(tomoyo_initerface_init);
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
new file mode 100644
index 0000000..6dcb7cc
--- /dev/null
+++ b/security/tomoyo/common.h
@@ -0,0 +1,359 @@
+/*
+ * security/tomoyo/common.h
+ *
+ * Common functions for TOMOYO.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#ifndef _SECURITY_TOMOYO_COMMON_H
+#define _SECURITY_TOMOYO_COMMON_H
+
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/file.h>
+#include <linux/kmod.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/list.h>
+
+struct dentry;
+struct vfsmount;
+
+/* Temporary buffer for holding pathnames. */
+struct tomoyo_page_buffer {
+	char buffer[4096];
+};
+
+/* Structure for holding a token. */
+struct tomoyo_path_info {
+	const char *name;
+	u32 hash;          /* = full_name_hash(name, strlen(name)) */
+	u16 total_len;     /* = strlen(name)                       */
+	u16 const_len;     /* = tomoyo_const_part_length(name)     */
+	bool is_dir;       /* = tomoyo_strendswith(name, "/")      */
+	bool is_patterned; /* = tomoyo_path_contains_pattern(name) */
+	u16 depth;         /* = tomoyo_path_depth(name)            */
+};
+
+/*
+ * This is the max length of a token.
+ *
+ * A token consists of only ASCII printable characters.
+ * Non printable characters in a token is represented in \ooo style
+ * octal string. Thus, \ itself is represented as \\.
+ */
+#define TOMOYO_MAX_PATHNAME_LEN 4000
+
+/* Structure for holding requested pathname. */
+struct tomoyo_path_info_with_data {
+	/* Keep "head" first, for this pointer is passed to tomoyo_free(). */
+	struct tomoyo_path_info head;
+	char bariier1[16]; /* Safeguard for overrun. */
+	char body[TOMOYO_MAX_PATHNAME_LEN];
+	char barrier2[16]; /* Safeguard for overrun. */
+};
+
+/*
+ * Common header for holding ACL entries.
+ *
+ * Packing "struct tomoyo_acl_info" allows
+ * "struct tomoyo_single_path_acl_record" to embed "u16" and
+ * "struct tomoyo_double_path_acl_record" to embed "u8"
+ * without enlarging their structure size.
+ */
+struct tomoyo_acl_info {
+	struct list_head list;
+	/*
+	 * Type of this ACL entry.
+	 *
+	 * MSB is is_deleted flag.
+	 */
+	u8 type;
+} __packed;
+
+/* This ACL entry is deleted.           */
+#define TOMOYO_ACL_DELETED        0x80
+
+/* Structure for domain information. */
+struct tomoyo_domain_info {
+	struct list_head list;
+	struct list_head acl_info_list;
+	/* Name of this domain. Never NULL.          */
+	const struct tomoyo_path_info *domainname;
+	u8 profile;        /* Profile number to use. */
+	u8 is_deleted;     /* Delete flag.
+			      0 = active.
+			      1 = deleted but undeletable.
+			      255 = deleted and no longer undeletable. */
+	bool quota_warned; /* Quota warnning flag.   */
+	/* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */
+	u8 flags;
+};
+
+/* Profile number is an integer between 0 and 255. */
+#define TOMOYO_MAX_PROFILES 256
+
+/* Ignore "allow_read" directive in exception policy. */
+#define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1
+/*
+ * This domain was unable to create a new domain at tomoyo_find_next_domain()
+ * because the name of the domain to be created was too long or
+ * it could not allocate memory.
+ * More than one process continued execve() without domain transition.
+ */
+#define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED        2
+
+/*
+ * Structure for "allow_read/write", "allow_execute", "allow_read",
+ * "allow_write", "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
+ * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar",
+ * "allow_truncate", "allow_symlink" and "allow_rewrite" directive.
+ */
+struct tomoyo_single_path_acl_record {
+	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */
+	u16 perm;
+	/* Pointer to single pathname. */
+	const struct tomoyo_path_info *filename;
+};
+
+/* Structure for "allow_rename" and "allow_link" directive. */
+struct tomoyo_double_path_acl_record {
+	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */
+	u8 perm;
+	/* Pointer to single pathname. */
+	const struct tomoyo_path_info *filename1;
+	/* Pointer to single pathname. */
+	const struct tomoyo_path_info *filename2;
+};
+
+/* Keywords for ACLs. */
+#define TOMOYO_KEYWORD_ALIAS                     "alias "
+#define TOMOYO_KEYWORD_ALLOW_READ                "allow_read "
+#define TOMOYO_KEYWORD_DELETE                    "delete "
+#define TOMOYO_KEYWORD_DENY_REWRITE              "deny_rewrite "
+#define TOMOYO_KEYWORD_FILE_PATTERN              "file_pattern "
+#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN         "initialize_domain "
+#define TOMOYO_KEYWORD_KEEP_DOMAIN               "keep_domain "
+#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN      "no_initialize_domain "
+#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN            "no_keep_domain "
+#define TOMOYO_KEYWORD_SELECT                    "select "
+#define TOMOYO_KEYWORD_UNDELETE                  "undelete "
+#define TOMOYO_KEYWORD_USE_PROFILE               "use_profile "
+#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ  "ignore_global_allow_read"
+/* A domain definition starts with <kernel>. */
+#define TOMOYO_ROOT_NAME                         "<kernel>"
+#define TOMOYO_ROOT_NAME_LEN                     (sizeof(TOMOYO_ROOT_NAME) - 1)
+
+/* Index numbers for Access Controls. */
+#define TOMOYO_MAC_FOR_FILE                  0  /* domain_policy.conf */
+#define TOMOYO_MAX_ACCEPT_ENTRY              1
+#define TOMOYO_VERBOSE                       2
+#define TOMOYO_MAX_CONTROL_INDEX             3
+
+/* Structure for reading/writing policy via securityfs interfaces. */
+struct tomoyo_io_buffer {
+	int (*read) (struct tomoyo_io_buffer *);
+	int (*write) (struct tomoyo_io_buffer *);
+	/* Exclusive lock for this structure.   */
+	struct mutex io_sem;
+	/* The position currently reading from. */
+	struct list_head *read_var1;
+	/* Extra variables for reading.         */
+	struct list_head *read_var2;
+	/* The position currently writing to.   */
+	struct tomoyo_domain_info *write_var1;
+	/* The step for reading.                */
+	int read_step;
+	/* Buffer for reading.                  */
+	char *read_buf;
+	/* EOF flag for reading.                */
+	bool read_eof;
+	/* Read domain ACL of specified PID?    */
+	bool read_single_domain;
+	/* Extra variable for reading.          */
+	u8 read_bit;
+	/* Bytes available for reading.         */
+	int read_avail;
+	/* Size of read buffer.                 */
+	int readbuf_size;
+	/* Buffer for writing.                  */
+	char *write_buf;
+	/* Bytes available for writing.         */
+	int write_avail;
+	/* Size of write buffer.                */
+	int writebuf_size;
+};
+
+/* Check whether the domain has too many ACL entries to hold. */
+bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain);
+/* Transactional sprintf() for policy dump. */
+bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
+	__attribute__ ((format(printf, 2, 3)));
+/* Check whether the domainname is correct. */
+bool tomoyo_is_correct_domain(const unsigned char *domainname,
+			      const char *function);
+/* Check whether the token is correct. */
+bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
+			    const s8 pattern_type, const s8 end_type,
+			    const char *function);
+/* Check whether the token can be a domainname. */
+bool tomoyo_is_domain_def(const unsigned char *buffer);
+/* Check whether the given filename matches the given pattern. */
+bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
+				 const struct tomoyo_path_info *pattern);
+/* Read "alias" entry in exception policy. */
+bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head);
+/*
+ * Read "initialize_domain" and "no_initialize_domain" entry
+ * in exception policy.
+ */
+bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head);
+/* Read "keep_domain" and "no_keep_domain" entry in exception policy. */
+bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head);
+/* Read "file_pattern" entry in exception policy. */
+bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head);
+/* Read "allow_read" entry in exception policy. */
+bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head);
+/* Read "deny_rewrite" entry in exception policy. */
+bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head);
+/* Write domain policy violation warning message to console? */
+bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain);
+/* Convert double path operation to operation name. */
+const char *tomoyo_dp2keyword(const u8 operation);
+/* Get the last component of the given domainname. */
+const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain);
+/* Get warning message. */
+const char *tomoyo_get_msg(const bool is_enforce);
+/* Convert single path operation to operation name. */
+const char *tomoyo_sp2keyword(const u8 operation);
+/* Delete a domain. */
+int tomoyo_delete_domain(char *data);
+/* Create "alias" entry in exception policy. */
+int tomoyo_write_alias_policy(char *data, const bool is_delete);
+/*
+ * Create "initialize_domain" and "no_initialize_domain" entry
+ * in exception policy.
+ */
+int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
+					   const bool is_delete);
+/* Create "keep_domain" and "no_keep_domain" entry in exception policy. */
+int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
+				      const bool is_delete);
+/*
+ * Create "allow_read/write", "allow_execute", "allow_read", "allow_write",
+ * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
+ * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar",
+ * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and
+ * "allow_link" entry in domain policy.
+ */
+int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
+			     const bool is_delete);
+/* Create "allow_read" entry in exception policy. */
+int tomoyo_write_globally_readable_policy(char *data, const bool is_delete);
+/* Create "deny_rewrite" entry in exception policy. */
+int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
+/* Create "file_pattern" entry in exception policy. */
+int tomoyo_write_pattern_policy(char *data, const bool is_delete);
+/* Find a domain by the given name. */
+struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
+/* Find or create a domain by the given name. */
+struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
+							    domainname,
+							    const u8 profile);
+/* Undelete a domain. */
+struct tomoyo_domain_info *tomoyo_undelete_domain(const char *domainname);
+/* Check mode for specified functionality. */
+unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
+				const u8 index);
+/* Allocate memory for structures. */
+void *tomoyo_alloc_acl_element(const u8 acl_type);
+/* Fill in "struct tomoyo_path_info" members. */
+void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
+/* Run policy loader when /sbin/init starts. */
+void tomoyo_load_policy(const char *filename);
+/* Change "struct tomoyo_domain_info"->flags. */
+void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
+			    const bool is_delete, const u8 flags);
+
+/* strcmp() for "struct tomoyo_path_info" structure. */
+static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
+				  const struct tomoyo_path_info *b)
+{
+	return a->hash != b->hash || strcmp(a->name, b->name);
+}
+
+/* Get type of an ACL entry. */
+static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr)
+{
+	return ptr->type & ~TOMOYO_ACL_DELETED;
+}
+
+/* Get type of an ACL entry. */
+static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr)
+{
+	return ptr->type;
+}
+
+/**
+ * tomoyo_is_valid - Check whether the character is a valid char.
+ *
+ * @c: The character to check.
+ *
+ * Returns true if @c is a valid character, false otherwise.
+ */
+static inline bool tomoyo_is_valid(const unsigned char c)
+{
+	return c > ' ' && c < 127;
+}
+
+/**
+ * tomoyo_is_invalid - Check whether the character is an invalid char.
+ *
+ * @c: The character to check.
+ *
+ * Returns true if @c is an invalid character, false otherwise.
+ */
+static inline bool tomoyo_is_invalid(const unsigned char c)
+{
+	return c && (c <= ' ' || c >= 127);
+}
+
+/* The list for "struct tomoyo_domain_info". */
+extern struct list_head tomoyo_domain_list;
+extern struct rw_semaphore tomoyo_domain_list_lock;
+
+/* Lock for domain->acl_info_list. */
+extern struct rw_semaphore tomoyo_domain_acl_info_list_lock;
+
+/* Has /sbin/init started? */
+extern bool tomoyo_policy_loaded;
+
+/* The kernel's domain. */
+extern struct tomoyo_domain_info tomoyo_kernel_domain;
+
+/**
+ * list_for_each_cookie - iterate over a list with cookie.
+ * @pos:        the &struct list_head to use as a loop cursor.
+ * @cookie:     the &struct list_head to use as a cookie.
+ * @head:       the head for your list.
+ *
+ * Same with list_for_each() except that this primitive uses @cookie
+ * so that we can continue iteration.
+ * @cookie must be NULL when iteration starts, and @cookie will become
+ * NULL when iteration finishes.
+ */
+#define list_for_each_cookie(pos, cookie, head)                       \
+	for (({ if (!cookie)                                          \
+				     cookie = head; }),               \
+	     pos = (cookie)->next;                                    \
+	     prefetch(pos->next), pos != (head) || ((cookie) = NULL); \
+	     (cookie) = pos, pos = pos->next)
+
+#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
new file mode 100644
index 0000000..093a756
--- /dev/null
+++ b/security/tomoyo/domain.c
@@ -0,0 +1,878 @@
+/*
+ * security/tomoyo/domain.c
+ *
+ * Implementation of the Domain-Based Mandatory Access Control.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#include "common.h"
+#include "tomoyo.h"
+#include "realpath.h"
+#include <linux/binfmts.h>
+
+/* Variables definitions.*/
+
+/* The initial domain. */
+struct tomoyo_domain_info tomoyo_kernel_domain;
+
+/* The list for "struct tomoyo_domain_info". */
+LIST_HEAD(tomoyo_domain_list);
+DECLARE_RWSEM(tomoyo_domain_list_lock);
+
+/* Structure for "initialize_domain" and "no_initialize_domain" keyword. */
+struct tomoyo_domain_initializer_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *domainname;    /* This may be NULL */
+	const struct tomoyo_path_info *program;
+	bool is_deleted;
+	bool is_not;       /* True if this entry is "no_initialize_domain".  */
+	/* True if the domainname is tomoyo_get_last_name(). */
+	bool is_last_name;
+};
+
+/* Structure for "keep_domain" and "no_keep_domain" keyword. */
+struct tomoyo_domain_keeper_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *domainname;
+	const struct tomoyo_path_info *program;       /* This may be NULL */
+	bool is_deleted;
+	bool is_not;       /* True if this entry is "no_keep_domain".        */
+	/* True if the domainname is tomoyo_get_last_name(). */
+	bool is_last_name;
+};
+
+/* Structure for "alias" keyword. */
+struct tomoyo_alias_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *original_name;
+	const struct tomoyo_path_info *aliased_name;
+	bool is_deleted;
+};
+
+/**
+ * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
+ *
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @is_delete: True if it is a delete request.
+ * @flags:     Flags to set or clear.
+ *
+ * Returns nothing.
+ */
+void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
+			    const bool is_delete, const u8 flags)
+{
+	/* We need to serialize because this is bitfield operation. */
+	static DEFINE_SPINLOCK(lock);
+	/***** CRITICAL SECTION START *****/
+	spin_lock(&lock);
+	if (!is_delete)
+		domain->flags |= flags;
+	else
+		domain->flags &= ~flags;
+	spin_unlock(&lock);
+	/***** CRITICAL SECTION END *****/
+}
+
+/**
+ * tomoyo_get_last_name - Get last component of a domainname.
+ *
+ * @domain: Pointer to "struct tomoyo_domain_info".
+ *
+ * Returns the last component of the domainname.
+ */
+const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
+{
+	const char *cp0 = domain->domainname->name;
+	const char *cp1 = strrchr(cp0, ' ');
+
+	if (cp1)
+		return cp1 + 1;
+	return cp0;
+}
+
+/* The list for "struct tomoyo_domain_initializer_entry". */
+static LIST_HEAD(tomoyo_domain_initializer_list);
+static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
+
+/**
+ * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
+ *
+ * @domainname: The name of domain. May be NULL.
+ * @program:    The name of program.
+ * @is_not:     True if it is "no_initialize_domain" entry.
+ * @is_delete:  True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_update_domain_initializer_entry(const char *domainname,
+						  const char *program,
+						  const bool is_not,
+						  const bool is_delete)
+{
+	struct tomoyo_domain_initializer_entry *new_entry;
+	struct tomoyo_domain_initializer_entry *ptr;
+	const struct tomoyo_path_info *saved_program;
+	const struct tomoyo_path_info *saved_domainname = NULL;
+	int error = -ENOMEM;
+	bool is_last_name = false;
+
+	if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
+		return -EINVAL; /* No patterns allowed. */
+	if (domainname) {
+		if (!tomoyo_is_domain_def(domainname) &&
+		    tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
+			is_last_name = true;
+		else if (!tomoyo_is_correct_domain(domainname, __func__))
+			return -EINVAL;
+		saved_domainname = tomoyo_save_name(domainname);
+		if (!saved_domainname)
+			return -ENOMEM;
+	}
+	saved_program = tomoyo_save_name(program);
+	if (!saved_program)
+		return -ENOMEM;
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_domain_initializer_list_lock);
+	list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
+		if (ptr->is_not != is_not ||
+		    ptr->domainname != saved_domainname ||
+		    ptr->program != saved_program)
+			continue;
+		ptr->is_deleted = is_delete;
+		error = 0;
+		goto out;
+	}
+	if (is_delete) {
+		error = -ENOENT;
+		goto out;
+	}
+	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
+	if (!new_entry)
+		goto out;
+	new_entry->domainname = saved_domainname;
+	new_entry->program = saved_program;
+	new_entry->is_not = is_not;
+	new_entry->is_last_name = is_last_name;
+	list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
+	error = 0;
+ out:
+	up_write(&tomoyo_domain_initializer_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return error;
+}
+
+/**
+ * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns true on success, false otherwise.
+ */
+bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
+{
+	struct list_head *pos;
+	bool done = true;
+
+	down_read(&tomoyo_domain_initializer_list_lock);
+	list_for_each_cookie(pos, head->read_var2,
+			     &tomoyo_domain_initializer_list) {
+		const char *no;
+		const char *from = "";
+		const char *domain = "";
+		struct tomoyo_domain_initializer_entry *ptr;
+		ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
+				  list);
+		if (ptr->is_deleted)
+			continue;
+		no = ptr->is_not ? "no_" : "";
+		if (ptr->domainname) {
+			from = " from ";
+			domain = ptr->domainname->name;
+		}
+		if (!tomoyo_io_printf(head,
+				      "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
+				      "%s%s%s\n", no, ptr->program->name, from,
+				      domain)) {
+			done = false;
+			break;
+		}
+	}
+	up_read(&tomoyo_domain_initializer_list_lock);
+	return done;
+}
+
+/**
+ * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
+ *
+ * @data:      String to parse.
+ * @is_not:    True if it is "no_initialize_domain" entry.
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
+					   const bool is_delete)
+{
+	char *cp = strstr(data, " from ");
+
+	if (cp) {
+		*cp = '\0';
+		return tomoyo_update_domain_initializer_entry(cp + 6, data,
+							      is_not,
+							      is_delete);
+	}
+	return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
+						      is_delete);
+}
+
+/**
+ * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
+ *
+ * @domainname: The name of domain.
+ * @program:    The name of program.
+ * @last_name:  The last component of @domainname.
+ *
+ * Returns true if executing @program reinitializes domain transition,
+ * false otherwise.
+ */
+static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
+					 domainname,
+					 const struct tomoyo_path_info *program,
+					 const struct tomoyo_path_info *
+					 last_name)
+{
+	struct tomoyo_domain_initializer_entry *ptr;
+	bool flag = false;
+
+	down_read(&tomoyo_domain_initializer_list_lock);
+	list_for_each_entry(ptr,  &tomoyo_domain_initializer_list, list) {
+		if (ptr->is_deleted)
+			continue;
+		if (ptr->domainname) {
+			if (!ptr->is_last_name) {
+				if (ptr->domainname != domainname)
+					continue;
+			} else {
+				if (tomoyo_pathcmp(ptr->domainname, last_name))
+					continue;
+			}
+		}
+		if (tomoyo_pathcmp(ptr->program, program))
+			continue;
+		if (ptr->is_not) {
+			flag = false;
+			break;
+		}
+		flag = true;
+	}
+	up_read(&tomoyo_domain_initializer_list_lock);
+	return flag;
+}
+
+/* The list for "struct tomoyo_domain_keeper_entry". */
+static LIST_HEAD(tomoyo_domain_keeper_list);
+static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
+
+/**
+ * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
+ *
+ * @domainname: The name of domain.
+ * @program:    The name of program. May be NULL.
+ * @is_not:     True if it is "no_keep_domain" entry.
+ * @is_delete:  True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_update_domain_keeper_entry(const char *domainname,
+					     const char *program,
+					     const bool is_not,
+					     const bool is_delete)
+{
+	struct tomoyo_domain_keeper_entry *new_entry;
+	struct tomoyo_domain_keeper_entry *ptr;
+	const struct tomoyo_path_info *saved_domainname;
+	const struct tomoyo_path_info *saved_program = NULL;
+	static DEFINE_MUTEX(lock);
+	int error = -ENOMEM;
+	bool is_last_name = false;
+
+	if (!tomoyo_is_domain_def(domainname) &&
+	    tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
+		is_last_name = true;
+	else if (!tomoyo_is_correct_domain(domainname, __func__))
+		return -EINVAL;
+	if (program) {
+		if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
+			return -EINVAL;
+		saved_program = tomoyo_save_name(program);
+		if (!saved_program)
+			return -ENOMEM;
+	}
+	saved_domainname = tomoyo_save_name(domainname);
+	if (!saved_domainname)
+		return -ENOMEM;
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_domain_keeper_list_lock);
+	list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
+		if (ptr->is_not != is_not ||
+		    ptr->domainname != saved_domainname ||
+		    ptr->program != saved_program)
+			continue;
+		ptr->is_deleted = is_delete;
+		error = 0;
+		goto out;
+	}
+	if (is_delete) {
+		error = -ENOENT;
+		goto out;
+	}
+	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
+	if (!new_entry)
+		goto out;
+	new_entry->domainname = saved_domainname;
+	new_entry->program = saved_program;
+	new_entry->is_not = is_not;
+	new_entry->is_last_name = is_last_name;
+	list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
+	error = 0;
+ out:
+	up_write(&tomoyo_domain_keeper_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return error;
+}
+
+/**
+ * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
+ *
+ * @data:      String to parse.
+ * @is_not:    True if it is "no_keep_domain" entry.
+ * @is_delete: True if it is a delete request.
+ *
+ */
+int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
+				      const bool is_delete)
+{
+	char *cp = strstr(data, " from ");
+
+	if (cp) {
+		*cp = '\0';
+		return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
+							 is_delete);
+	}
+	return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
+}
+
+/**
+ * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns true on success, false otherwise.
+ */
+bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
+{
+	struct list_head *pos;
+	bool done = true;
+
+	down_read(&tomoyo_domain_keeper_list_lock);
+	list_for_each_cookie(pos, head->read_var2,
+			     &tomoyo_domain_keeper_list) {
+		struct tomoyo_domain_keeper_entry *ptr;
+		const char *no;
+		const char *from = "";
+		const char *program = "";
+
+		ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
+		if (ptr->is_deleted)
+			continue;
+		no = ptr->is_not ? "no_" : "";
+		if (ptr->program) {
+			from = " from ";
+			program = ptr->program->name;
+		}
+		if (!tomoyo_io_printf(head,
+				      "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
+				      "%s%s%s\n", no, program, from,
+				      ptr->domainname->name)) {
+			done = false;
+			break;
+		}
+	}
+	up_read(&tomoyo_domain_keeper_list_lock);
+	return done;
+}
+
+/**
+ * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
+ *
+ * @domainname: The name of domain.
+ * @program:    The name of program.
+ * @last_name:  The last component of @domainname.
+ *
+ * Returns true if executing @program supresses domain transition,
+ * false otherwise.
+ */
+static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
+				    const struct tomoyo_path_info *program,
+				    const struct tomoyo_path_info *last_name)
+{
+	struct tomoyo_domain_keeper_entry *ptr;
+	bool flag = false;
+
+	down_read(&tomoyo_domain_keeper_list_lock);
+	list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
+		if (ptr->is_deleted)
+			continue;
+		if (!ptr->is_last_name) {
+			if (ptr->domainname != domainname)
+				continue;
+		} else {
+			if (tomoyo_pathcmp(ptr->domainname, last_name))
+				continue;
+		}
+		if (ptr->program && tomoyo_pathcmp(ptr->program, program))
+			continue;
+		if (ptr->is_not) {
+			flag = false;
+			break;
+		}
+		flag = true;
+	}
+	up_read(&tomoyo_domain_keeper_list_lock);
+	return flag;
+}
+
+/* The list for "struct tomoyo_alias_entry". */
+static LIST_HEAD(tomoyo_alias_list);
+static DECLARE_RWSEM(tomoyo_alias_list_lock);
+
+/**
+ * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
+ *
+ * @original_name: The original program's real name.
+ * @aliased_name:  The symbolic program's symbolic link's name.
+ * @is_delete:     True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_update_alias_entry(const char *original_name,
+				     const char *aliased_name,
+				     const bool is_delete)
+{
+	struct tomoyo_alias_entry *new_entry;
+	struct tomoyo_alias_entry *ptr;
+	const struct tomoyo_path_info *saved_original_name;
+	const struct tomoyo_path_info *saved_aliased_name;
+	int error = -ENOMEM;
+
+	if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
+	    !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
+		return -EINVAL; /* No patterns allowed. */
+	saved_original_name = tomoyo_save_name(original_name);
+	saved_aliased_name = tomoyo_save_name(aliased_name);
+	if (!saved_original_name || !saved_aliased_name)
+		return -ENOMEM;
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_alias_list_lock);
+	list_for_each_entry(ptr, &tomoyo_alias_list, list) {
+		if (ptr->original_name != saved_original_name ||
+		    ptr->aliased_name != saved_aliased_name)
+			continue;
+		ptr->is_deleted = is_delete;
+		error = 0;
+		goto out;
+	}
+	if (is_delete) {
+		error = -ENOENT;
+		goto out;
+	}
+	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
+	if (!new_entry)
+		goto out;
+	new_entry->original_name = saved_original_name;
+	new_entry->aliased_name = saved_aliased_name;
+	list_add_tail(&new_entry->list, &tomoyo_alias_list);
+	error = 0;
+ out:
+	up_write(&tomoyo_alias_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return error;
+}
+
+/**
+ * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns true on success, false otherwise.
+ */
+bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
+{
+	struct list_head *pos;
+	bool done = true;
+
+	down_read(&tomoyo_alias_list_lock);
+	list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
+		struct tomoyo_alias_entry *ptr;
+
+		ptr = list_entry(pos, struct tomoyo_alias_entry, list);
+		if (ptr->is_deleted)
+			continue;
+		if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
+				      ptr->original_name->name,
+				      ptr->aliased_name->name)) {
+			done = false;
+			break;
+		}
+	}
+	up_read(&tomoyo_alias_list_lock);
+	return done;
+}
+
+/**
+ * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
+ *
+ * @data:      String to parse.
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_write_alias_policy(char *data, const bool is_delete)
+{
+	char *cp = strchr(data, ' ');
+
+	if (!cp)
+		return -EINVAL;
+	*cp++ = '\0';
+	return tomoyo_update_alias_entry(data, cp, is_delete);
+}
+
+/* Domain create/delete/undelete handler. */
+
+/* #define TOMOYO_DEBUG_DOMAIN_UNDELETE */
+
+/**
+ * tomoyo_delete_domain - Delete a domain.
+ *
+ * @domainname: The name of domain.
+ *
+ * Returns 0.
+ */
+int tomoyo_delete_domain(char *domainname)
+{
+	struct tomoyo_domain_info *domain;
+	struct tomoyo_path_info name;
+
+	name.name = domainname;
+	tomoyo_fill_path_info(&name);
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_domain_list_lock);
+#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
+	printk(KERN_DEBUG "tomoyo_delete_domain %s\n", domainname);
+	list_for_each_entry(domain, &tomoyo_domain_list, list) {
+		if (tomoyo_pathcmp(domain->domainname, &name))
+			continue;
+		printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
+	}
+#endif
+	/* Is there an active domain? */
+	list_for_each_entry(domain, &tomoyo_domain_list, list) {
+		struct tomoyo_domain_info *domain2;
+		/* Never delete tomoyo_kernel_domain */
+		if (domain == &tomoyo_kernel_domain)
+			continue;
+		if (domain->is_deleted ||
+		    tomoyo_pathcmp(domain->domainname, &name))
+			continue;
+		/* Mark already deleted domains as non undeletable. */
+		list_for_each_entry(domain2, &tomoyo_domain_list, list) {
+			if (!domain2->is_deleted ||
+			    tomoyo_pathcmp(domain2->domainname, &name))
+				continue;
+#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
+			if (domain2->is_deleted != 255)
+				printk(KERN_DEBUG
+				       "Marked %p as non undeletable\n",
+				       domain2);
+#endif
+			domain2->is_deleted = 255;
+		}
+		/* Delete and mark active domain as undeletable. */
+		domain->is_deleted = 1;
+#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
+		printk(KERN_DEBUG "Marked %p as undeletable\n", domain);
+#endif
+		break;
+	}
+	up_write(&tomoyo_domain_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return 0;
+}
+
+/**
+ * tomoyo_undelete_domain - Undelete a domain.
+ *
+ * @domainname: The name of domain.
+ *
+ * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
+ */
+struct tomoyo_domain_info *tomoyo_undelete_domain(const char *domainname)
+{
+	struct tomoyo_domain_info *domain;
+	struct tomoyo_domain_info *candidate_domain = NULL;
+	struct tomoyo_path_info name;
+
+	name.name = domainname;
+	tomoyo_fill_path_info(&name);
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_domain_list_lock);
+#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
+	printk(KERN_DEBUG "tomoyo_undelete_domain %s\n", domainname);
+	list_for_each_entry(domain, &tomoyo_domain_list, list) {
+		if (tomoyo_pathcmp(domain->domainname, &name))
+			continue;
+		printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
+	}
+#endif
+	list_for_each_entry(domain, &tomoyo_domain_list, list) {
+		if (tomoyo_pathcmp(&name, domain->domainname))
+			continue;
+		if (!domain->is_deleted) {
+			/* This domain is active. I can't undelete. */
+			candidate_domain = NULL;
+#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
+			printk(KERN_DEBUG "%p is active. I can't undelete.\n",
+			       domain);
+#endif
+			break;
+		}
+		/* Is this domain undeletable? */
+		if (domain->is_deleted == 1)
+			candidate_domain = domain;
+	}
+	if (candidate_domain) {
+		candidate_domain->is_deleted = 0;
+#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
+		printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain);
+#endif
+	}
+	up_write(&tomoyo_domain_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return candidate_domain;
+}
+
+/**
+ * tomoyo_find_or_assign_new_domain - Create a domain.
+ *
+ * @domainname: The name of domain.
+ * @profile:    Profile number to assign if the domain was newly created.
+ *
+ * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
+ */
+struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
+							    domainname,
+							    const u8 profile)
+{
+	struct tomoyo_domain_info *domain = NULL;
+	const struct tomoyo_path_info *saved_domainname;
+
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_domain_list_lock);
+	domain = tomoyo_find_domain(domainname);
+	if (domain)
+		goto out;
+	if (!tomoyo_is_correct_domain(domainname, __func__))
+		goto out;
+	saved_domainname = tomoyo_save_name(domainname);
+	if (!saved_domainname)
+		goto out;
+	/* Can I reuse memory of deleted domain? */
+	list_for_each_entry(domain, &tomoyo_domain_list, list) {
+		struct task_struct *p;
+		struct tomoyo_acl_info *ptr;
+		bool flag;
+		if (!domain->is_deleted ||
+		    domain->domainname != saved_domainname)
+			continue;
+		flag = false;
+		/***** CRITICAL SECTION START *****/
+		read_lock(&tasklist_lock);
+		for_each_process(p) {
+			if (tomoyo_real_domain(p) != domain)
+				continue;
+			flag = true;
+			break;
+		}
+		read_unlock(&tasklist_lock);
+		/***** CRITICAL SECTION END *****/
+		if (flag)
+			continue;
+#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
+		printk(KERN_DEBUG "Reusing %p %s\n", domain,
+		       domain->domainname->name);
+#endif
+		list_for_each_entry(ptr, &domain->acl_info_list, list) {
+			ptr->type |= TOMOYO_ACL_DELETED;
+		}
+		tomoyo_set_domain_flag(domain, true, domain->flags);
+		domain->profile = profile;
+		domain->quota_warned = false;
+		mb(); /* Avoid out-of-order execution. */
+		domain->is_deleted = 0;
+		goto out;
+	}
+	/* No memory reusable. Create using new memory. */
+	domain = tomoyo_alloc_element(sizeof(*domain));
+	if (domain) {
+		INIT_LIST_HEAD(&domain->acl_info_list);
+		domain->domainname = saved_domainname;
+		domain->profile = profile;
+		list_add_tail(&domain->list, &tomoyo_domain_list);
+	}
+ out:
+	up_write(&tomoyo_domain_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return domain;
+}
+
+/**
+ * tomoyo_find_next_domain - Find a domain.
+ *
+ * @bprm:           Pointer to "struct linux_binprm".
+ * @next_domain:    Pointer to pointer to "struct tomoyo_domain_info".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_find_next_domain(struct linux_binprm *bprm,
+			    struct tomoyo_domain_info **next_domain)
+{
+	/*
+	 * This function assumes that the size of buffer returned by
+	 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
+	 */
+	struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp));
+	struct tomoyo_domain_info *old_domain = tomoyo_domain();
+	struct tomoyo_domain_info *domain = NULL;
+	const char *old_domain_name = old_domain->domainname->name;
+	const char *original_name = bprm->filename;
+	char *new_domain_name = NULL;
+	char *real_program_name = NULL;
+	char *symlink_program_name = NULL;
+	const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
+	const bool is_enforce = (mode == 3);
+	int retval = -ENOMEM;
+	struct tomoyo_path_info r; /* real name */
+	struct tomoyo_path_info s; /* symlink name */
+	struct tomoyo_path_info l; /* last name */
+	static bool initialized;
+
+	if (!tmp)
+		goto out;
+
+	if (!initialized) {
+		/*
+		 * Built-in initializers. This is needed because policies are
+		 * not loaded until starting /sbin/init.
+		 */
+		tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
+						       false, false);
+		tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
+						       false, false);
+		initialized = true;
+	}
+
+	/* Get tomoyo_realpath of program. */
+	retval = -ENOENT;
+	/* I hope tomoyo_realpath() won't fail with -ENOMEM. */
+	real_program_name = tomoyo_realpath(original_name);
+	if (!real_program_name)
+		goto out;
+	/* Get tomoyo_realpath of symbolic link. */
+	symlink_program_name = tomoyo_realpath_nofollow(original_name);
+	if (!symlink_program_name)
+		goto out;
+
+	r.name = real_program_name;
+	tomoyo_fill_path_info(&r);
+	s.name = symlink_program_name;
+	tomoyo_fill_path_info(&s);
+	l.name = tomoyo_get_last_name(old_domain);
+	tomoyo_fill_path_info(&l);
+
+	/* Check 'alias' directive. */
+	if (tomoyo_pathcmp(&r, &s)) {
+		struct tomoyo_alias_entry *ptr;
+		/* Is this program allowed to be called via symbolic links? */
+		down_read(&tomoyo_alias_list_lock);
+		list_for_each_entry(ptr, &tomoyo_alias_list, list) {
+			if (ptr->is_deleted ||
+			    tomoyo_pathcmp(&r, ptr->original_name) ||
+			    tomoyo_pathcmp(&s, ptr->aliased_name))
+				continue;
+			memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
+			strncpy(real_program_name, ptr->aliased_name->name,
+				TOMOYO_MAX_PATHNAME_LEN - 1);
+			tomoyo_fill_path_info(&r);
+			break;
+		}
+		up_read(&tomoyo_alias_list_lock);
+	}
+
+	/* Check execute permission. */
+	retval = tomoyo_check_exec_perm(old_domain, &r, tmp);
+	if (retval < 0)
+		goto out;
+
+	new_domain_name = tmp->buffer;
+	if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) {
+		/* Transit to the child of tomoyo_kernel_domain domain. */
+		snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
+			 TOMOYO_ROOT_NAME " " "%s", real_program_name);
+	} else if (old_domain == &tomoyo_kernel_domain &&
+		   !tomoyo_policy_loaded) {
+		/*
+		 * Needn't to transit from kernel domain before starting
+		 * /sbin/init. But transit from kernel domain if executing
+		 * initializers because they might start before /sbin/init.
+		 */
+		domain = old_domain;
+	} else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
+		/* Keep current domain. */
+		domain = old_domain;
+	} else {
+		/* Normal domain transition. */
+		snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
+			 "%s %s", old_domain_name, real_program_name);
+	}
+	if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
+		goto done;
+	down_read(&tomoyo_domain_list_lock);
+	domain = tomoyo_find_domain(new_domain_name);
+	up_read(&tomoyo_domain_list_lock);
+	if (domain)
+		goto done;
+	if (is_enforce)
+		goto done;
+	domain = tomoyo_find_or_assign_new_domain(new_domain_name,
+						  old_domain->profile);
+ done:
+	if (domain)
+		goto out;
+	printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
+	       new_domain_name);
+	if (is_enforce)
+		retval = -EPERM;
+	else
+		tomoyo_set_domain_flag(old_domain, false,
+				       TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
+ out:
+	tomoyo_free(real_program_name);
+	tomoyo_free(symlink_program_name);
+	*next_domain = domain ? domain : old_domain;
+	tomoyo_free(tmp);
+	return retval;
+}
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
new file mode 100644
index 0000000..65f50c1
--- /dev/null
+++ b/security/tomoyo/file.c
@@ -0,0 +1,1241 @@
+/*
+ * security/tomoyo/file.c
+ *
+ * Implementation of the Domain-Based Mandatory Access Control.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#include "common.h"
+#include "tomoyo.h"
+#include "realpath.h"
+#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
+
+/* Structure for "allow_read" keyword. */
+struct tomoyo_globally_readable_file_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *filename;
+	bool is_deleted;
+};
+
+/* Structure for "file_pattern" keyword. */
+struct tomoyo_pattern_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *pattern;
+	bool is_deleted;
+};
+
+/* Structure for "deny_rewrite" keyword. */
+struct tomoyo_no_rewrite_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *pattern;
+	bool is_deleted;
+};
+
+/* Keyword array for single path operations. */
+static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
+	[TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
+	[TOMOYO_TYPE_EXECUTE_ACL]    = "execute",
+	[TOMOYO_TYPE_READ_ACL]       = "read",
+	[TOMOYO_TYPE_WRITE_ACL]      = "write",
+	[TOMOYO_TYPE_CREATE_ACL]     = "create",
+	[TOMOYO_TYPE_UNLINK_ACL]     = "unlink",
+	[TOMOYO_TYPE_MKDIR_ACL]      = "mkdir",
+	[TOMOYO_TYPE_RMDIR_ACL]      = "rmdir",
+	[TOMOYO_TYPE_MKFIFO_ACL]     = "mkfifo",
+	[TOMOYO_TYPE_MKSOCK_ACL]     = "mksock",
+	[TOMOYO_TYPE_MKBLOCK_ACL]    = "mkblock",
+	[TOMOYO_TYPE_MKCHAR_ACL]     = "mkchar",
+	[TOMOYO_TYPE_TRUNCATE_ACL]   = "truncate",
+	[TOMOYO_TYPE_SYMLINK_ACL]    = "symlink",
+	[TOMOYO_TYPE_REWRITE_ACL]    = "rewrite",
+};
+
+/* Keyword array for double path operations. */
+static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
+	[TOMOYO_TYPE_LINK_ACL]    = "link",
+	[TOMOYO_TYPE_RENAME_ACL]  = "rename",
+};
+
+/**
+ * tomoyo_sp2keyword - Get the name of single path operation.
+ *
+ * @operation: Type of operation.
+ *
+ * Returns the name of single path operation.
+ */
+const char *tomoyo_sp2keyword(const u8 operation)
+{
+	return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
+		? tomoyo_sp_keyword[operation] : NULL;
+}
+
+/**
+ * tomoyo_dp2keyword - Get the name of double path operation.
+ *
+ * @operation: Type of operation.
+ *
+ * Returns the name of double path operation.
+ */
+const char *tomoyo_dp2keyword(const u8 operation)
+{
+	return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
+		? tomoyo_dp_keyword[operation] : NULL;
+}
+
+/**
+ * tomoyo_strendswith - Check whether the token ends with the given token.
+ *
+ * @name: The token to check.
+ * @tail: The token to find.
+ *
+ * Returns true if @name ends with @tail, false otherwise.
+ */
+static bool tomoyo_strendswith(const char *name, const char *tail)
+{
+	int len;
+
+	if (!name || !tail)
+		return false;
+	len = strlen(name) - strlen(tail);
+	return len >= 0 && !strcmp(name + len, tail);
+}
+
+/**
+ * tomoyo_get_path - Get realpath.
+ *
+ * @path: Pointer to "struct path".
+ *
+ * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
+ */
+static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
+{
+	int error;
+	struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
+
+	if (!buf)
+		return NULL;
+	/* Reserve one byte for appending "/". */
+	error = tomoyo_realpath_from_path2(path, buf->body,
+					   sizeof(buf->body) - 2);
+	if (!error) {
+		buf->head.name = buf->body;
+		tomoyo_fill_path_info(&buf->head);
+		return &buf->head;
+	}
+	tomoyo_free(buf);
+	return NULL;
+}
+
+/* Lock for domain->acl_info_list. */
+DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
+
+static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
+					 const char *filename2,
+					 struct tomoyo_domain_info *
+					 const domain, const bool is_delete);
+static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
+					 struct tomoyo_domain_info *
+					 const domain, const bool is_delete);
+
+/* The list for "struct tomoyo_globally_readable_file_entry". */
+static LIST_HEAD(tomoyo_globally_readable_list);
+static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
+
+/**
+ * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
+ *
+ * @filename:  Filename unconditionally permitted to open() for reading.
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_update_globally_readable_entry(const char *filename,
+						 const bool is_delete)
+{
+	struct tomoyo_globally_readable_file_entry *new_entry;
+	struct tomoyo_globally_readable_file_entry *ptr;
+	const struct tomoyo_path_info *saved_filename;
+	int error = -ENOMEM;
+
+	if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
+		return -EINVAL;
+	saved_filename = tomoyo_save_name(filename);
+	if (!saved_filename)
+		return -ENOMEM;
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_globally_readable_list_lock);
+	list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
+		if (ptr->filename != saved_filename)
+			continue;
+		ptr->is_deleted = is_delete;
+		error = 0;
+		goto out;
+	}
+	if (is_delete) {
+		error = -ENOENT;
+		goto out;
+	}
+	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
+	if (!new_entry)
+		goto out;
+	new_entry->filename = saved_filename;
+	list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
+	error = 0;
+ out:
+	up_write(&tomoyo_globally_readable_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return error;
+}
+
+/**
+ * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
+ *
+ * @filename: The filename to check.
+ *
+ * Returns true if any domain can open @filename for reading, false otherwise.
+ */
+static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
+					     filename)
+{
+	struct tomoyo_globally_readable_file_entry *ptr;
+	bool found = false;
+	down_read(&tomoyo_globally_readable_list_lock);
+	list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
+		if (!ptr->is_deleted &&
+		    tomoyo_path_matches_pattern(filename, ptr->filename)) {
+			found = true;
+			break;
+		}
+	}
+	up_read(&tomoyo_globally_readable_list_lock);
+	return found;
+}
+
+/**
+ * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list.
+ *
+ * @data:      String to parse.
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
+{
+	return tomoyo_update_globally_readable_entry(data, is_delete);
+}
+
+/**
+ * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns true on success, false otherwise.
+ */
+bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
+{
+	struct list_head *pos;
+	bool done = true;
+
+	down_read(&tomoyo_globally_readable_list_lock);
+	list_for_each_cookie(pos, head->read_var2,
+			     &tomoyo_globally_readable_list) {
+		struct tomoyo_globally_readable_file_entry *ptr;
+		ptr = list_entry(pos,
+				 struct tomoyo_globally_readable_file_entry,
+				 list);
+		if (ptr->is_deleted)
+			continue;
+		if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
+				      ptr->filename->name)) {
+			done = false;
+			break;
+		}
+	}
+	up_read(&tomoyo_globally_readable_list_lock);
+	return done;
+}
+
+/* The list for "struct tomoyo_pattern_entry". */
+static LIST_HEAD(tomoyo_pattern_list);
+static DECLARE_RWSEM(tomoyo_pattern_list_lock);
+
+/**
+ * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
+ *
+ * @pattern:   Pathname pattern.
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_update_file_pattern_entry(const char *pattern,
+					    const bool is_delete)
+{
+	struct tomoyo_pattern_entry *new_entry;
+	struct tomoyo_pattern_entry *ptr;
+	const struct tomoyo_path_info *saved_pattern;
+	int error = -ENOMEM;
+
+	if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
+		return -EINVAL;
+	saved_pattern = tomoyo_save_name(pattern);
+	if (!saved_pattern)
+		return -ENOMEM;
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_pattern_list_lock);
+	list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
+		if (saved_pattern != ptr->pattern)
+			continue;
+		ptr->is_deleted = is_delete;
+		error = 0;
+		goto out;
+	}
+	if (is_delete) {
+		error = -ENOENT;
+		goto out;
+	}
+	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
+	if (!new_entry)
+		goto out;
+	new_entry->pattern = saved_pattern;
+	list_add_tail(&new_entry->list, &tomoyo_pattern_list);
+	error = 0;
+ out:
+	up_write(&tomoyo_pattern_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return error;
+}
+
+/**
+ * tomoyo_get_file_pattern - Get patterned pathname.
+ *
+ * @filename: The filename to find patterned pathname.
+ *
+ * Returns pointer to pathname pattern if matched, @filename otherwise.
+ */
+static const struct tomoyo_path_info *
+tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
+{
+	struct tomoyo_pattern_entry *ptr;
+	const struct tomoyo_path_info *pattern = NULL;
+
+	down_read(&tomoyo_pattern_list_lock);
+	list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
+		if (ptr->is_deleted)
+			continue;
+		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
+			continue;
+		pattern = ptr->pattern;
+		if (tomoyo_strendswith(pattern->name, "/\\*")) {
+			/* Do nothing. Try to find the better match. */
+		} else {
+			/* This would be the better match. Use this. */
+			break;
+		}
+	}
+	up_read(&tomoyo_pattern_list_lock);
+	if (pattern)
+		filename = pattern;
+	return filename;
+}
+
+/**
+ * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list.
+ *
+ * @data:      String to parse.
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_write_pattern_policy(char *data, const bool is_delete)
+{
+	return tomoyo_update_file_pattern_entry(data, is_delete);
+}
+
+/**
+ * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns true on success, false otherwise.
+ */
+bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
+{
+	struct list_head *pos;
+	bool done = true;
+
+	down_read(&tomoyo_pattern_list_lock);
+	list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
+		struct tomoyo_pattern_entry *ptr;
+		ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
+		if (ptr->is_deleted)
+			continue;
+		if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN "%s\n",
+				      ptr->pattern->name)) {
+			done = false;
+			break;
+		}
+	}
+	up_read(&tomoyo_pattern_list_lock);
+	return done;
+}
+
+/* The list for "struct tomoyo_no_rewrite_entry". */
+static LIST_HEAD(tomoyo_no_rewrite_list);
+static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
+
+/**
+ * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
+ *
+ * @pattern:   Pathname pattern that are not rewritable by default.
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_update_no_rewrite_entry(const char *pattern,
+					  const bool is_delete)
+{
+	struct tomoyo_no_rewrite_entry *new_entry, *ptr;
+	const struct tomoyo_path_info *saved_pattern;
+	int error = -ENOMEM;
+
+	if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
+		return -EINVAL;
+	saved_pattern = tomoyo_save_name(pattern);
+	if (!saved_pattern)
+		return -ENOMEM;
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_no_rewrite_list_lock);
+	list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
+		if (ptr->pattern != saved_pattern)
+			continue;
+		ptr->is_deleted = is_delete;
+		error = 0;
+		goto out;
+	}
+	if (is_delete) {
+		error = -ENOENT;
+		goto out;
+	}
+	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
+	if (!new_entry)
+		goto out;
+	new_entry->pattern = saved_pattern;
+	list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
+	error = 0;
+ out:
+	up_write(&tomoyo_no_rewrite_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return error;
+}
+
+/**
+ * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
+ *
+ * @filename: Filename to check.
+ *
+ * Returns true if @filename is specified by "deny_rewrite" directive,
+ * false otherwise.
+ */
+static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
+{
+	struct tomoyo_no_rewrite_entry *ptr;
+	bool found = false;
+
+	down_read(&tomoyo_no_rewrite_list_lock);
+	list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
+		if (ptr->is_deleted)
+			continue;
+		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
+			continue;
+		found = true;
+		break;
+	}
+	up_read(&tomoyo_no_rewrite_list_lock);
+	return found;
+}
+
+/**
+ * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list.
+ *
+ * @data:      String to parse.
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
+{
+	return tomoyo_update_no_rewrite_entry(data, is_delete);
+}
+
+/**
+ * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns true on success, false otherwise.
+ */
+bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
+{
+	struct list_head *pos;
+	bool done = true;
+
+	down_read(&tomoyo_no_rewrite_list_lock);
+	list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
+		struct tomoyo_no_rewrite_entry *ptr;
+		ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
+		if (ptr->is_deleted)
+			continue;
+		if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE "%s\n",
+				      ptr->pattern->name)) {
+			done = false;
+			break;
+		}
+	}
+	up_read(&tomoyo_no_rewrite_list_lock);
+	return done;
+}
+
+/**
+ * tomoyo_update_file_acl - Update file's read/write/execute ACL.
+ *
+ * @filename:  Filename.
+ * @perm:      Permission (between 1 to 7).
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ *
+ * This is legacy support interface for older policy syntax.
+ * Current policy syntax uses "allow_read/write" instead of "6",
+ * "allow_read" instead of "4", "allow_write" instead of "2",
+ * "allow_execute" instead of "1".
+ */
+static int tomoyo_update_file_acl(const char *filename, u8 perm,
+				  struct tomoyo_domain_info * const domain,
+				  const bool is_delete)
+{
+	if (perm > 7 || !perm) {
+		printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
+		       __func__, perm, filename);
+		return -EINVAL;
+	}
+	if (filename[0] != '@' && tomoyo_strendswith(filename, "/"))
+		/*
+		 * Only 'allow_mkdir' and 'allow_rmdir' are valid for
+		 * directory permissions.
+		 */
+		return 0;
+	if (perm & 4)
+		tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
+					      domain, is_delete);
+	if (perm & 2)
+		tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
+					      domain, is_delete);
+	if (perm & 1)
+		tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
+					      filename, domain, is_delete);
+	return 0;
+}
+
+/**
+ * tomoyo_check_single_path_acl2 - Check permission for single path operation.
+ *
+ * @domain:          Pointer to "struct tomoyo_domain_info".
+ * @filename:        Filename to check.
+ * @perm:            Permission.
+ * @may_use_pattern: True if patterned ACL is permitted.
+ *
+ * Returns 0 on success, -EPERM otherwise.
+ */
+static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
+					 domain,
+					 const struct tomoyo_path_info *
+					 filename,
+					 const u16 perm,
+					 const bool may_use_pattern)
+{
+	struct tomoyo_acl_info *ptr;
+	int error = -EPERM;
+
+	down_read(&tomoyo_domain_acl_info_list_lock);
+	list_for_each_entry(ptr, &domain->acl_info_list, list) {
+		struct tomoyo_single_path_acl_record *acl;
+		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
+			continue;
+		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
+				   head);
+		if (!(acl->perm & perm))
+			continue;
+		if (may_use_pattern || !acl->filename->is_patterned) {
+			if (!tomoyo_path_matches_pattern(filename,
+							 acl->filename))
+				continue;
+		} else {
+			continue;
+		}
+		error = 0;
+		break;
+	}
+	up_read(&tomoyo_domain_acl_info_list_lock);
+	return error;
+}
+
+/**
+ * tomoyo_check_file_acl - Check permission for opening files.
+ *
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @filename:  Filename to check.
+ * @operation: Mode ("read" or "write" or "read/write" or "execute").
+ *
+ * Returns 0 on success, -EPERM otherwise.
+ */
+static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
+				 const struct tomoyo_path_info *filename,
+				 const u8 operation)
+{
+	u16 perm = 0;
+
+	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
+		return 0;
+	if (operation == 6)
+		perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
+	else if (operation == 4)
+		perm = 1 << TOMOYO_TYPE_READ_ACL;
+	else if (operation == 2)
+		perm = 1 << TOMOYO_TYPE_WRITE_ACL;
+	else if (operation == 1)
+		perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
+	else
+		BUG();
+	return tomoyo_check_single_path_acl2(domain, filename, perm,
+					     operation != 1);
+}
+
+/**
+ * tomoyo_check_file_perm2 - Check permission for opening files.
+ *
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @filename:  Filename to check.
+ * @perm:      Mode ("read" or "write" or "read/write" or "execute").
+ * @operation: Operation name passed used for verbose mode.
+ * @mode:      Access control mode.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
+				   const struct tomoyo_path_info *filename,
+				   const u8 perm, const char *operation,
+				   const u8 mode)
+{
+	const bool is_enforce = (mode == 3);
+	const char *msg = "<unknown>";
+	int error = 0;
+
+	if (!filename)
+		return 0;
+	error = tomoyo_check_file_acl(domain, filename, perm);
+	if (error && perm == 4 &&
+	    (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
+	    && tomoyo_is_globally_readable_file(filename))
+		error = 0;
+	if (perm == 6)
+		msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
+	else if (perm == 4)
+		msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
+	else if (perm == 2)
+		msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
+	else if (perm == 1)
+		msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
+	else
+		BUG();
+	if (!error)
+		return 0;
+	if (tomoyo_verbose_mode(domain))
+		printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied "
+		       "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
+		       filename->name, tomoyo_get_last_name(domain));
+	if (is_enforce)
+		return error;
+	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
+		/* Don't use patterns for execute permission. */
+		const struct tomoyo_path_info *patterned_file = (perm != 1) ?
+			tomoyo_get_file_pattern(filename) : filename;
+		tomoyo_update_file_acl(patterned_file->name, perm,
+				       domain, false);
+	}
+	return 0;
+}
+
+/**
+ * tomoyo_write_file_policy - Update file related list.
+ *
+ * @data:      String to parse.
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
+			     const bool is_delete)
+{
+	char *filename = strchr(data, ' ');
+	char *filename2;
+	unsigned int perm;
+	u8 type;
+
+	if (!filename)
+		return -EINVAL;
+	*filename++ = '\0';
+	if (sscanf(data, "%u", &perm) == 1)
+		return tomoyo_update_file_acl(filename, (u8) perm, domain,
+					      is_delete);
+	if (strncmp(data, "allow_", 6))
+		goto out;
+	data += 6;
+	for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
+		if (strcmp(data, tomoyo_sp_keyword[type]))
+			continue;
+		return tomoyo_update_single_path_acl(type, filename,
+						     domain, is_delete);
+	}
+	filename2 = strchr(filename, ' ');
+	if (!filename2)
+		goto out;
+	*filename2++ = '\0';
+	for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
+		if (strcmp(data, tomoyo_dp_keyword[type]))
+			continue;
+		return tomoyo_update_double_path_acl(type, filename, filename2,
+						     domain, is_delete);
+	}
+ out:
+	return -EINVAL;
+}
+
+/**
+ * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list.
+ *
+ * @type:      Type of operation.
+ * @filename:  Filename.
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
+					 struct tomoyo_domain_info *
+					 const domain, const bool is_delete)
+{
+	static const u16 rw_mask =
+		(1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
+	const struct tomoyo_path_info *saved_filename;
+	struct tomoyo_acl_info *ptr;
+	struct tomoyo_single_path_acl_record *acl;
+	int error = -ENOMEM;
+	const u16 perm = 1 << type;
+
+	if (!domain)
+		return -EINVAL;
+	if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
+		return -EINVAL;
+	saved_filename = tomoyo_save_name(filename);
+	if (!saved_filename)
+		return -ENOMEM;
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_domain_acl_info_list_lock);
+	if (is_delete)
+		goto delete;
+	list_for_each_entry(ptr, &domain->acl_info_list, list) {
+		if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
+			continue;
+		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
+				   head);
+		if (acl->filename != saved_filename)
+			continue;
+		/* Special case. Clear all bits if marked as deleted. */
+		if (ptr->type & TOMOYO_ACL_DELETED)
+			acl->perm = 0;
+		acl->perm |= perm;
+		if ((acl->perm & rw_mask) == rw_mask)
+			acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
+		else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
+			acl->perm |= rw_mask;
+		ptr->type &= ~TOMOYO_ACL_DELETED;
+		error = 0;
+		goto out;
+	}
+	/* Not found. Append it to the tail. */
+	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
+	if (!acl)
+		goto out;
+	acl->perm = perm;
+	if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
+		acl->perm |= rw_mask;
+	acl->filename = saved_filename;
+	list_add_tail(&acl->head.list, &domain->acl_info_list);
+	error = 0;
+	goto out;
+ delete:
+	error = -ENOENT;
+	list_for_each_entry(ptr, &domain->acl_info_list, list) {
+		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
+			continue;
+		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
+				   head);
+		if (acl->filename != saved_filename)
+			continue;
+		acl->perm &= ~perm;
+		if ((acl->perm & rw_mask) != rw_mask)
+			acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
+		else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
+			acl->perm &= ~rw_mask;
+		if (!acl->perm)
+			ptr->type |= TOMOYO_ACL_DELETED;
+		error = 0;
+		break;
+	}
+ out:
+	up_write(&tomoyo_domain_acl_info_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return error;
+}
+
+/**
+ * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list.
+ *
+ * @type:      Type of operation.
+ * @filename1: First filename.
+ * @filename2: Second filename.
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @is_delete: True if it is a delete request.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
+					 const char *filename2,
+					 struct tomoyo_domain_info *
+					 const domain, const bool is_delete)
+{
+	const struct tomoyo_path_info *saved_filename1;
+	const struct tomoyo_path_info *saved_filename2;
+	struct tomoyo_acl_info *ptr;
+	struct tomoyo_double_path_acl_record *acl;
+	int error = -ENOMEM;
+	const u8 perm = 1 << type;
+
+	if (!domain)
+		return -EINVAL;
+	if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
+	    !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
+		return -EINVAL;
+	saved_filename1 = tomoyo_save_name(filename1);
+	saved_filename2 = tomoyo_save_name(filename2);
+	if (!saved_filename1 || !saved_filename2)
+		return -ENOMEM;
+	/***** EXCLUSIVE SECTION START *****/
+	down_write(&tomoyo_domain_acl_info_list_lock);
+	if (is_delete)
+		goto delete;
+	list_for_each_entry(ptr, &domain->acl_info_list, list) {
+		if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
+			continue;
+		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
+				   head);
+		if (acl->filename1 != saved_filename1 ||
+		    acl->filename2 != saved_filename2)
+			continue;
+		/* Special case. Clear all bits if marked as deleted. */
+		if (ptr->type & TOMOYO_ACL_DELETED)
+			acl->perm = 0;
+		acl->perm |= perm;
+		ptr->type &= ~TOMOYO_ACL_DELETED;
+		error = 0;
+		goto out;
+	}
+	/* Not found. Append it to the tail. */
+	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
+	if (!acl)
+		goto out;
+	acl->perm = perm;
+	acl->filename1 = saved_filename1;
+	acl->filename2 = saved_filename2;
+	list_add_tail(&acl->head.list, &domain->acl_info_list);
+	error = 0;
+	goto out;
+ delete:
+	error = -ENOENT;
+	list_for_each_entry(ptr, &domain->acl_info_list, list) {
+		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
+			continue;
+		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
+				   head);
+		if (acl->filename1 != saved_filename1 ||
+		    acl->filename2 != saved_filename2)
+			continue;
+		acl->perm &= ~perm;
+		if (!acl->perm)
+			ptr->type |= TOMOYO_ACL_DELETED;
+		error = 0;
+		break;
+	}
+ out:
+	up_write(&tomoyo_domain_acl_info_list_lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return error;
+}
+
+/**
+ * tomoyo_check_single_path_acl - Check permission for single path operation.
+ *
+ * @domain:   Pointer to "struct tomoyo_domain_info".
+ * @type:     Type of operation.
+ * @filename: Filename to check.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
+					const u8 type,
+					const struct tomoyo_path_info *filename)
+{
+	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
+		return 0;
+	return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
+}
+
+/**
+ * tomoyo_check_double_path_acl - Check permission for double path operation.
+ *
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @type:      Type of operation.
+ * @filename1: First filename to check.
+ * @filename2: Second filename to check.
+ *
+ * Returns 0 on success, -EPERM otherwise.
+ */
+static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
+					const u8 type,
+					const struct tomoyo_path_info *
+					filename1,
+					const struct tomoyo_path_info *
+					filename2)
+{
+	struct tomoyo_acl_info *ptr;
+	const u8 perm = 1 << type;
+	int error = -EPERM;
+
+	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
+		return 0;
+	down_read(&tomoyo_domain_acl_info_list_lock);
+	list_for_each_entry(ptr, &domain->acl_info_list, list) {
+		struct tomoyo_double_path_acl_record *acl;
+		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
+			continue;
+		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
+				   head);
+		if (!(acl->perm & perm))
+			continue;
+		if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
+			continue;
+		if (!tomoyo_path_matches_pattern(filename2, acl->filename2))
+			continue;
+		error = 0;
+		break;
+	}
+	up_read(&tomoyo_domain_acl_info_list_lock);
+	return error;
+}
+
+/**
+ * tomoyo_check_single_path_permission2 - Check permission for single path operation.
+ *
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @operation: Type of operation.
+ * @filename:  Filename to check.
+ * @mode:      Access control mode.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
+						const domain, u8 operation,
+						const struct tomoyo_path_info *
+						filename, const u8 mode)
+{
+	const char *msg;
+	int error;
+	const bool is_enforce = (mode == 3);
+
+	if (!mode)
+		return 0;
+ next:
+	error = tomoyo_check_single_path_acl(domain, operation, filename);
+	msg = tomoyo_sp2keyword(operation);
+	if (!error)
+		goto ok;
+	if (tomoyo_verbose_mode(domain))
+		printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n",
+		       tomoyo_get_msg(is_enforce), msg, filename->name,
+		       tomoyo_get_last_name(domain));
+	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
+		const char *name = tomoyo_get_file_pattern(filename)->name;
+		tomoyo_update_single_path_acl(operation, name, domain, false);
+	}
+	if (!is_enforce)
+		error = 0;
+ ok:
+	/*
+	 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
+	 * we need to check "allow_rewrite" permission if the filename is
+	 * specified by "deny_rewrite" keyword.
+	 */
+	if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
+	    tomoyo_is_no_rewrite_file(filename)) {
+		operation = TOMOYO_TYPE_REWRITE_ACL;
+		goto next;
+	}
+	return error;
+}
+
+/**
+ * tomoyo_check_file_perm - Check permission for sysctl()'s "read" and "write".
+ *
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @filename:  Filename to check.
+ * @perm:      Mode ("read" or "write" or "read/write").
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
+			   const char *filename, const u8 perm)
+{
+	struct tomoyo_path_info name;
+	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
+
+	if (!mode)
+		return 0;
+	name.name = filename;
+	tomoyo_fill_path_info(&name);
+	return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
+}
+
+/**
+ * tomoyo_check_exec_perm - Check permission for "execute".
+ *
+ * @domain:   Pointer to "struct tomoyo_domain_info".
+ * @filename: Check permission for "execute".
+ * @tmp:      Buffer for temporary use.
+ *
+ * Returns 0 on success, negativevalue otherwise.
+ */
+int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
+			   const struct tomoyo_path_info *filename,
+			   struct tomoyo_page_buffer *tmp)
+{
+	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
+
+	if (!mode)
+		return 0;
+	return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode);
+}
+
+/**
+ * tomoyo_check_open_permission - Check permission for "read" and "write".
+ *
+ * @domain: Pointer to "struct tomoyo_domain_info".
+ * @path:   Pointer to "struct path".
+ * @flag:   Flags for open().
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
+				 struct path *path, const int flag)
+{
+	const u8 acc_mode = ACC_MODE(flag);
+	int error = -ENOMEM;
+	struct tomoyo_path_info *buf;
+	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
+	const bool is_enforce = (mode == 3);
+
+	if (!mode || !path->mnt)
+		return 0;
+	if (acc_mode == 0)
+		return 0;
+	if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
+		/*
+		 * I don't check directories here because mkdir() and rmdir()
+		 * don't call me.
+		 */
+		return 0;
+	buf = tomoyo_get_path(path);
+	if (!buf)
+		goto out;
+	error = 0;
+	/*
+	 * If the filename is specified by "deny_rewrite" keyword,
+	 * we need to check "allow_rewrite" permission when the filename is not
+	 * opened for append mode or the filename is truncated at open time.
+	 */
+	if ((acc_mode & MAY_WRITE) &&
+	    ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
+	    (tomoyo_is_no_rewrite_file(buf))) {
+		error = tomoyo_check_single_path_permission2(domain,
+						     TOMOYO_TYPE_REWRITE_ACL,
+							     buf, mode);
+	}
+	if (!error)
+		error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
+						mode);
+	if (!error && (flag & O_TRUNC))
+		error = tomoyo_check_single_path_permission2(domain,
+						     TOMOYO_TYPE_TRUNCATE_ACL,
+							     buf, mode);
+ out:
+	tomoyo_free(buf);
+	if (!is_enforce)
+		error = 0;
+	return error;
+}
+
+/**
+ * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
+ *
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @operation: Type of operation.
+ * @path:      Pointer to "struct path".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
+			    const u8 operation, struct path *path)
+{
+	int error = -ENOMEM;
+	struct tomoyo_path_info *buf;
+	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
+	const bool is_enforce = (mode == 3);
+
+	if (!mode || !path->mnt)
+		return 0;
+	buf = tomoyo_get_path(path);
+	if (!buf)
+		goto out;
+	switch (operation) {
+	case TOMOYO_TYPE_MKDIR_ACL:
+	case TOMOYO_TYPE_RMDIR_ACL:
+		if (!buf->is_dir) {
+			/*
+			 * tomoyo_get_path() reserves space for appending "/."
+			 */
+			strcat((char *) buf->name, "/");
+			tomoyo_fill_path_info(buf);
+		}
+	}
+	error = tomoyo_check_single_path_permission2(domain, operation, buf,
+						     mode);
+ out:
+	tomoyo_free(buf);
+	if (!is_enforce)
+		error = 0;
+	return error;
+}
+
+/**
+ * tomoyo_check_rewrite_permission - Check permission for "rewrite".
+ *
+ * @domain: Pointer to "struct tomoyo_domain_info".
+ * @filp: Pointer to "struct file".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
+				    struct file *filp)
+{
+	int error = -ENOMEM;
+	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
+	const bool is_enforce = (mode == 3);
+	struct tomoyo_path_info *buf;
+
+	if (!mode || !filp->f_path.mnt)
+		return 0;
+	buf = tomoyo_get_path(&filp->f_path);
+	if (!buf)
+		goto out;
+	if (!tomoyo_is_no_rewrite_file(buf)) {
+		error = 0;
+		goto out;
+	}
+	error = tomoyo_check_single_path_permission2(domain,
+						     TOMOYO_TYPE_REWRITE_ACL,
+						     buf, mode);
+ out:
+	tomoyo_free(buf);
+	if (!is_enforce)
+		error = 0;
+	return error;
+}
+
+/**
+ * tomoyo_check_2path_perm - Check permission for "rename" and "link".
+ *
+ * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @operation: Type of operation.
+ * @path1:      Pointer to "struct path".
+ * @path2:      Pointer to "struct path".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
+			    const u8 operation, struct path *path1,
+			    struct path *path2)
+{
+	int error = -ENOMEM;
+	struct tomoyo_path_info *buf1, *buf2;
+	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
+	const bool is_enforce = (mode == 3);
+	const char *msg;
+
+	if (!mode || !path1->mnt || !path2->mnt)
+		return 0;
+	buf1 = tomoyo_get_path(path1);
+	buf2 = tomoyo_get_path(path2);
+	if (!buf1 || !buf2)
+		goto out;
+	{
+		struct dentry *dentry = path1->dentry;
+		if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
+			/*
+			 * tomoyo_get_path() reserves space for appending "/."
+			 */
+			if (!buf1->is_dir) {
+				strcat((char *) buf1->name, "/");
+				tomoyo_fill_path_info(buf1);
+			}
+			if (!buf2->is_dir) {
+				strcat((char *) buf2->name, "/");
+				tomoyo_fill_path_info(buf2);
+			}
+		}
+	}
+	error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
+	msg = tomoyo_dp2keyword(operation);
+	if (!error)
+		goto out;
+	if (tomoyo_verbose_mode(domain))
+		printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' "
+		       "denied for %s\n", tomoyo_get_msg(is_enforce),
+		       msg, buf1->name, buf2->name,
+		       tomoyo_get_last_name(domain));
+	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
+		const char *name1 = tomoyo_get_file_pattern(buf1)->name;
+		const char *name2 = tomoyo_get_file_pattern(buf2)->name;
+		tomoyo_update_double_path_acl(operation, name1, name2, domain,
+					      false);
+	}
+ out:
+	tomoyo_free(buf1);
+	tomoyo_free(buf2);
+	if (!is_enforce)
+		error = 0;
+	return error;
+}
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
new file mode 100644
index 0000000..d47f16b
--- /dev/null
+++ b/security/tomoyo/realpath.c
@@ -0,0 +1,482 @@
+/*
+ * security/tomoyo/realpath.c
+ *
+ * Get the canonicalized absolute pathnames. The basis for TOMOYO.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/mount.h>
+#include <linux/mnt_namespace.h>
+#include "common.h"
+#include "realpath.h"
+
+/**
+ * tomoyo_encode: Convert binary string to ascii string.
+ *
+ * @buffer:  Buffer for ASCII string.
+ * @buflen:  Size of @buffer.
+ * @str:     Binary string.
+ *
+ * Returns 0 on success, -ENOMEM otherwise.
+ */
+int tomoyo_encode(char *buffer, int buflen, const char *str)
+{
+	while (1) {
+		const unsigned char c = *(unsigned char *) str++;
+
+		if (tomoyo_is_valid(c)) {
+			if (--buflen <= 0)
+				break;
+			*buffer++ = (char) c;
+			if (c != '\\')
+				continue;
+			if (--buflen <= 0)
+				break;
+			*buffer++ = (char) c;
+			continue;
+		}
+		if (!c) {
+			if (--buflen <= 0)
+				break;
+			*buffer = '\0';
+			return 0;
+		}
+		buflen -= 4;
+		if (buflen <= 0)
+			break;
+		*buffer++ = '\\';
+		*buffer++ = (c >> 6) + '0';
+		*buffer++ = ((c >> 3) & 7) + '0';
+		*buffer++ = (c & 7) + '0';
+	}
+	return -ENOMEM;
+}
+
+/**
+ * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
+ *
+ * @path:        Pointer to "struct path".
+ * @newname:     Pointer to buffer to return value in.
+ * @newname_len: Size of @newname.
+ *
+ * Returns 0 on success, negative value otherwise.
+ *
+ * If dentry is a directory, trailing '/' is appended.
+ * Characters out of 0x20 < c < 0x7F range are converted to
+ * \ooo style octal string.
+ * Character \ is converted to \\ string.
+ */
+int tomoyo_realpath_from_path2(struct path *path, char *newname,
+			       int newname_len)
+{
+	int error = -ENOMEM;
+	struct dentry *dentry = path->dentry;
+	char *sp;
+
+	if (!dentry || !path->mnt || !newname || newname_len <= 2048)
+		return -EINVAL;
+	if (dentry->d_op && dentry->d_op->d_dname) {
+		/* For "socket:[\$]" and "pipe:[\$]". */
+		static const int offset = 1536;
+		sp = dentry->d_op->d_dname(dentry, newname + offset,
+					   newname_len - offset);
+	} else {
+		/* Taken from d_namespace_path(). */
+		struct path root;
+		struct path ns_root = { };
+		struct path tmp;
+
+		read_lock(&current->fs->lock);
+		root = current->fs->root;
+		path_get(&root);
+		read_unlock(&current->fs->lock);
+		spin_lock(&vfsmount_lock);
+		if (root.mnt && root.mnt->mnt_ns)
+			ns_root.mnt = mntget(root.mnt->mnt_ns->root);
+		if (ns_root.mnt)
+			ns_root.dentry = dget(ns_root.mnt->mnt_root);
+		spin_unlock(&vfsmount_lock);
+		spin_lock(&dcache_lock);
+		tmp = ns_root;
+		sp = __d_path(path, &tmp, newname, newname_len);
+		spin_unlock(&dcache_lock);
+		path_put(&root);
+		path_put(&ns_root);
+	}
+	if (IS_ERR(sp))
+		error = PTR_ERR(sp);
+	else
+		error = tomoyo_encode(newname, sp - newname, sp);
+	/* Append trailing '/' if dentry is a directory. */
+	if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
+	    && *newname) {
+		sp = newname + strlen(newname);
+		if (*(sp - 1) != '/') {
+			if (sp < newname + newname_len - 4) {
+				*sp++ = '/';
+				*sp = '\0';
+			} else {
+				error = -ENOMEM;
+			}
+		}
+	}
+	if (error)
+		printk(KERN_WARNING "tomoyo_realpath: Pathname too long.\n");
+	return error;
+}
+
+/**
+ * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
+ *
+ * @path: Pointer to "struct path".
+ *
+ * Returns the realpath of the given @path on success, NULL otherwise.
+ *
+ * These functions use tomoyo_alloc(), so the caller must call tomoyo_free()
+ * if these functions didn't return NULL.
+ */
+char *tomoyo_realpath_from_path(struct path *path)
+{
+	char *buf = tomoyo_alloc(sizeof(struct tomoyo_page_buffer));
+
+	BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
+		     <= TOMOYO_MAX_PATHNAME_LEN - 1);
+	if (!buf)
+		return NULL;
+	if (tomoyo_realpath_from_path2(path, buf,
+				       TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
+		return buf;
+	tomoyo_free(buf);
+	return NULL;
+}
+
+/**
+ * tomoyo_realpath - Get realpath of a pathname.
+ *
+ * @pathname: The pathname to solve.
+ *
+ * Returns the realpath of @pathname on success, NULL otherwise.
+ */
+char *tomoyo_realpath(const char *pathname)
+{
+	struct nameidata nd;
+
+	if (pathname && path_lookup(pathname, LOOKUP_FOLLOW, &nd) == 0) {
+		char *buf = tomoyo_realpath_from_path(&nd.path);
+		path_put(&nd.path);
+		return buf;
+	}
+	return NULL;
+}
+
+/**
+ * tomoyo_realpath_nofollow - Get realpath of a pathname.
+ *
+ * @pathname: The pathname to solve.
+ *
+ * Returns the realpath of @pathname on success, NULL otherwise.
+ */
+char *tomoyo_realpath_nofollow(const char *pathname)
+{
+	struct nameidata nd;
+
+	if (pathname && path_lookup(pathname, 0, &nd) == 0) {
+		char *buf = tomoyo_realpath_from_path(&nd.path);
+		path_put(&nd.path);
+		return buf;
+	}
+	return NULL;
+}
+
+/* Memory allocated for non-string data. */
+static unsigned int tomoyo_allocated_memory_for_elements;
+/* Quota for holding non-string data. */
+static unsigned int tomoyo_quota_for_elements;
+
+/**
+ * tomoyo_alloc_element - Allocate permanent memory for structures.
+ *
+ * @size: Size in bytes.
+ *
+ * Returns pointer to allocated memory on success, NULL otherwise.
+ *
+ * Memory has to be zeroed.
+ * The RAM is chunked, so NEVER try to kfree() the returned pointer.
+ */
+void *tomoyo_alloc_element(const unsigned int size)
+{
+	static char *buf;
+	static DEFINE_MUTEX(lock);
+	static unsigned int buf_used_len = PATH_MAX;
+	char *ptr = NULL;
+	/*Assumes sizeof(void *) >= sizeof(long) is true. */
+	const unsigned int word_aligned_size
+		= roundup(size, max(sizeof(void *), sizeof(long)));
+	if (word_aligned_size > PATH_MAX)
+		return NULL;
+	/***** EXCLUSIVE SECTION START *****/
+	mutex_lock(&lock);
+	if (buf_used_len + word_aligned_size > PATH_MAX) {
+		if (!tomoyo_quota_for_elements ||
+		    tomoyo_allocated_memory_for_elements
+		    + PATH_MAX <= tomoyo_quota_for_elements)
+			ptr = kzalloc(PATH_MAX, GFP_KERNEL);
+		if (!ptr) {
+			printk(KERN_WARNING "ERROR: Out of memory "
+			       "for tomoyo_alloc_element().\n");
+			if (!tomoyo_policy_loaded)
+				panic("MAC Initialization failed.\n");
+		} else {
+			buf = ptr;
+			tomoyo_allocated_memory_for_elements += PATH_MAX;
+			buf_used_len = word_aligned_size;
+			ptr = buf;
+		}
+	} else if (word_aligned_size) {
+		int i;
+		ptr = buf + buf_used_len;
+		buf_used_len += word_aligned_size;
+		for (i = 0; i < word_aligned_size; i++) {
+			if (!ptr[i])
+				continue;
+			printk(KERN_ERR "WARNING: Reserved memory was tainted! "
+			       "The system might go wrong.\n");
+			ptr[i] = '\0';
+		}
+	}
+	mutex_unlock(&lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return ptr;
+}
+
+/* Memory allocated for string data in bytes. */
+static unsigned int tomoyo_allocated_memory_for_savename;
+/* Quota for holding string data in bytes. */
+static unsigned int tomoyo_quota_for_savename;
+
+/*
+ * TOMOYO uses this hash only when appending a string into the string
+ * table. Frequency of appending strings is very low. So we don't need
+ * large (e.g. 64k) hash size. 256 will be sufficient.
+ */
+#define TOMOYO_MAX_HASH 256
+
+/* Structure for string data. */
+struct tomoyo_name_entry {
+	struct list_head list;
+	struct tomoyo_path_info entry;
+};
+
+/* Structure for available memory region. */
+struct tomoyo_free_memory_block_list {
+	struct list_head list;
+	char *ptr;             /* Pointer to a free area. */
+	int len;               /* Length of the area.     */
+};
+
+/*
+ * The list for "struct tomoyo_name_entry".
+ *
+ * This list is updated only inside tomoyo_save_name(), thus
+ * no global mutex exists.
+ */
+static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
+
+/**
+ * tomoyo_save_name - Allocate permanent memory for string data.
+ *
+ * @name: The string to store into the permernent memory.
+ *
+ * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
+ *
+ * The RAM is shared, so NEVER try to modify or kfree() the returned name.
+ */
+const struct tomoyo_path_info *tomoyo_save_name(const char *name)
+{
+	static LIST_HEAD(fmb_list);
+	static DEFINE_MUTEX(lock);
+	struct tomoyo_name_entry *ptr;
+	unsigned int hash;
+	/* fmb contains available size in bytes.
+	   fmb is removed from the fmb_list when fmb->len becomes 0. */
+	struct tomoyo_free_memory_block_list *fmb;
+	int len;
+	char *cp;
+
+	if (!name)
+		return NULL;
+	len = strlen(name) + 1;
+	if (len > TOMOYO_MAX_PATHNAME_LEN) {
+		printk(KERN_WARNING "ERROR: Name too long "
+		       "for tomoyo_save_name().\n");
+		return NULL;
+	}
+	hash = full_name_hash((const unsigned char *) name, len - 1);
+	/***** EXCLUSIVE SECTION START *****/
+	mutex_lock(&lock);
+	list_for_each_entry(ptr, &tomoyo_name_list[hash % TOMOYO_MAX_HASH],
+			     list) {
+		if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
+			goto out;
+	}
+	list_for_each_entry(fmb, &fmb_list, list) {
+		if (len <= fmb->len)
+			goto ready;
+	}
+	if (!tomoyo_quota_for_savename ||
+	    tomoyo_allocated_memory_for_savename + PATH_MAX
+	    <= tomoyo_quota_for_savename)
+		cp = kzalloc(PATH_MAX, GFP_KERNEL);
+	else
+		cp = NULL;
+	fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
+	if (!cp || !fmb) {
+		kfree(cp);
+		kfree(fmb);
+		printk(KERN_WARNING "ERROR: Out of memory "
+		       "for tomoyo_save_name().\n");
+		if (!tomoyo_policy_loaded)
+			panic("MAC Initialization failed.\n");
+		ptr = NULL;
+		goto out;
+	}
+	tomoyo_allocated_memory_for_savename += PATH_MAX;
+	list_add(&fmb->list, &fmb_list);
+	fmb->ptr = cp;
+	fmb->len = PATH_MAX;
+ ready:
+	ptr = tomoyo_alloc_element(sizeof(*ptr));
+	if (!ptr)
+		goto out;
+	ptr->entry.name = fmb->ptr;
+	memmove(fmb->ptr, name, len);
+	tomoyo_fill_path_info(&ptr->entry);
+	fmb->ptr += len;
+	fmb->len -= len;
+	list_add_tail(&ptr->list, &tomoyo_name_list[hash % TOMOYO_MAX_HASH]);
+	if (fmb->len == 0) {
+		list_del(&fmb->list);
+		kfree(fmb);
+	}
+ out:
+	mutex_unlock(&lock);
+	/***** EXCLUSIVE SECTION END *****/
+	return ptr ? &ptr->entry : NULL;
+}
+
+/**
+ * tomoyo_realpath_init - Initialize realpath related code.
+ */
+void __init tomoyo_realpath_init(void)
+{
+	int i;
+
+	BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
+	for (i = 0; i < TOMOYO_MAX_HASH; i++)
+		INIT_LIST_HEAD(&tomoyo_name_list[i]);
+	INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
+	tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME);
+	list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
+	down_read(&tomoyo_domain_list_lock);
+	if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
+		panic("Can't register tomoyo_kernel_domain");
+	up_read(&tomoyo_domain_list_lock);
+}
+
+/* Memory allocated for temporary purpose. */
+static atomic_t tomoyo_dynamic_memory_size;
+
+/**
+ * tomoyo_alloc - Allocate memory for temporary purpose.
+ *
+ * @size: Size in bytes.
+ *
+ * Returns pointer to allocated memory on success, NULL otherwise.
+ */
+void *tomoyo_alloc(const size_t size)
+{
+	void *p = kzalloc(size, GFP_KERNEL);
+	if (p)
+		atomic_add(ksize(p), &tomoyo_dynamic_memory_size);
+	return p;
+}
+
+/**
+ * tomoyo_free - Release memory allocated by tomoyo_alloc().
+ *
+ * @p: Pointer returned by tomoyo_alloc(). May be NULL.
+ *
+ * Returns nothing.
+ */
+void tomoyo_free(const void *p)
+{
+	if (p) {
+		atomic_sub(ksize(p), &tomoyo_dynamic_memory_size);
+		kfree(p);
+	}
+}
+
+/**
+ * tomoyo_read_memory_counter - Check for memory usage in bytes.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns memory usage.
+ */
+int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
+{
+	if (!head->read_eof) {
+		const unsigned int shared
+			= tomoyo_allocated_memory_for_savename;
+		const unsigned int private
+			= tomoyo_allocated_memory_for_elements;
+		const unsigned int dynamic
+			= atomic_read(&tomoyo_dynamic_memory_size);
+		char buffer[64];
+
+		memset(buffer, 0, sizeof(buffer));
+		if (tomoyo_quota_for_savename)
+			snprintf(buffer, sizeof(buffer) - 1,
+				 "   (Quota: %10u)",
+				 tomoyo_quota_for_savename);
+		else
+			buffer[0] = '\0';
+		tomoyo_io_printf(head, "Shared:  %10u%s\n", shared, buffer);
+		if (tomoyo_quota_for_elements)
+			snprintf(buffer, sizeof(buffer) - 1,
+				 "   (Quota: %10u)",
+				 tomoyo_quota_for_elements);
+		else
+			buffer[0] = '\0';
+		tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer);
+		tomoyo_io_printf(head, "Dynamic: %10u\n", dynamic);
+		tomoyo_io_printf(head, "Total:   %10u\n",
+				 shared + private + dynamic);
+		head->read_eof = true;
+	}
+	return 0;
+}
+
+/**
+ * tomoyo_write_memory_quota - Set memory quota.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0.
+ */
+int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
+{
+	char *data = head->write_buf;
+	unsigned int size;
+
+	if (sscanf(data, "Shared: %u", &size) == 1)
+		tomoyo_quota_for_savename = size;
+	else if (sscanf(data, "Private: %u", &size) == 1)
+		tomoyo_quota_for_elements = size;
+	return 0;
+}
diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h
new file mode 100644
index 0000000..7ec9fc9c
--- /dev/null
+++ b/security/tomoyo/realpath.h
@@ -0,0 +1,66 @@
+/*
+ * security/tomoyo/realpath.h
+ *
+ * Get the canonicalized absolute pathnames. The basis for TOMOYO.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#ifndef _SECURITY_TOMOYO_REALPATH_H
+#define _SECURITY_TOMOYO_REALPATH_H
+
+struct path;
+struct tomoyo_path_info;
+struct tomoyo_io_buffer;
+
+/* Convert binary string to ascii string. */
+int tomoyo_encode(char *buffer, int buflen, const char *str);
+
+/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
+int tomoyo_realpath_from_path2(struct path *path, char *newname,
+			       int newname_len);
+
+/*
+ * Returns realpath(3) of the given pathname but ignores chroot'ed root.
+ * These functions use tomoyo_alloc(), so the caller must call tomoyo_free()
+ * if these functions didn't return NULL.
+ */
+char *tomoyo_realpath(const char *pathname);
+/*
+ * Same with tomoyo_realpath() except that it doesn't follow the final symlink.
+ */
+char *tomoyo_realpath_nofollow(const char *pathname);
+/* Same with tomoyo_realpath() except that the pathname is already solved. */
+char *tomoyo_realpath_from_path(struct path *path);
+
+/*
+ * Allocate memory for ACL entry.
+ * The RAM is chunked, so NEVER try to kfree() the returned pointer.
+ */
+void *tomoyo_alloc_element(const unsigned int size);
+
+/*
+ * Keep the given name on the RAM.
+ * The RAM is shared, so NEVER try to modify or kfree() the returned name.
+ */
+const struct tomoyo_path_info *tomoyo_save_name(const char *name);
+
+/* Allocate memory for temporary use (e.g. permission checks). */
+void *tomoyo_alloc(const size_t size);
+
+/* Free memory allocated by tomoyo_alloc(). */
+void tomoyo_free(const void *p);
+
+/* Check for memory usage. */
+int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
+
+/* Set memory quota. */
+int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
+
+/* Initialize realpath related code. */
+void __init tomoyo_realpath_init(void);
+
+#endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
new file mode 100644
index 0000000..3eeeae1
--- /dev/null
+++ b/security/tomoyo/tomoyo.c
@@ -0,0 +1,294 @@
+/*
+ * security/tomoyo/tomoyo.c
+ *
+ * LSM hooks for TOMOYO Linux.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#include <linux/security.h>
+#include "common.h"
+#include "tomoyo.h"
+#include "realpath.h"
+
+static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
+			       gfp_t gfp)
+{
+	/*
+	 * Since "struct tomoyo_domain_info *" is a sharable pointer,
+	 * we don't need to duplicate.
+	 */
+	new->security = old->security;
+	return 0;
+}
+
+static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
+{
+	/*
+	 * Do only if this function is called for the first time of an execve
+	 * operation.
+	 */
+	if (bprm->cred_prepared)
+		return 0;
+	/*
+	 * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested
+	 * for the first time.
+	 */
+	if (!tomoyo_policy_loaded)
+		tomoyo_load_policy(bprm->filename);
+	/*
+	 * Tell tomoyo_bprm_check_security() is called for the first time of an
+	 * execve operation.
+	 */
+	bprm->cred->security = NULL;
+	return 0;
+}
+
+static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
+{
+	struct tomoyo_domain_info *domain = bprm->cred->security;
+
+	/*
+	 * Execute permission is checked against pathname passed to do_execve()
+	 * using current domain.
+	 */
+	if (!domain) {
+		struct tomoyo_domain_info *next_domain = NULL;
+		int retval = tomoyo_find_next_domain(bprm, &next_domain);
+
+		if (!retval)
+			bprm->cred->security = next_domain;
+		return retval;
+	}
+	/*
+	 * Read permission is checked against interpreters using next domain.
+	 * '1' is the result of open_to_namei_flags(O_RDONLY).
+	 */
+	return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1);
+}
+
+#ifdef CONFIG_SYSCTL
+
+static int tomoyo_prepend(char **buffer, int *buflen, const char *str)
+{
+	int namelen = strlen(str);
+
+	if (*buflen < namelen)
+		return -ENOMEM;
+	*buflen -= namelen;
+	*buffer -= namelen;
+	memcpy(*buffer, str, namelen);
+	return 0;
+}
+
+/**
+ * tomoyo_sysctl_path - return the realpath of a ctl_table.
+ * @table: pointer to "struct ctl_table".
+ *
+ * Returns realpath(3) of the @table on success.
+ * Returns NULL on failure.
+ *
+ * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
+ * if this function didn't return NULL.
+ */
+static char *tomoyo_sysctl_path(struct ctl_table *table)
+{
+	int buflen = TOMOYO_MAX_PATHNAME_LEN;
+	char *buf = tomoyo_alloc(buflen);
+	char *end = buf + buflen;
+	int error = -ENOMEM;
+
+	if (!buf)
+		return NULL;
+
+	*--end = '\0';
+	buflen--;
+	while (table) {
+		char num[32];
+		const char *sp = table->procname;
+
+		if (!sp) {
+			memset(num, 0, sizeof(num));
+			snprintf(num, sizeof(num) - 1, "=%d=", table->ctl_name);
+			sp = num;
+		}
+		if (tomoyo_prepend(&end, &buflen, sp) ||
+		    tomoyo_prepend(&end, &buflen, "/"))
+			goto out;
+		table = table->parent;
+	}
+	if (tomoyo_prepend(&end, &buflen, "/proc/sys"))
+		goto out;
+	error = tomoyo_encode(buf, end - buf, end);
+ out:
+	if (!error)
+		return buf;
+	tomoyo_free(buf);
+	return NULL;
+}
+
+static int tomoyo_sysctl(struct ctl_table *table, int op)
+{
+	int error;
+	char *name;
+
+	op &= MAY_READ | MAY_WRITE;
+	if (!op)
+		return 0;
+	name = tomoyo_sysctl_path(table);
+	if (!name)
+		return -ENOMEM;
+	error = tomoyo_check_file_perm(tomoyo_domain(), name, op);
+	tomoyo_free(name);
+	return error;
+}
+#endif
+
+static int tomoyo_path_truncate(struct path *path, loff_t length,
+				unsigned int time_attrs)
+{
+	return tomoyo_check_1path_perm(tomoyo_domain(),
+				       TOMOYO_TYPE_TRUNCATE_ACL,
+				       path);
+}
+
+static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
+{
+	struct path path = { parent->mnt, dentry };
+	return tomoyo_check_1path_perm(tomoyo_domain(),
+				       TOMOYO_TYPE_UNLINK_ACL,
+				       &path);
+}
+
+static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
+			     int mode)
+{
+	struct path path = { parent->mnt, dentry };
+	return tomoyo_check_1path_perm(tomoyo_domain(),
+				       TOMOYO_TYPE_MKDIR_ACL,
+				       &path);
+}
+
+static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
+{
+	struct path path = { parent->mnt, dentry };
+	return tomoyo_check_1path_perm(tomoyo_domain(),
+				       TOMOYO_TYPE_RMDIR_ACL,
+				       &path);
+}
+
+static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
+			       const char *old_name)
+{
+	struct path path = { parent->mnt, dentry };
+	return tomoyo_check_1path_perm(tomoyo_domain(),
+				       TOMOYO_TYPE_SYMLINK_ACL,
+				       &path);
+}
+
+static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
+			     int mode, unsigned int dev)
+{
+	struct path path = { parent->mnt, dentry };
+	int type = TOMOYO_TYPE_CREATE_ACL;
+
+	switch (mode & S_IFMT) {
+	case S_IFCHR:
+		type = TOMOYO_TYPE_MKCHAR_ACL;
+		break;
+	case S_IFBLK:
+		type = TOMOYO_TYPE_MKBLOCK_ACL;
+		break;
+	case S_IFIFO:
+		type = TOMOYO_TYPE_MKFIFO_ACL;
+		break;
+	case S_IFSOCK:
+		type = TOMOYO_TYPE_MKSOCK_ACL;
+		break;
+	}
+	return tomoyo_check_1path_perm(tomoyo_domain(),
+				       type, &path);
+}
+
+static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
+			    struct dentry *new_dentry)
+{
+	struct path path1 = { new_dir->mnt, old_dentry };
+	struct path path2 = { new_dir->mnt, new_dentry };
+	return tomoyo_check_2path_perm(tomoyo_domain(),
+				       TOMOYO_TYPE_LINK_ACL,
+				       &path1, &path2);
+}
+
+static int tomoyo_path_rename(struct path *old_parent,
+			      struct dentry *old_dentry,
+			      struct path *new_parent,
+			      struct dentry *new_dentry)
+{
+	struct path path1 = { old_parent->mnt, old_dentry };
+	struct path path2 = { new_parent->mnt, new_dentry };
+	return tomoyo_check_2path_perm(tomoyo_domain(),
+				       TOMOYO_TYPE_RENAME_ACL,
+				       &path1, &path2);
+}
+
+static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))
+		return tomoyo_check_rewrite_permission(tomoyo_domain(), file);
+	return 0;
+}
+
+static int tomoyo_dentry_open(struct file *f, const struct cred *cred)
+{
+	int flags = f->f_flags;
+
+	if ((flags + 1) & O_ACCMODE)
+		flags++;
+	flags |= f->f_flags & (O_APPEND | O_TRUNC);
+	/* Don't check read permission here if called from do_execve(). */
+	if (current->in_execve)
+		return 0;
+	return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags);
+}
+
+static struct security_operations tomoyo_security_ops = {
+	.name                = "tomoyo",
+	.cred_prepare        = tomoyo_cred_prepare,
+	.bprm_set_creds      = tomoyo_bprm_set_creds,
+	.bprm_check_security = tomoyo_bprm_check_security,
+#ifdef CONFIG_SYSCTL
+	.sysctl              = tomoyo_sysctl,
+#endif
+	.file_fcntl          = tomoyo_file_fcntl,
+	.dentry_open         = tomoyo_dentry_open,
+	.path_truncate       = tomoyo_path_truncate,
+	.path_unlink         = tomoyo_path_unlink,
+	.path_mkdir          = tomoyo_path_mkdir,
+	.path_rmdir          = tomoyo_path_rmdir,
+	.path_symlink        = tomoyo_path_symlink,
+	.path_mknod          = tomoyo_path_mknod,
+	.path_link           = tomoyo_path_link,
+	.path_rename         = tomoyo_path_rename,
+};
+
+static int __init tomoyo_init(void)
+{
+	struct cred *cred = (struct cred *) current_cred();
+
+	if (!security_module_enable(&tomoyo_security_ops))
+		return 0;
+	/* register ourselves with the security framework */
+	if (register_security(&tomoyo_security_ops))
+		panic("Failure registering TOMOYO Linux");
+	printk(KERN_INFO "TOMOYO Linux initialized\n");
+	cred->security = &tomoyo_kernel_domain;
+	tomoyo_realpath_init();
+	return 0;
+}
+
+security_initcall(tomoyo_init);
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h
new file mode 100644
index 0000000..a0c8f6e
--- /dev/null
+++ b/security/tomoyo/tomoyo.h
@@ -0,0 +1,106 @@
+/*
+ * security/tomoyo/tomoyo.h
+ *
+ * Implementation of the Domain-Based Mandatory Access Control.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#ifndef _SECURITY_TOMOYO_TOMOYO_H
+#define _SECURITY_TOMOYO_TOMOYO_H
+
+struct tomoyo_path_info;
+struct path;
+struct inode;
+struct linux_binprm;
+struct pt_regs;
+struct tomoyo_page_buffer;
+
+int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
+			   const char *filename, const u8 perm);
+int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
+			   const struct tomoyo_path_info *filename,
+			   struct tomoyo_page_buffer *buf);
+int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
+				 struct path *path, const int flag);
+int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
+			    const u8 operation, struct path *path);
+int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain,
+			    const u8 operation, struct path *path1,
+			    struct path *path2);
+int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
+				    struct file *filp);
+int tomoyo_find_next_domain(struct linux_binprm *bprm,
+			    struct tomoyo_domain_info **next_domain);
+
+/* Index numbers for Access Controls. */
+
+#define TOMOYO_TYPE_SINGLE_PATH_ACL                 0
+#define TOMOYO_TYPE_DOUBLE_PATH_ACL                 1
+
+/* Index numbers for File Controls. */
+
+/*
+ * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set
+ * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and
+ * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set.
+ * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or
+ * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are
+ * automatically cleared if TYPE_READ_WRITE_ACL is cleared.
+ */
+
+#define TOMOYO_TYPE_READ_WRITE_ACL    0
+#define TOMOYO_TYPE_EXECUTE_ACL       1
+#define TOMOYO_TYPE_READ_ACL          2
+#define TOMOYO_TYPE_WRITE_ACL         3
+#define TOMOYO_TYPE_CREATE_ACL        4
+#define TOMOYO_TYPE_UNLINK_ACL        5
+#define TOMOYO_TYPE_MKDIR_ACL         6
+#define TOMOYO_TYPE_RMDIR_ACL         7
+#define TOMOYO_TYPE_MKFIFO_ACL        8
+#define TOMOYO_TYPE_MKSOCK_ACL        9
+#define TOMOYO_TYPE_MKBLOCK_ACL      10
+#define TOMOYO_TYPE_MKCHAR_ACL       11
+#define TOMOYO_TYPE_TRUNCATE_ACL     12
+#define TOMOYO_TYPE_SYMLINK_ACL      13
+#define TOMOYO_TYPE_REWRITE_ACL      14
+#define TOMOYO_MAX_SINGLE_PATH_OPERATION 15
+
+#define TOMOYO_TYPE_LINK_ACL         0
+#define TOMOYO_TYPE_RENAME_ACL       1
+#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 2
+
+#define TOMOYO_DOMAINPOLICY          0
+#define TOMOYO_EXCEPTIONPOLICY       1
+#define TOMOYO_DOMAIN_STATUS         2
+#define TOMOYO_PROCESS_STATUS        3
+#define TOMOYO_MEMINFO               4
+#define TOMOYO_SELFDOMAIN            5
+#define TOMOYO_VERSION               6
+#define TOMOYO_PROFILE               7
+#define TOMOYO_MANAGER               8
+
+extern struct tomoyo_domain_info tomoyo_kernel_domain;
+
+static inline struct tomoyo_domain_info *tomoyo_domain(void)
+{
+	return current_cred()->security;
+}
+
+/* Caller holds tasklist_lock spinlock. */
+static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
+							    *task)
+{
+	/***** CRITICAL SECTION START *****/
+	const struct cred *cred = get_task_cred(task);
+	struct tomoyo_domain_info *domain = cred->security;
+
+	put_cred(cred);
+	return domain;
+	/***** CRITICAL SECTION END *****/
+}
+
+#endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */
diff --git a/sound/Kconfig b/sound/Kconfig
index 200aca1..1eceb85 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -60,6 +60,8 @@
 
 source "sound/arm/Kconfig"
 
+source "sound/atmel/Kconfig"
+
 source "sound/spi/Kconfig"
 
 source "sound/mips/Kconfig"
diff --git a/sound/Makefile b/sound/Makefile
index c76d707..ec467de 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -6,7 +6,7 @@
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
-	sparc/ spi/ parisc/ pcmcia/ mips/ soc/
+	sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
 obj-$(CONFIG_SND_AOA) += aoa/
 
 # This one must be compilable even if sound is configured out
diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h
index ee64f5d..6065b03 100644
--- a/sound/aoa/aoa-gpio.h
+++ b/sound/aoa/aoa-gpio.h
@@ -34,10 +34,12 @@
 	void (*set_headphone)(struct gpio_runtime *rt, int on);
 	void (*set_speakers)(struct gpio_runtime *rt, int on);
 	void (*set_lineout)(struct gpio_runtime *rt, int on);
+	void (*set_master)(struct gpio_runtime *rt, int on);
 
 	int (*get_headphone)(struct gpio_runtime *rt);
 	int (*get_speakers)(struct gpio_runtime *rt);
 	int (*get_lineout)(struct gpio_runtime *rt);
+	int (*get_master)(struct gpio_runtime *rt);
 
 	void (*set_hw_reset)(struct gpio_runtime *rt, int on);
 
diff --git a/sound/aoa/core/alsa.c b/sound/aoa/core/alsa.c
index 6178504..0fa3855 100644
--- a/sound/aoa/core/alsa.c
+++ b/sound/aoa/core/alsa.c
@@ -23,9 +23,10 @@
 		/* cannot be EEXIST due to usage in aoa_fabric_register */
 		return -EBUSY;
 
-	alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card));
-	if (!alsa_card)
-		return -ENOMEM;
+	err = snd_card_create(index, name, mod, sizeof(struct aoa_card),
+			      &alsa_card);
+	if (err < 0)
+		return err;
 	aoa_card = alsa_card->private_data;
 	aoa_card->alsa_card = alsa_card;
 	alsa_card->dev = dev;
diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c
index c93ad5d..de8e03a 100644
--- a/sound/aoa/core/gpio-feature.c
+++ b/sound/aoa/core/gpio-feature.c
@@ -14,7 +14,7 @@
 #include <linux/interrupt.h>
 #include "../aoa.h"
 
-/* TODO: these are 20 global variables
+/* TODO: these are lots of global variables
  * that aren't used on most machines...
  * Move them into a dynamically allocated
  * structure and use that.
@@ -23,6 +23,7 @@
 /* these are the GPIO numbers (register addresses as offsets into
  * the GPIO space) */
 static int headphone_mute_gpio;
+static int master_mute_gpio;
 static int amp_mute_gpio;
 static int lineout_mute_gpio;
 static int hw_reset_gpio;
@@ -32,6 +33,7 @@
 
 /* see the SWITCH_GPIO macro */
 static int headphone_mute_gpio_activestate;
+static int master_mute_gpio_activestate;
 static int amp_mute_gpio_activestate;
 static int lineout_mute_gpio_activestate;
 static int hw_reset_gpio_activestate;
@@ -156,6 +158,7 @@
 FTR_GPIO(headphone, 0);
 FTR_GPIO(amp, 1);
 FTR_GPIO(lineout, 2);
+FTR_GPIO(master, 3);
 
 static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
 {
@@ -172,6 +175,8 @@
 			  hw_reset_gpio, v);
 }
 
+static struct gpio_methods methods;
+
 static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
 {
 	int saved;
@@ -181,6 +186,8 @@
 	ftr_gpio_set_headphone(rt, 0);
 	ftr_gpio_set_amp(rt, 0);
 	ftr_gpio_set_lineout(rt, 0);
+	if (methods.set_master)
+		ftr_gpio_set_master(rt, 0);
 	rt->implementation_private = saved;
 }
 
@@ -193,6 +200,8 @@
 	ftr_gpio_set_headphone(rt, (s>>0)&1);
 	ftr_gpio_set_amp(rt, (s>>1)&1);
 	ftr_gpio_set_lineout(rt, (s>>2)&1);
+	if (methods.set_master)
+		ftr_gpio_set_master(rt, (s>>3)&1);
 }
 
 static void ftr_handle_notify(struct work_struct *work)
@@ -231,6 +240,12 @@
 	get_gpio("hw-reset", "audio-hw-reset",
 		 &hw_reset_gpio,
 		 &hw_reset_gpio_activestate);
+	if (get_gpio("master-mute", NULL,
+		     &master_mute_gpio,
+		     &master_mute_gpio_activestate)) {
+		methods.set_master = ftr_gpio_set_master;
+		methods.get_master = ftr_gpio_get_master;
+	}
 
 	headphone_detect_node = get_gpio("headphone-detect", NULL,
 					 &headphone_detect_gpio,
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c
index ad60f5d..fbf5c93 100644
--- a/sound/aoa/fabrics/layout.c
+++ b/sound/aoa/fabrics/layout.c
@@ -1,16 +1,14 @@
 /*
- * Apple Onboard Audio driver -- layout fabric
+ * Apple Onboard Audio driver -- layout/machine id fabric
  *
- * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
  *
  * GPL v2, can be found in COPYING.
  *
  *
- * This fabric module looks for sound codecs
- * based on the layout-id property in the device tree.
- *
+ * This fabric module looks for sound codecs based on the
+ * layout-id or device-id property in the device tree.
  */
-
 #include <asm/prom.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -63,7 +61,7 @@
 #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF	(1<<0)
 
 struct layout {
-	unsigned int layout_id;
+	unsigned int layout_id, device_id;
 	struct codec_connect_info codecs[MAX_CODECS_PER_BUS];
 	int flags;
 
@@ -111,6 +109,10 @@
 MODULE_ALIAS("sound-layout-98");
 MODULE_ALIAS("sound-layout-100");
 
+MODULE_ALIAS("aoa-device-id-14");
+MODULE_ALIAS("aoa-device-id-22");
+MODULE_ALIAS("aoa-device-id-35");
+
 /* onyx with all but microphone connected */
 static struct codec_connection onyx_connections_nomic[] = {
 	{
@@ -518,6 +520,27 @@
 		.connections = onyx_connections_noheadphones,
 	  },
 	},
+	/* PowerMac3,4 */
+	{ .device_id = 14,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_noline,
+	  },
+	},
+	/* PowerMac3,6 */
+	{ .device_id = 22,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_all,
+	  },
+	},
+	/* PowerBook5,2 */
+	{ .device_id = 35,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_all,
+	  },
+	},
 	{}
 };
 
@@ -526,7 +549,7 @@
 	struct layout *l;
 
 	l = layouts;
-	while (l->layout_id) {
+	while (l->codecs[0].name) {
 		if (l->layout_id == id)
 			return l;
 		l++;
@@ -534,6 +557,19 @@
 	return NULL;
 }
 
+static struct layout *find_layout_by_device(unsigned int id)
+{
+	struct layout *l;
+
+	l = layouts;
+	while (l->codecs[0].name) {
+		if (l->device_id == id)
+			return l;
+		l++;
+	}
+	return NULL;
+}
+
 static void use_layout(struct layout *l)
 {
 	int i;
@@ -564,6 +600,7 @@
 	struct snd_kcontrol *headphone_ctrl;
 	struct snd_kcontrol *lineout_ctrl;
 	struct snd_kcontrol *speaker_ctrl;
+	struct snd_kcontrol *master_ctrl;
 	struct snd_kcontrol *headphone_detected_ctrl;
 	struct snd_kcontrol *lineout_detected_ctrl;
 
@@ -615,6 +652,7 @@
 AMP_CONTROL(headphone, "Headphone Switch");
 AMP_CONTROL(speakers, "Speakers Switch");
 AMP_CONTROL(lineout, "Line-Out Switch");
+AMP_CONTROL(master, "Master Switch");
 
 static int detect_choice_get(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
@@ -855,6 +893,11 @@
  	lineout = codec->gpio->methods->get_detect(codec->gpio,
 						   AOA_NOTIFY_LINE_OUT);
 
+	if (codec->gpio->methods->set_master) {
+		ctl = snd_ctl_new1(&master_ctl, codec->gpio);
+		ldev->master_ctrl = ctl;
+		aoa_snd_ctl_add(ctl);
+	}
 	while (cc->connected) {
 		if (cc->connected & CC_SPEAKERS) {
 			if (headphones <= 0 && lineout <= 0)
@@ -938,8 +981,8 @@
 static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
 {
 	struct device_node *sound = NULL;
-	const unsigned int *layout_id;
-	struct layout *layout;
+	const unsigned int *id;
+	struct layout *layout = NULL;
 	struct layout_dev *ldev = NULL;
 	int err;
 
@@ -952,15 +995,18 @@
 		if (sound->type && strcasecmp(sound->type, "soundchip") == 0)
 			break;
 	}
-	if (!sound) return -ENODEV;
+	if (!sound)
+		return -ENODEV;
 
-	layout_id = of_get_property(sound, "layout-id", NULL);
-	if (!layout_id)
-		goto outnodev;
-	printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d\n",
-	       *layout_id);
+	id = of_get_property(sound, "layout-id", NULL);
+	if (id) {
+		layout = find_layout_by_id(*id);
+	} else {
+		id = of_get_property(sound, "device-id", NULL);
+		if (id)
+			layout = find_layout_by_device(*id);
+	}
 
-	layout = find_layout_by_id(*layout_id);
 	if (!layout) {
 		printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n");
 		goto outnodev;
@@ -976,6 +1022,7 @@
 	ldev->layout = layout;
 	ldev->gpio.node = sound->parent;
 	switch (layout->layout_id) {
+	case 0:  /* anything with device_id, not layout_id */
 	case 41: /* that unknown machine no one seems to have */
 	case 51: /* PowerBook5,4 */
 	case 58: /* Mac Mini */
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index be468edf..418c84c 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -1,7 +1,7 @@
 /*
  * i2sbus driver
  *
- * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
  *
  * GPL v2, can be found in COPYING.
  */
@@ -186,13 +186,25 @@
 		}
 	}
 	if (i == 1) {
-		const u32 *layout_id =
-			of_get_property(sound, "layout-id", NULL);
-		if (layout_id) {
-			layout = *layout_id;
+		const u32 *id = of_get_property(sound, "layout-id", NULL);
+
+		if (id) {
+			layout = *id;
 			snprintf(dev->sound.modalias, 32,
 				 "sound-layout-%d", layout);
 			ok = 1;
+		} else {
+			id = of_get_property(sound, "device-id", NULL);
+			/*
+			 * We probably cannot handle all device-id machines,
+			 * so restrict to those we do handle for now.
+			 */
+			if (id && (*id == 22 || *id == 14 || *id == 35)) {
+				snprintf(dev->sound.modalias, 32,
+					 "aoa-device-id-%d", *id);
+				ok = 1;
+				layout = -1;
+			}
 		}
 	}
 	/* for the time being, until we can handle non-layout-id
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index f8e6de4..885683a 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -11,17 +11,6 @@
 
 if SND_ARM
 
-config SND_SA11XX_UDA1341
-	tristate "SA11xx UDA1341TS driver (iPaq H3600)"
-	depends on ARCH_SA1100 && L3
-	select SND_PCM
-	help
-	  Say Y here if you have a Compaq iPaq H3x00 handheld computer
-	  and want to use its Philips UDA 1341 audio chip.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called snd-sa11xx-uda1341.
-
 config SND_ARMAACI
 	tristate "ARM PrimeCell PL041 AC Link support"
 	depends on ARM_AMBA
diff --git a/sound/arm/Makefile b/sound/arm/Makefile
index 2054de1..5a549ed 100644
--- a/sound/arm/Makefile
+++ b/sound/arm/Makefile
@@ -2,9 +2,6 @@
 # Makefile for ALSA
 #
 
-obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o 
-snd-sa11xx-uda1341-objs		:= sa11xx-uda1341.o
-
 obj-$(CONFIG_SND_ARMAACI)	+= snd-aaci.o
 snd-aaci-objs			:= aaci.o devdma.o
 
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 772901e..7fbd68f 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -995,10 +995,11 @@
 {
 	struct aaci *aaci;
 	struct snd_card *card;
+	int err;
 
-	card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-			    THIS_MODULE, sizeof(struct aaci));
-	if (card == NULL)
+	err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			      THIS_MODULE, sizeof(struct aaci), &card);
+	if (err < 0)
 		return NULL;
 
 	card->private_free = aaci_free_card;
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 35afd0c..2e6355f 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -31,6 +31,7 @@
 static volatile long gsr_bits;
 static struct clk *ac97_clk;
 static struct clk *ac97conf_clk;
+static int reset_gpio;
 
 /*
  * Beware PXA27x bugs:
@@ -42,6 +43,45 @@
  * 1 jiffy timeout if interrupt never comes).
  */
 
+enum {
+	RESETGPIO_FORCE_HIGH,
+	RESETGPIO_FORCE_LOW,
+	RESETGPIO_NORMAL_ALTFUNC
+};
+
+/**
+ * set_resetgpio_mode - computes and sets the AC97_RESET gpio mode on PXA
+ * @mode: chosen action
+ *
+ * As the PXA27x CPUs suffer from a AC97 bug, a manual control of the reset line
+ * must be done to insure proper work of AC97 reset line.  This function
+ * computes the correct gpio_mode for further use by reset functions, and
+ * applied the change through pxa_gpio_mode.
+ */
+static void set_resetgpio_mode(int resetgpio_action)
+{
+	int mode = 0;
+
+	if (reset_gpio)
+		switch (resetgpio_action) {
+		case RESETGPIO_NORMAL_ALTFUNC:
+			if (reset_gpio == 113)
+				mode = 113 | GPIO_OUT | GPIO_DFLT_LOW;
+			if (reset_gpio == 95)
+				mode = 95 | GPIO_ALT_FN_1_OUT;
+			break;
+		case RESETGPIO_FORCE_LOW:
+			mode = reset_gpio | GPIO_OUT | GPIO_DFLT_LOW;
+			break;
+		case RESETGPIO_FORCE_HIGH:
+			mode = reset_gpio | GPIO_OUT | GPIO_DFLT_HIGH;
+			break;
+		};
+
+	if (mode)
+		pxa_gpio_mode(mode);
+}
+
 unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
 	unsigned short val = -1;
@@ -137,10 +177,10 @@
 
 	/* warm reset broken on Bulverde,
 	   so manually keep AC97 reset high */
-	pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
+	set_resetgpio_mode(RESETGPIO_FORCE_HIGH);
 	udelay(10);
 	GCR |= GCR_WARM_RST;
-	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+	set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
 	udelay(500);
 }
 
@@ -308,8 +348,8 @@
 		pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
 	}
 	if (cpu_is_pxa27x()) {
-		/* Use GPIO 113 as AC97 Reset on Bulverde */
-		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+		/* Use GPIO 113 or 95 as AC97 Reset on Bulverde */
+		set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
 	}
 	clk_enable(ac97_clk);
 	return 0;
@@ -320,6 +360,27 @@
 int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
 {
 	int ret;
+	struct pxa2xx_ac97_platform_data *pdata = dev->dev.platform_data;
+
+	if (pdata) {
+		switch (pdata->reset_gpio) {
+		case 95:
+		case 113:
+			reset_gpio = pdata->reset_gpio;
+			break;
+		case 0:
+			reset_gpio = 113;
+			break;
+		case -1:
+			break;
+		default:
+			dev_err(&dev->dev, "Invalid reset GPIO %d\n",
+				pdata->reset_gpio);
+		}
+	} else {
+		if (cpu_is_pxa27x())
+			reset_gpio = 113;
+	}
 
 	if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
 		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
@@ -330,7 +391,7 @@
 
 	if (cpu_is_pxa27x()) {
 		/* Use GPIO 113 as AC97 Reset on Bulverde */
-		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+		set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
 		ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
 		if (IS_ERR(ac97conf_clk)) {
 			ret = PTR_ERR(ac97conf_clk);
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 85cf591..7ed100c 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -173,10 +173,9 @@
 	struct snd_ac97_template ac97_template;
 	int ret;
 
-	ret = -ENOMEM;
-	card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-			    THIS_MODULE, 0);
-	if (!card)
+	ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			      THIS_MODULE, 0, &card);
+	if (ret < 0)
 		goto err;
 
 	card->dev = &dev->dev;
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
deleted file mode 100644
index 1dcd51d..0000000
--- a/sound/arm/sa11xx-uda1341.c
+++ /dev/null
@@ -1,983 +0,0 @@
-/*
- *  Driver for Philips UDA1341TS on Compaq iPAQ H3600 soundcard
- *  Copyright (C) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License.
- * 
- * History:
- *
- * 2002-03-13   Tomas Kasparek  initial release - based on h3600-uda1341.c from OSS
- * 2002-03-20   Tomas Kasparek  playback over ALSA is working
- * 2002-03-28   Tomas Kasparek  playback over OSS emulation is working
- * 2002-03-29   Tomas Kasparek  basic capture is working (native ALSA)
- * 2002-03-29   Tomas Kasparek  capture is working (OSS emulation)
- * 2002-04-04   Tomas Kasparek  better rates handling (allow non-standard rates)
- * 2003-02-14   Brian Avery     fixed full duplex mode, other updates
- * 2003-02-20   Tomas Kasparek  merged updates by Brian (except HAL)
- * 2003-04-19   Jaroslav Kysela recoded DMA stuff to follow 2.4.18rmk3-hh24 kernel
- *                              working suspend and resume
- * 2003-04-28   Tomas Kasparek  updated work by Jaroslav to compile it under 2.5.x again
- *                              merged HAL layer (patches from Brian)
- */
-
-/***************************************************************************************************
-*
-* To understand what Alsa Drivers should be doing look at "Writing an Alsa Driver" by Takashi Iwai
-* available in the Alsa doc section on the website		
-* 
-* A few notes to make things clearer. The UDA1341 is hooked up to Serial port 4 on the SA1100.
-* We are using  SSP mode to talk to the UDA1341. The UDA1341 bit & wordselect clocks are generated
-* by this UART. Unfortunately, the clock only runs if the transmit buffer has something in it.
-* So, if we are just recording, we feed the transmit DMA stream a bunch of 0x0000 so that the
-* transmit buffer is full and the clock keeps going. The zeroes come from FLUSH_BASE_PHYS which
-* is a mem loc that always decodes to 0's w/ no off chip access.
-*
-* Some alsa terminology:
-*	frame => num_channels * sample_size  e.g stereo 16 bit is 2 * 16 = 32 bytes
-*	period => the least number of bytes that will generate an interrupt e.g. we have a 1024 byte
-*             buffer and 4 periods in the runtime structure this means we'll get an int every 256
-*             bytes or 4 times per buffer.
-*             A number of the sizes are in frames rather than bytes, use frames_to_bytes and
-*             bytes_to_frames to convert.  The easiest way to tell the units is to look at the
-*             type i.e. runtime-> buffer_size is in frames and its type is snd_pcm_uframes_t
-*             
-*	Notes about the pointer fxn:
-*	The pointer fxn needs to return the offset into the dma buffer in frames.
-*	Interrupts must be blocked before calling the dma_get_pos fxn to avoid race with interrupts.
-*
-*	Notes about pause/resume
-*	Implementing this would be complicated so it's skipped.  The problem case is:
-*	A full duplex connection is going, then play is paused. At this point you need to start xmitting
-*	0's to keep the record active which means you cant just freeze the dma and resume it later you'd
-*	need to	save off the dma info, and restore it properly on a resume.  Yeach!
-*
-*	Notes about transfer methods:
-*	The async write calls fail.  I probably need to implement something else to support them?
-* 
-***************************************************************************************************/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/errno.h>
-#include <linux/ioctl.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_PM
-#include <linux/pm.h>
-#endif
-
-#include <mach/hardware.h>
-#include <mach/h3600.h>
-#include <asm/mach-types.h>
-#include <asm/dma.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-
-#include <linux/l3/l3.h>
-
-#undef DEBUG_MODE
-#undef DEBUG_FUNCTION_NAMES
-#include <sound/uda1341.h>
-
-/*
- * FIXME: Is this enough as autodetection of 2.4.X-rmkY-hhZ kernels?
- * We use DMA stuff from 2.4.18-rmk3-hh24 here to be able to compile this
- * module for Familiar 0.6.1
- */
-
-/* {{{ Type definitions */
-
-MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA");
-MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}");
-
-static char *id;	/* ID for this card */
-
-module_param(id, charp, 0444);
-MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard.");
-
-struct audio_stream {
-	char *id;		/* identification string */
-	int stream_id;		/* numeric identification */	
-	dma_device_t dma_dev;	/* device identifier for DMA */
-#ifdef HH_VERSION
-	dmach_t dmach;		/* dma channel identification */
-#else
-	dma_regs_t *dma_regs;	/* points to our DMA registers */
-#endif
-	unsigned int active:1;	/* we are using this stream for transfer now */
-	int period;		/* current transfer period */
-	int periods;		/* current count of periods registerd in the DMA engine */
-	int tx_spin;		/* are we recoding - flag used to do DMA trans. for sync */
-	unsigned int old_offset;
-	spinlock_t dma_lock;	/* for locking in DMA operations (see dma-sa1100.c in the kernel) */
-	struct snd_pcm_substream *stream;
-};
-
-struct sa11xx_uda1341 {
-	struct snd_card *card;
-	struct l3_client *uda1341;
-	struct snd_pcm *pcm;
-	long samplerate;
-	struct audio_stream s[2];	/* playback & capture */
-};
-
-static unsigned int rates[] = {
-	8000,  10666, 10985, 14647,
-	16000, 21970, 22050, 24000,
-	29400, 32000, 44100, 48000,
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
-	.count	= ARRAY_SIZE(rates),
-	.list	= rates,
-	.mask	= 0,
-};
-
-static struct platform_device *device;
-
-/* }}} */
-
-/* {{{ Clock and sample rate stuff */
-
-/*
- * Stop-gap solution until rest of hh.org HAL stuff is merged.
- */
-#define GPIO_H3600_CLK_SET0		GPIO_GPIO (12)
-#define GPIO_H3600_CLK_SET1		GPIO_GPIO (13)
-
-#ifdef CONFIG_SA1100_H3XXX
-#define	clr_sa11xx_uda1341_egpio(x)	clr_h3600_egpio(x)
-#define set_sa11xx_uda1341_egpio(x)	set_h3600_egpio(x)
-#else
-#error This driver could serve H3x00 handhelds only!
-#endif
-
-static void sa11xx_uda1341_set_audio_clock(long val)
-{
-	switch (val) {
-	case 24000: case 32000: case 48000:	/* 00: 12.288 MHz */
-		GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
-		break;
-
-	case 22050: case 29400: case 44100:	/* 01: 11.2896 MHz */
-		GPSR = GPIO_H3600_CLK_SET0;
-		GPCR = GPIO_H3600_CLK_SET1;
-		break;
-
-	case 8000: case 10666: case 16000:	/* 10: 4.096 MHz */
-		GPCR = GPIO_H3600_CLK_SET0;
-		GPSR = GPIO_H3600_CLK_SET1;
-		break;
-
-	case 10985: case 14647: case 21970:	/* 11: 5.6245 MHz */
-		GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
-		break;
-	}
-}
-
-static void sa11xx_uda1341_set_samplerate(struct sa11xx_uda1341 *sa11xx_uda1341, long rate)
-{
-	int clk_div = 0;
-	int clk=0;
-
-	/* We don't want to mess with clocks when frames are in flight */
-	Ser4SSCR0 &= ~SSCR0_SSE;
-	/* wait for any frame to complete */
-	udelay(125);
-
-	/*
-	 * We have the following clock sources:
-	 * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz
-	 * Those can be divided either by 256, 384 or 512.
-	 * This makes up 12 combinations for the following samplerates...
-	 */
-	if (rate >= 48000)
-		rate = 48000;
-	else if (rate >= 44100)
-		rate = 44100;
-	else if (rate >= 32000)
-		rate = 32000;
-	else if (rate >= 29400)
-		rate = 29400;
-	else if (rate >= 24000)
-		rate = 24000;
-	else if (rate >= 22050)
-		rate = 22050;
-	else if (rate >= 21970)
-		rate = 21970;
-	else if (rate >= 16000)
-		rate = 16000;
-	else if (rate >= 14647)
-		rate = 14647;
-	else if (rate >= 10985)
-		rate = 10985;
-	else if (rate >= 10666)
-		rate = 10666;
-	else
-		rate = 8000;
-
-	/* Set the external clock generator */
-	
-	sa11xx_uda1341_set_audio_clock(rate);
-
-	/* Select the clock divisor */
-	switch (rate) {
-	case 8000:
-	case 10985:
-	case 22050:
-	case 24000:
-		clk = F512;
-		clk_div = SSCR0_SerClkDiv(16);
-		break;
-	case 16000:
-	case 21970:
-	case 44100:
-	case 48000:
-		clk = F256;
-		clk_div = SSCR0_SerClkDiv(8);
-		break;
-	case 10666:
-	case 14647:
-	case 29400:
-	case 32000:
-		clk = F384;
-		clk_div = SSCR0_SerClkDiv(12);
-		break;
-	}
-
-	/* FMT setting should be moved away when other FMTs are added (FIXME) */
-	l3_command(sa11xx_uda1341->uda1341, CMD_FORMAT, (void *)LSB16);
-	
-	l3_command(sa11xx_uda1341->uda1341, CMD_FS, (void *)clk);        
-	Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
-	sa11xx_uda1341->samplerate = rate;
-}
-
-/* }}} */
-
-/* {{{ HW init and shutdown */
-
-static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341)
-{
-	unsigned long flags;
-
-	/* Setup DMA stuff */
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].id = "UDA1341 out";
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id = SNDRV_PCM_STREAM_PLAYBACK;
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev = DMA_Ser4SSPWr;
-
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].id = "UDA1341 in";
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].stream_id = SNDRV_PCM_STREAM_CAPTURE;
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev = DMA_Ser4SSPRd;
-
-	/* Initialize the UDA1341 internal state */
-       
-	/* Setup the uarts */
-	local_irq_save(flags);
-	GAFR |= (GPIO_SSP_CLK);
-	GPDR &= ~(GPIO_SSP_CLK);
-	Ser4SSCR0 = 0;
-	Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8);
-	Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
-	Ser4SSCR0 |= SSCR0_SSE;
-	local_irq_restore(flags);
-
-	/* Enable the audio power */
-
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);
-	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON);
-	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
- 
-	/* Wait for the UDA1341 to wake up */
-	mdelay(1); //FIXME - was removed by Perex - Why?
-
-	/* Initialize the UDA1341 internal state */
-	l3_open(sa11xx_uda1341->uda1341);
-	
-	/* external clock configuration (after l3_open - regs must be initialized */
-	sa11xx_uda1341_set_samplerate(sa11xx_uda1341, sa11xx_uda1341->samplerate);
-
-	/* Wait for the UDA1341 to wake up */
-	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);
-	mdelay(1);	
-
-	/* make the left and right channels unswapped (flip the WS latch) */
-	Ser4SSDR = 0;
-
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-}
-
-static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341)
-{
-	/* mute on */
-	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-	
-	/* disable the audio power and all signals leading to the audio chip */
-	l3_close(sa11xx_uda1341->uda1341);
-	Ser4SSCR0 = 0;
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);
-
-	/* power off and mute off */
-	/* FIXME - is muting off necesary??? */
-
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON);
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-}
-
-/* }}} */
-
-/* {{{ DMA staff */
-
-/*
- * these are the address and sizes used to fill the xmit buffer
- * so we can get a clock in record only mode
- */
-#define FORCE_CLOCK_ADDR		(dma_addr_t)FLUSH_BASE_PHYS
-#define FORCE_CLOCK_SIZE		4096 // was 2048
-
-// FIXME Why this value exactly - wrote comment
-#define DMA_BUF_SIZE	8176	/* <= MAX_DMA_SIZE from asm/arch-sa1100/dma.h */
-
-#ifdef HH_VERSION
-
-static int audio_dma_request(struct audio_stream *s, void (*callback)(void *, int))
-{
-	int ret;
-
-	ret = sa1100_request_dma(&s->dmach, s->id, s->dma_dev);
-	if (ret < 0) {
-		printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev);
-		return ret;
-	}
-	sa1100_dma_set_callback(s->dmach, callback);
-	return 0;
-}
-
-static inline void audio_dma_free(struct audio_stream *s)
-{
-	sa1100_free_dma(s->dmach);
-	s->dmach = -1;
-}
-
-#else
-
-static int audio_dma_request(struct audio_stream *s, void (*callback)(void *))
-{
-	int ret;
-
-	ret = sa1100_request_dma(s->dma_dev, s->id, callback, s, &s->dma_regs);
-	if (ret < 0)
-		printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev);
-	return ret;
-}
-
-static void audio_dma_free(struct audio_stream *s)
-{
-	sa1100_free_dma(s->dma_regs);
-	s->dma_regs = 0;
-}
-
-#endif
-
-static u_int audio_get_dma_pos(struct audio_stream *s)
-{
-	struct snd_pcm_substream *substream = s->stream;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	unsigned int offset;
-	unsigned long flags;
-	dma_addr_t addr;
-	
-	// this must be called w/ interrupts locked out see dma-sa1100.c in the kernel
-	spin_lock_irqsave(&s->dma_lock, flags);
-#ifdef HH_VERSION	
-	sa1100_dma_get_current(s->dmach, NULL, &addr);
-#else
-	addr = sa1100_get_dma_pos((s)->dma_regs);
-#endif
-	offset = addr - runtime->dma_addr;
-	spin_unlock_irqrestore(&s->dma_lock, flags);
-	
-	offset = bytes_to_frames(runtime,offset);
-	if (offset >= runtime->buffer_size)
-		offset = 0;
-
-	return offset;
-}
-
-/*
- * this stops the dma and clears the dma ptrs
- */
-static void audio_stop_dma(struct audio_stream *s)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&s->dma_lock, flags);	
-	s->active = 0;
-	s->period = 0;
-	/* this stops the dma channel and clears the buffer ptrs */
-#ifdef HH_VERSION
-	sa1100_dma_flush_all(s->dmach);
-#else
-	sa1100_clear_dma(s->dma_regs);	
-#endif
-	spin_unlock_irqrestore(&s->dma_lock, flags);
-}
-
-static void audio_process_dma(struct audio_stream *s)
-{
-	struct snd_pcm_substream *substream = s->stream;
-	struct snd_pcm_runtime *runtime;
-	unsigned int dma_size;		
-	unsigned int offset;
-	int ret;
-                
-	/* we are requested to process synchronization DMA transfer */
-	if (s->tx_spin) {
-		if (snd_BUG_ON(s->stream_id != SNDRV_PCM_STREAM_PLAYBACK))
-			return;
-		/* fill the xmit dma buffers and return */
-#ifdef HH_VERSION
-		sa1100_dma_set_spin(s->dmach, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE);
-#else
-		while (1) {
-			ret = sa1100_start_dma(s->dma_regs, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE);
-			if (ret)
-				return;   
-		}
-#endif
-		return;
-	}
-
-	/* must be set here - only valid for running streams, not for forced_clock dma fills  */
-	runtime = substream->runtime;
-	while (s->active && s->periods < runtime->periods) {
-		dma_size = frames_to_bytes(runtime, runtime->period_size);
-		if (s->old_offset) {
-			/* a little trick, we need resume from old position */
-			offset = frames_to_bytes(runtime, s->old_offset - 1);
-			s->old_offset = 0;
-			s->periods = 0;
-			s->period = offset / dma_size;
-			offset %= dma_size;
-			dma_size = dma_size - offset;
-			if (!dma_size)
-				continue;		/* special case */
-		} else {
-			offset = dma_size * s->period;
-			snd_BUG_ON(dma_size > DMA_BUF_SIZE);
-		}
-#ifdef HH_VERSION
-		ret = sa1100_dma_queue_buffer(s->dmach, s, runtime->dma_addr + offset, dma_size);
-		if (ret)
-			return; //FIXME
-#else
-		ret = sa1100_start_dma((s)->dma_regs, runtime->dma_addr + offset, dma_size);
-		if (ret) {
-			printk(KERN_ERR "audio_process_dma: cannot queue DMA buffer (%i)\n", ret);
-			return;
-		}
-#endif
-
-		s->period++;
-		s->period %= runtime->periods;
-		s->periods++;
-	}
-}
-
-#ifdef HH_VERSION
-static void audio_dma_callback(void *data, int size)
-#else
-static void audio_dma_callback(void *data)
-#endif
-{
-	struct audio_stream *s = data;
-        
-	/* 
-	 * If we are getting a callback for an active stream then we inform
-	 * the PCM middle layer we've finished a period
-	 */
- 	if (s->active)
-		snd_pcm_period_elapsed(s->stream);
-
-	spin_lock(&s->dma_lock);
-	if (!s->tx_spin && s->periods > 0)
-		s->periods--;
-	audio_process_dma(s);
-	spin_unlock(&s->dma_lock);
-}
-
-/* }}} */
-
-/* {{{ PCM setting */
-
-/* {{{ trigger & timer */
-
-static int snd_sa11xx_uda1341_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-	int stream_id = substream->pstr->stream;
-	struct audio_stream *s = &chip->s[stream_id];
-	struct audio_stream *s1 = &chip->s[stream_id ^ 1];
-	int err = 0;
-
-	/* note local interrupts are already disabled in the midlevel code */
-	spin_lock(&s->dma_lock);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		/* now we need to make sure a record only stream has a clock */
-		if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) {
-			/* we need to force fill the xmit DMA with zeros */
-			s1->tx_spin = 1;
-			audio_process_dma(s1);
-		}
-		/* this case is when you were recording then you turn on a
-		 * playback stream so we stop (also clears it) the dma first,
-		 * clear the sync flag and then we let it turned on
-		 */		
-		else {
- 			s->tx_spin = 0;
- 		}
-
-		/* requested stream startup */
-		s->active = 1;
-		audio_process_dma(s);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-		/* requested stream shutdown */
-		audio_stop_dma(s);
-		
-		/*
-		 * now we need to make sure a record only stream has a clock
-		 * so if we're stopping a playback with an active capture
-		 * we need to turn the 0 fill dma on for the xmit side
-		 */
-		if (stream_id == SNDRV_PCM_STREAM_PLAYBACK && s1->active) {
-			/* we need to force fill the xmit DMA with zeros */
-			s->tx_spin = 1;
-			audio_process_dma(s);
-		}
-		/*
-		 * we killed a capture only stream, so we should also kill
-		 * the zero fill transmit
-		 */
-		else {
-			if (s1->tx_spin) {
-				s1->tx_spin = 0;
-				audio_stop_dma(s1);
-			}
-		}
-		
-		break;
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-		s->active = 0;
-#ifdef HH_VERSION		
-		sa1100_dma_stop(s->dmach);
-#else
-		//FIXME - DMA API
-#endif		
-		s->old_offset = audio_get_dma_pos(s) + 1;
-#ifdef HH_VERSION		
-		sa1100_dma_flush_all(s->dmach);
-#else
-		//FIXME - DMA API
-#endif		
-		s->periods = 0;
-		break;
-	case SNDRV_PCM_TRIGGER_RESUME:
-		s->active = 1;
-		s->tx_spin = 0;
-		audio_process_dma(s);
-		if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) {
-			s1->tx_spin = 1;
-			audio_process_dma(s1);
-		}
-		break;
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-#ifdef HH_VERSION		
-		sa1100_dma_stop(s->dmach);
-#else
-		//FIXME - DMA API
-#endif
-		s->active = 0;
-		if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
-			if (s1->active) {
-				s->tx_spin = 1;
-				s->old_offset = audio_get_dma_pos(s) + 1;
-#ifdef HH_VERSION				
-				sa1100_dma_flush_all(s->dmach);
-#else
-				//FIXME - DMA API
-#endif				
-				audio_process_dma(s);
-			}
-		} else {
-			if (s1->tx_spin) {
-				s1->tx_spin = 0;
-#ifdef HH_VERSION				
-				sa1100_dma_flush_all(s1->dmach);
-#else
-				//FIXME - DMA API
-#endif				
-			}
-		}
-		break;
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		s->active = 1;
-		if (s->old_offset) {
-			s->tx_spin = 0;
-			audio_process_dma(s);
-			break;
-		}
-		if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) {
-			s1->tx_spin = 1;
-			audio_process_dma(s1);
-		}
-#ifdef HH_VERSION		
-		sa1100_dma_resume(s->dmach);
-#else
-		//FIXME - DMA API
-#endif
-		break;
-	default:
-		err = -EINVAL;
-		break;
-	}
-	spin_unlock(&s->dma_lock);	
-	return err;
-}
-
-static int snd_sa11xx_uda1341_prepare(struct snd_pcm_substream *substream)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct audio_stream *s = &chip->s[substream->pstr->stream];
-        
-	/* set requested samplerate */
-	sa11xx_uda1341_set_samplerate(chip, runtime->rate);
-
-	/* set requestd format when available */
-	/* set FMT here !!! FIXME */
-
-	s->period = 0;
-	s->periods = 0;
-        
-	return 0;
-}
-
-static snd_pcm_uframes_t snd_sa11xx_uda1341_pointer(struct snd_pcm_substream *substream)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-	return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
-}
-
-/* }}} */
-
-static struct snd_pcm_hardware snd_sa11xx_uda1341_capture =
-{
-	.info			= (SNDRV_PCM_INFO_INTERLEAVED |
-				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				   SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-				   SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
-	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
-	.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_KNOT),
-	.rate_min		= 8000,
-	.rate_max		= 48000,
-	.channels_min		= 2,
-	.channels_max		= 2,
-	.buffer_bytes_max	= 64*1024,
-	.period_bytes_min	= 64,
-	.period_bytes_max	= DMA_BUF_SIZE,
-	.periods_min		= 2,
-	.periods_max		= 255,
-	.fifo_size		= 0,
-};
-
-static struct snd_pcm_hardware snd_sa11xx_uda1341_playback =
-{
-	.info			= (SNDRV_PCM_INFO_INTERLEAVED |
-				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				   SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-				   SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
-	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
-	.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_KNOT),
-	.rate_min		= 8000,
-	.rate_max		= 48000,
-	.channels_min		= 2,
-	.channels_max		= 2,
-	.buffer_bytes_max	= 64*1024,
-	.period_bytes_min	= 64,
-	.period_bytes_max	= DMA_BUF_SIZE,
-	.periods_min		= 2,
-	.periods_max		= 255,
-	.fifo_size		= 0,
-};
-
-static int snd_card_sa11xx_uda1341_open(struct snd_pcm_substream *substream)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	int stream_id = substream->pstr->stream;
-	int err;
-
-	chip->s[stream_id].stream = substream;
-
-	if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
-		runtime->hw = snd_sa11xx_uda1341_playback;
-	else
-		runtime->hw = snd_sa11xx_uda1341_capture;
-	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
-		return err;
-	if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0)
-		return err;
-        
-	return 0;
-}
-
-static int snd_card_sa11xx_uda1341_close(struct snd_pcm_substream *substream)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-
-	chip->s[substream->pstr->stream].stream = NULL;
-	return 0;
-}
-
-/* {{{ HW params & free */
-
-static int snd_sa11xx_uda1341_hw_params(struct snd_pcm_substream *substream,
-					struct snd_pcm_hw_params *hw_params)
-{
-        
-	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_sa11xx_uda1341_hw_free(struct snd_pcm_substream *substream)
-{
-	return snd_pcm_lib_free_pages(substream);
-}
-
-/* }}} */
-
-static struct snd_pcm_ops snd_card_sa11xx_uda1341_playback_ops = {
-	.open			= snd_card_sa11xx_uda1341_open,
-	.close			= snd_card_sa11xx_uda1341_close,
-	.ioctl			= snd_pcm_lib_ioctl,
-	.hw_params	        = snd_sa11xx_uda1341_hw_params,
-	.hw_free	        = snd_sa11xx_uda1341_hw_free,
-	.prepare		= snd_sa11xx_uda1341_prepare,
-	.trigger		= snd_sa11xx_uda1341_trigger,
-	.pointer		= snd_sa11xx_uda1341_pointer,
-};
-
-static struct snd_pcm_ops snd_card_sa11xx_uda1341_capture_ops = {
-	.open			= snd_card_sa11xx_uda1341_open,
-	.close			= snd_card_sa11xx_uda1341_close,
-	.ioctl			= snd_pcm_lib_ioctl,
-	.hw_params	        = snd_sa11xx_uda1341_hw_params,
-	.hw_free	        = snd_sa11xx_uda1341_hw_free,
-	.prepare		= snd_sa11xx_uda1341_prepare,
-	.trigger		= snd_sa11xx_uda1341_trigger,
-	.pointer		= snd_sa11xx_uda1341_pointer,
-};
-
-static int __init snd_card_sa11xx_uda1341_pcm(struct sa11xx_uda1341 *sa11xx_uda1341, int device)
-{
-	struct snd_pcm *pcm;
-	int err;
-
-	if ((err = snd_pcm_new(sa11xx_uda1341->card, "UDA1341 PCM", device, 1, 1, &pcm)) < 0)
-		return err;
-
-	/*
-	 * this sets up our initial buffers and sets the dma_type to isa.
-	 * isa works but I'm not sure why (or if) it's the right choice
-	 * this may be too large, trying it for now
-	 */
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 
-					      snd_dma_isa_data(),
-					      64*1024, 64*1024);
-
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_sa11xx_uda1341_playback_ops);
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_sa11xx_uda1341_capture_ops);
-	pcm->private_data = sa11xx_uda1341;
-	pcm->info_flags = 0;
-	strcpy(pcm->name, "UDA1341 PCM");
-
-	sa11xx_uda1341_audio_init(sa11xx_uda1341);
-
-	/* setup DMA controller */
-	audio_dma_request(&sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK], audio_dma_callback);
-	audio_dma_request(&sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE], audio_dma_callback);
-
-	sa11xx_uda1341->pcm = pcm;
-
-	return 0;
-}
-
-/* }}} */
-
-/* {{{ module init & exit */
-
-#ifdef CONFIG_PM
-
-static int snd_sa11xx_uda1341_suspend(struct platform_device *devptr,
-				      pm_message_t state)
-{
-	struct snd_card *card = platform_get_drvdata(devptr);
-	struct sa11xx_uda1341 *chip = card->private_data;
-
-	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-	snd_pcm_suspend_all(chip->pcm);
-#ifdef HH_VERSION
-	sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_PLAYBACK].dmach);
-	sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_CAPTURE].dmach);
-#else
-	//FIXME
-#endif
-	l3_command(chip->uda1341, CMD_SUSPEND, NULL);
-	sa11xx_uda1341_audio_shutdown(chip);
-
-	return 0;
-}
-
-static int snd_sa11xx_uda1341_resume(struct platform_device *devptr)
-{
-	struct snd_card *card = platform_get_drvdata(devptr);
-	struct sa11xx_uda1341 *chip = card->private_data;
-
-	sa11xx_uda1341_audio_init(chip);
-	l3_command(chip->uda1341, CMD_RESUME, NULL);
-#ifdef HH_VERSION	
-	sa1100_dma_wakeup(chip->s[SNDRV_PCM_STREAM_PLAYBACK].dmach);
-	sa1100_dma_wakeup(chip->s[SNDRV_PCM_STREAM_CAPTURE].dmach);
-#else
-	//FIXME
-#endif
-	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-	return 0;
-}
-#endif /* COMFIG_PM */
-
-void snd_sa11xx_uda1341_free(struct snd_card *card)
-{
-	struct sa11xx_uda1341 *chip = card->private_data;
-
-	audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
-	audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
-}
-
-static int __devinit sa11xx_uda1341_probe(struct platform_device *devptr)
-{
-	int err;
-	struct snd_card *card;
-	struct sa11xx_uda1341 *chip;
-
-	/* register the soundcard */
-	card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct sa11xx_uda1341));
-	if (card == NULL)
-		return -ENOMEM;
-
-	chip = card->private_data;
-	spin_lock_init(&chip->s[0].dma_lock);
-	spin_lock_init(&chip->s[1].dma_lock);
-
-	card->private_free = snd_sa11xx_uda1341_free;
-	chip->card = card;
-	chip->samplerate = AUDIO_RATE_DEFAULT;
-
-	// mixer
-	if ((err = snd_chip_uda1341_mixer_new(card, &chip->uda1341)))
-		goto nodev;
-
-	// PCM
-	if ((err = snd_card_sa11xx_uda1341_pcm(chip, 0)) < 0)
-		goto nodev;
-        
-	strcpy(card->driver, "UDA1341");
-	strcpy(card->shortname, "H3600 UDA1341TS");
-	sprintf(card->longname, "Compaq iPAQ H3600 with Philips UDA1341TS");
-        
-	snd_card_set_dev(card, &devptr->dev);
-
-	if ((err = snd_card_register(card)) == 0) {
-		printk( KERN_INFO "iPAQ audio support initialized\n" );
-		platform_set_drvdata(devptr, card);
-		return 0;
-	}
-        
- nodev:
-	snd_card_free(card);
-	return err;
-}
-
-static int __devexit sa11xx_uda1341_remove(struct platform_device *devptr)
-{
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
-	return 0;
-}
-
-#define SA11XX_UDA1341_DRIVER	"sa11xx_uda1341"
-
-static struct platform_driver sa11xx_uda1341_driver = {
-	.probe		= sa11xx_uda1341_probe,
-	.remove		= __devexit_p(sa11xx_uda1341_remove),
-#ifdef CONFIG_PM
-	.suspend	= snd_sa11xx_uda1341_suspend,
-	.resume		= snd_sa11xx_uda1341_resume,
-#endif
-	.driver		= {
-		.name	= SA11XX_UDA1341_DRIVER,
-	},
-};
-
-static int __init sa11xx_uda1341_init(void)
-{
-	int err;
-
-	if (!machine_is_h3xxx())
-		return -ENODEV;
-	if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0)
-		return err;
-	device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0);
-	if (!IS_ERR(device)) {
-		if (platform_get_drvdata(device))
-			return 0;
-		platform_device_unregister(device);
-		err = -ENODEV;
-	} else
-		err = PTR_ERR(device);
-	platform_driver_unregister(&sa11xx_uda1341_driver);
-	return err;
-}
-
-static void __exit sa11xx_uda1341_exit(void)
-{
-	platform_device_unregister(device);
-	platform_driver_unregister(&sa11xx_uda1341_driver);
-}
-
-module_init(sa11xx_uda1341_init);
-module_exit(sa11xx_uda1341_exit);
-
-/* }}} */
-
-/*
- * Local variables:
- * indent-tabs-mode: t
- * End:
- */
diff --git a/sound/atmel/Kconfig b/sound/atmel/Kconfig
new file mode 100644
index 0000000..6c228a9
--- /dev/null
+++ b/sound/atmel/Kconfig
@@ -0,0 +1,19 @@
+menu "Atmel devices (AVR32 and AT91)"
+	depends on AVR32 || ARCH_AT91
+
+config SND_ATMEL_ABDAC
+	tristate "Atmel Audio Bitstream DAC (ABDAC) driver"
+	select SND_PCM
+	depends on DW_DMAC && AVR32
+	help
+	  ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC).
+
+config SND_ATMEL_AC97C
+	tristate "Atmel AC97 Controller (AC97C) driver"
+	select SND_PCM
+	select SND_AC97_CODEC
+	depends on DW_DMAC && AVR32
+	help
+	  ALSA sound driver for the Atmel AC97 controller.
+
+endmenu
diff --git a/sound/atmel/Makefile b/sound/atmel/Makefile
new file mode 100644
index 0000000..219dcfa
--- /dev/null
+++ b/sound/atmel/Makefile
@@ -0,0 +1,5 @@
+snd-atmel-abdac-objs		:= abdac.o
+snd-atmel-ac97c-objs		:= ac97c.o
+
+obj-$(CONFIG_SND_ATMEL_ABDAC)	+= snd-atmel-abdac.o
+obj-$(CONFIG_SND_ATMEL_AC97C)	+= snd-atmel-ac97c.o
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c
new file mode 100644
index 0000000..28b3c7f
--- /dev/null
+++ b/sound/atmel/abdac.c
@@ -0,0 +1,602 @@
+/*
+ * Driver for the Atmel on-chip Audio Bitstream DAC (ABDAC)
+ *
+ * Copyright (C) 2006-2009 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/bitmap.h>
+#include <linux/dw_dmac.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/atmel-abdac.h>
+
+/* DAC register offsets */
+#define DAC_DATA                                0x0000
+#define DAC_CTRL                                0x0008
+#define DAC_INT_MASK                            0x000c
+#define DAC_INT_EN                              0x0010
+#define DAC_INT_DIS                             0x0014
+#define DAC_INT_CLR                             0x0018
+#define DAC_INT_STATUS                          0x001c
+
+/* Bitfields in CTRL */
+#define DAC_SWAP_OFFSET                         30
+#define DAC_SWAP_SIZE                           1
+#define DAC_EN_OFFSET                           31
+#define DAC_EN_SIZE                             1
+
+/* Bitfields in INT_MASK/INT_EN/INT_DIS/INT_STATUS/INT_CLR */
+#define DAC_UNDERRUN_OFFSET                     28
+#define DAC_UNDERRUN_SIZE                       1
+#define DAC_TX_READY_OFFSET                     29
+#define DAC_TX_READY_SIZE                       1
+
+/* Bit manipulation macros */
+#define DAC_BIT(name)					\
+	(1 << DAC_##name##_OFFSET)
+#define DAC_BF(name, value)				\
+	(((value) & ((1 << DAC_##name##_SIZE) - 1))	\
+	 << DAC_##name##_OFFSET)
+#define DAC_BFEXT(name, value)				\
+	(((value) >> DAC_##name##_OFFSET)		\
+	 & ((1 << DAC_##name##_SIZE) - 1))
+#define DAC_BFINS(name, value, old)			\
+	(((old) & ~(((1 << DAC_##name##_SIZE) - 1)	\
+		    << DAC_##name##_OFFSET))		\
+	 | DAC_BF(name, value))
+
+/* Register access macros */
+#define dac_readl(port, reg)				\
+	__raw_readl((port)->regs + DAC_##reg)
+#define dac_writel(port, reg, value)			\
+	__raw_writel((value), (port)->regs + DAC_##reg)
+
+/*
+ * ABDAC supports a maximum of 6 different rates from a generic clock. The
+ * generic clock has a power of two divider, which gives 6 steps from 192 kHz
+ * to 5112 Hz.
+ */
+#define MAX_NUM_RATES	6
+/* ALSA seems to use rates between 192000 Hz and 5112 Hz. */
+#define RATE_MAX	192000
+#define RATE_MIN	5112
+
+enum {
+	DMA_READY = 0,
+};
+
+struct atmel_abdac_dma {
+	struct dma_chan		*chan;
+	struct dw_cyclic_desc	*cdesc;
+};
+
+struct atmel_abdac {
+	struct clk				*pclk;
+	struct clk				*sample_clk;
+	struct platform_device			*pdev;
+	struct atmel_abdac_dma			dma;
+
+	struct snd_pcm_hw_constraint_list	constraints_rates;
+	struct snd_pcm_substream		*substream;
+	struct snd_card				*card;
+	struct snd_pcm				*pcm;
+
+	void __iomem				*regs;
+	unsigned long				flags;
+	unsigned int				rates[MAX_NUM_RATES];
+	unsigned int				rates_num;
+	int					irq;
+};
+
+#define get_dac(card) ((struct atmel_abdac *)(card)->private_data)
+
+/* This function is called by the DMA driver. */
+static void atmel_abdac_dma_period_done(void *arg)
+{
+	struct atmel_abdac *dac = arg;
+	snd_pcm_period_elapsed(dac->substream);
+}
+
+static int atmel_abdac_prepare_dma(struct atmel_abdac *dac,
+		struct snd_pcm_substream *substream,
+		enum dma_data_direction direction)
+{
+	struct dma_chan			*chan = dac->dma.chan;
+	struct dw_cyclic_desc		*cdesc;
+	struct snd_pcm_runtime		*runtime = substream->runtime;
+	unsigned long			buffer_len, period_len;
+
+	/*
+	 * We don't do DMA on "complex" transfers, i.e. with
+	 * non-halfword-aligned buffers or lengths.
+	 */
+	if (runtime->dma_addr & 1 || runtime->buffer_size & 1) {
+		dev_dbg(&dac->pdev->dev, "too complex transfer\n");
+		return -EINVAL;
+	}
+
+	buffer_len = frames_to_bytes(runtime, runtime->buffer_size);
+	period_len = frames_to_bytes(runtime, runtime->period_size);
+
+	cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
+			period_len, DMA_TO_DEVICE);
+	if (IS_ERR(cdesc)) {
+		dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n");
+		return PTR_ERR(cdesc);
+	}
+
+	cdesc->period_callback = atmel_abdac_dma_period_done;
+	cdesc->period_callback_param = dac;
+
+	dac->dma.cdesc = cdesc;
+
+	set_bit(DMA_READY, &dac->flags);
+
+	return 0;
+}
+
+static struct snd_pcm_hardware atmel_abdac_hw = {
+	.info			= (SNDRV_PCM_INFO_MMAP
+				  | SNDRV_PCM_INFO_MMAP_VALID
+				  | SNDRV_PCM_INFO_INTERLEAVED
+				  | SNDRV_PCM_INFO_BLOCK_TRANSFER
+				  | SNDRV_PCM_INFO_RESUME
+				  | SNDRV_PCM_INFO_PAUSE),
+	.formats		= (SNDRV_PCM_FMTBIT_S16_BE),
+	.rates			= (SNDRV_PCM_RATE_KNOT),
+	.rate_min		= RATE_MIN,
+	.rate_max		= RATE_MAX,
+	.channels_min		= 2,
+	.channels_max		= 2,
+	.buffer_bytes_max	= 64 * 4096,
+	.period_bytes_min	= 4096,
+	.period_bytes_max	= 4096,
+	.periods_min		= 4,
+	.periods_max		= 64,
+};
+
+static int atmel_abdac_open(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+
+	dac->substream = substream;
+	atmel_abdac_hw.rate_max = dac->rates[dac->rates_num - 1];
+	atmel_abdac_hw.rate_min = dac->rates[0];
+	substream->runtime->hw = atmel_abdac_hw;
+
+	return snd_pcm_hw_constraint_list(substream->runtime, 0,
+			SNDRV_PCM_HW_PARAM_RATE, &dac->constraints_rates);
+}
+
+static int atmel_abdac_close(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	dac->substream = NULL;
+	return 0;
+}
+
+static int atmel_abdac_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *hw_params)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	int retval;
+
+	retval = snd_pcm_lib_malloc_pages(substream,
+			params_buffer_bytes(hw_params));
+	if (retval < 0)
+		return retval;
+	/* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
+	if (retval == 1)
+		if (test_and_clear_bit(DMA_READY, &dac->flags))
+			dw_dma_cyclic_free(dac->dma.chan);
+
+	return retval;
+}
+
+static int atmel_abdac_hw_free(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	if (test_and_clear_bit(DMA_READY, &dac->flags))
+		dw_dma_cyclic_free(dac->dma.chan);
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int atmel_abdac_prepare(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	int retval;
+
+	retval = clk_set_rate(dac->sample_clk, 256 * substream->runtime->rate);
+	if (retval)
+		return retval;
+
+	if (!test_bit(DMA_READY, &dac->flags))
+		retval = atmel_abdac_prepare_dma(dac, substream, DMA_TO_DEVICE);
+
+	return retval;
+}
+
+static int atmel_abdac_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	int retval = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+	case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
+	case SNDRV_PCM_TRIGGER_START:
+		clk_enable(dac->sample_clk);
+		retval = dw_dma_cyclic_start(dac->dma.chan);
+		if (retval)
+			goto out;
+		dac_writel(dac, CTRL, DAC_BIT(EN));
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+	case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
+	case SNDRV_PCM_TRIGGER_STOP:
+		dw_dma_cyclic_stop(dac->dma.chan);
+		dac_writel(dac, DATA, 0);
+		dac_writel(dac, CTRL, 0);
+		clk_disable(dac->sample_clk);
+		break;
+	default:
+		retval = -EINVAL;
+		break;
+	}
+out:
+	return retval;
+}
+
+static snd_pcm_uframes_t
+atmel_abdac_pointer(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac	*dac = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime	*runtime = substream->runtime;
+	snd_pcm_uframes_t	frames;
+	unsigned long		bytes;
+
+	bytes = dw_dma_get_src_addr(dac->dma.chan);
+	bytes -= runtime->dma_addr;
+
+	frames = bytes_to_frames(runtime, bytes);
+	if (frames >= runtime->buffer_size)
+		frames -= runtime->buffer_size;
+
+	return frames;
+}
+
+static irqreturn_t abdac_interrupt(int irq, void *dev_id)
+{
+	struct atmel_abdac *dac = dev_id;
+	u32 status;
+
+	status = dac_readl(dac, INT_STATUS);
+	if (status & DAC_BIT(UNDERRUN)) {
+		dev_err(&dac->pdev->dev, "underrun detected\n");
+		dac_writel(dac, INT_CLR, DAC_BIT(UNDERRUN));
+	} else {
+		dev_err(&dac->pdev->dev, "spurious interrupt (status=0x%x)\n",
+			status);
+		dac_writel(dac, INT_CLR, status);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct snd_pcm_ops atmel_abdac_ops = {
+	.open		= atmel_abdac_open,
+	.close		= atmel_abdac_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= atmel_abdac_hw_params,
+	.hw_free	= atmel_abdac_hw_free,
+	.prepare	= atmel_abdac_prepare,
+	.trigger	= atmel_abdac_trigger,
+	.pointer	= atmel_abdac_pointer,
+};
+
+static int __devinit atmel_abdac_pcm_new(struct atmel_abdac *dac)
+{
+	struct snd_pcm_hardware hw = atmel_abdac_hw;
+	struct snd_pcm *pcm;
+	int retval;
+
+	retval = snd_pcm_new(dac->card, dac->card->shortname,
+			dac->pdev->id, 1, 0, &pcm);
+	if (retval)
+		return retval;
+
+	strcpy(pcm->name, dac->card->shortname);
+	pcm->private_data = dac;
+	pcm->info_flags = 0;
+	dac->pcm = pcm;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_abdac_ops);
+
+	retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+			&dac->pdev->dev, hw.periods_min * hw.period_bytes_min,
+			hw.buffer_bytes_max);
+
+	return retval;
+}
+
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	struct dw_dma_slave *dws = slave;
+
+	if (dws->dma_dev == chan->device->dev) {
+		chan->private = dws;
+		return true;
+	} else
+		return false;
+}
+
+static int set_sample_rates(struct atmel_abdac *dac)
+{
+	long new_rate = RATE_MAX;
+	int retval = -EINVAL;
+	int index = 0;
+
+	/* we start at 192 kHz and work our way down to 5112 Hz */
+	while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) {
+		new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate);
+		if (new_rate < 0)
+			break;
+		/* make sure we are below the ABDAC clock */
+		if (new_rate <= clk_get_rate(dac->pclk)) {
+			dac->rates[index] = new_rate / 256;
+			index++;
+		}
+		/* divide by 256 and then by two to get next rate */
+		new_rate /= 256 * 2;
+	}
+
+	if (index) {
+		int i;
+
+		/* reverse array, smallest go first */
+		for (i = 0; i < (index / 2); i++) {
+			unsigned int tmp = dac->rates[index - 1 - i];
+			dac->rates[index - 1 - i] = dac->rates[i];
+			dac->rates[i] = tmp;
+		}
+
+		dac->constraints_rates.count = index;
+		dac->constraints_rates.list = dac->rates;
+		dac->constraints_rates.mask = 0;
+		dac->rates_num = index;
+
+		retval = 0;
+	}
+
+	return retval;
+}
+
+static int __devinit atmel_abdac_probe(struct platform_device *pdev)
+{
+	struct snd_card		*card;
+	struct atmel_abdac	*dac;
+	struct resource		*regs;
+	struct atmel_abdac_pdata	*pdata;
+	struct clk		*pclk;
+	struct clk		*sample_clk;
+	int			retval;
+	int			irq;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_dbg(&pdev->dev, "no memory resource\n");
+		return -ENXIO;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_dbg(&pdev->dev, "could not get IRQ number\n");
+		return irq;
+	}
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_dbg(&pdev->dev, "no platform data\n");
+		return -ENXIO;
+	}
+
+	pclk = clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(pclk)) {
+		dev_dbg(&pdev->dev, "no peripheral clock\n");
+		return PTR_ERR(pclk);
+	}
+	sample_clk = clk_get(&pdev->dev, "sample_clk");
+	if (IS_ERR(pclk)) {
+		dev_dbg(&pdev->dev, "no sample clock\n");
+		retval = PTR_ERR(pclk);
+		goto out_put_pclk;
+	}
+	clk_enable(pclk);
+
+	retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			THIS_MODULE, sizeof(struct atmel_abdac), &card);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not create sound card device\n");
+		goto out_put_sample_clk;
+	}
+
+	dac = get_dac(card);
+
+	dac->irq = irq;
+	dac->card = card;
+	dac->pclk = pclk;
+	dac->sample_clk = sample_clk;
+	dac->pdev = pdev;
+
+	retval = set_sample_rates(dac);
+	if (retval < 0) {
+		dev_dbg(&pdev->dev, "could not set supported rates\n");
+		goto out_free_card;
+	}
+
+	dac->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!dac->regs) {
+		dev_dbg(&pdev->dev, "could not remap register memory\n");
+		goto out_free_card;
+	}
+
+	/* make sure the DAC is silent and disabled */
+	dac_writel(dac, DATA, 0);
+	dac_writel(dac, CTRL, 0);
+
+	retval = request_irq(irq, abdac_interrupt, 0, "abdac", dac);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not request irq\n");
+		goto out_unmap_regs;
+	}
+
+	snd_card_set_dev(card, &pdev->dev);
+
+	if (pdata->dws.dma_dev) {
+		struct dw_dma_slave *dws = &pdata->dws;
+		dma_cap_mask_t mask;
+
+		dws->tx_reg = regs->start + DAC_DATA;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		dac->dma.chan = dma_request_channel(mask, filter, dws);
+	}
+	if (!pdata->dws.dma_dev || !dac->dma.chan) {
+		dev_dbg(&pdev->dev, "DMA not available\n");
+		retval = -ENODEV;
+		goto out_unset_card_dev;
+	}
+
+	strcpy(card->driver, "Atmel ABDAC");
+	strcpy(card->shortname, "Atmel ABDAC");
+	sprintf(card->longname, "Atmel Audio Bitstream DAC");
+
+	retval = atmel_abdac_pcm_new(dac);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register ABDAC pcm device\n");
+		goto out_release_dma;
+	}
+
+	retval = snd_card_register(card);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register sound card\n");
+		goto out_release_dma;
+	}
+
+	platform_set_drvdata(pdev, card);
+
+	dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n",
+			dac->regs, dac->dma.chan->dev->device.bus_id);
+
+	return retval;
+
+out_release_dma:
+	dma_release_channel(dac->dma.chan);
+	dac->dma.chan = NULL;
+out_unset_card_dev:
+	snd_card_set_dev(card, NULL);
+	free_irq(irq, dac);
+out_unmap_regs:
+	iounmap(dac->regs);
+out_free_card:
+	snd_card_free(card);
+out_put_sample_clk:
+	clk_put(sample_clk);
+	clk_disable(pclk);
+out_put_pclk:
+	clk_put(pclk);
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int atmel_abdac_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_abdac *dac = card->private_data;
+
+	dw_dma_cyclic_stop(dac->dma.chan);
+	clk_disable(dac->sample_clk);
+	clk_disable(dac->pclk);
+
+	return 0;
+}
+
+static int atmel_abdac_resume(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_abdac *dac = card->private_data;
+
+	clk_enable(dac->pclk);
+	clk_enable(dac->sample_clk);
+	if (test_bit(DMA_READY, &dac->flags))
+		dw_dma_cyclic_start(dac->dma.chan);
+
+	return 0;
+}
+#else
+#define atmel_abdac_suspend NULL
+#define atmel_abdac_resume NULL
+#endif
+
+static int __devexit atmel_abdac_remove(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_abdac *dac = get_dac(card);
+
+	clk_put(dac->sample_clk);
+	clk_disable(dac->pclk);
+	clk_put(dac->pclk);
+
+	dma_release_channel(dac->dma.chan);
+	dac->dma.chan = NULL;
+	snd_card_set_dev(card, NULL);
+	iounmap(dac->regs);
+	free_irq(dac->irq, dac);
+	snd_card_free(card);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver atmel_abdac_driver = {
+	.remove		= __devexit_p(atmel_abdac_remove),
+	.driver		= {
+		.name	= "atmel_abdac",
+	},
+	.suspend	= atmel_abdac_suspend,
+	.resume		= atmel_abdac_resume,
+};
+
+static int __init atmel_abdac_init(void)
+{
+	return platform_driver_probe(&atmel_abdac_driver,
+			atmel_abdac_probe);
+}
+module_init(atmel_abdac_init);
+
+static void __exit atmel_abdac_exit(void)
+{
+	platform_driver_unregister(&atmel_abdac_driver);
+}
+module_exit(atmel_abdac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for Atmel Audio Bitstream DAC (ABDAC)");
+MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
new file mode 100644
index 0000000..dd72e00
--- /dev/null
+++ b/sound/atmel/ac97c.c
@@ -0,0 +1,932 @@
+/*
+ * Driver for the Atmel AC97C controller
+ *
+ * Copyright (C) 2005-2009 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/bitmap.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+#include <sound/atmel-ac97c.h>
+#include <sound/memalloc.h>
+
+#include <linux/dw_dmac.h>
+
+#include "ac97c.h"
+
+enum {
+	DMA_TX_READY = 0,
+	DMA_RX_READY,
+	DMA_TX_CHAN_PRESENT,
+	DMA_RX_CHAN_PRESENT,
+};
+
+/* Serialize access to opened variable */
+static DEFINE_MUTEX(opened_mutex);
+
+struct atmel_ac97c_dma {
+	struct dma_chan			*rx_chan;
+	struct dma_chan			*tx_chan;
+};
+
+struct atmel_ac97c {
+	struct clk			*pclk;
+	struct platform_device		*pdev;
+	struct atmel_ac97c_dma		dma;
+
+	struct snd_pcm_substream	*playback_substream;
+	struct snd_pcm_substream	*capture_substream;
+	struct snd_card			*card;
+	struct snd_pcm			*pcm;
+	struct snd_ac97			*ac97;
+	struct snd_ac97_bus		*ac97_bus;
+
+	u64				cur_format;
+	unsigned int			cur_rate;
+	unsigned long			flags;
+	/* Serialize access to opened variable */
+	spinlock_t			lock;
+	void __iomem			*regs;
+	int				opened;
+	int				reset_pin;
+};
+
+#define get_chip(card) ((struct atmel_ac97c *)(card)->private_data)
+
+#define ac97c_writel(chip, reg, val)			\
+	__raw_writel((val), (chip)->regs + AC97C_##reg)
+#define ac97c_readl(chip, reg)				\
+	__raw_readl((chip)->regs + AC97C_##reg)
+
+/* This function is called by the DMA driver. */
+static void atmel_ac97c_dma_playback_period_done(void *arg)
+{
+	struct atmel_ac97c *chip = arg;
+	snd_pcm_period_elapsed(chip->playback_substream);
+}
+
+static void atmel_ac97c_dma_capture_period_done(void *arg)
+{
+	struct atmel_ac97c *chip = arg;
+	snd_pcm_period_elapsed(chip->capture_substream);
+}
+
+static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
+		struct snd_pcm_substream *substream,
+		enum dma_data_direction direction)
+{
+	struct dma_chan			*chan;
+	struct dw_cyclic_desc		*cdesc;
+	struct snd_pcm_runtime		*runtime = substream->runtime;
+	unsigned long			buffer_len, period_len;
+
+	/*
+	 * We don't do DMA on "complex" transfers, i.e. with
+	 * non-halfword-aligned buffers or lengths.
+	 */
+	if (runtime->dma_addr & 1 || runtime->buffer_size & 1) {
+		dev_dbg(&chip->pdev->dev, "too complex transfer\n");
+		return -EINVAL;
+	}
+
+	if (direction == DMA_TO_DEVICE)
+		chan = chip->dma.tx_chan;
+	else
+		chan = chip->dma.rx_chan;
+
+	buffer_len = frames_to_bytes(runtime, runtime->buffer_size);
+	period_len = frames_to_bytes(runtime, runtime->period_size);
+
+	cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
+			period_len, direction);
+	if (IS_ERR(cdesc)) {
+		dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n");
+		return PTR_ERR(cdesc);
+	}
+
+	if (direction == DMA_TO_DEVICE) {
+		cdesc->period_callback = atmel_ac97c_dma_playback_period_done;
+		set_bit(DMA_TX_READY, &chip->flags);
+	} else {
+		cdesc->period_callback = atmel_ac97c_dma_capture_period_done;
+		set_bit(DMA_RX_READY, &chip->flags);
+	}
+
+	cdesc->period_callback_param = chip;
+
+	return 0;
+}
+
+static struct snd_pcm_hardware atmel_ac97c_hw = {
+	.info			= (SNDRV_PCM_INFO_MMAP
+				  | SNDRV_PCM_INFO_MMAP_VALID
+				  | SNDRV_PCM_INFO_INTERLEAVED
+				  | SNDRV_PCM_INFO_BLOCK_TRANSFER
+				  | SNDRV_PCM_INFO_JOINT_DUPLEX
+				  | SNDRV_PCM_INFO_RESUME
+				  | SNDRV_PCM_INFO_PAUSE),
+	.formats		= (SNDRV_PCM_FMTBIT_S16_BE
+				  | SNDRV_PCM_FMTBIT_S16_LE),
+	.rates			= (SNDRV_PCM_RATE_CONTINUOUS),
+	.rate_min		= 4000,
+	.rate_max		= 48000,
+	.channels_min		= 1,
+	.channels_max		= 2,
+	.buffer_bytes_max	= 64 * 4096,
+	.period_bytes_min	= 4096,
+	.period_bytes_max	= 4096,
+	.periods_min		= 4,
+	.periods_max		= 64,
+};
+
+static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	mutex_lock(&opened_mutex);
+	chip->opened++;
+	runtime->hw = atmel_ac97c_hw;
+	if (chip->cur_rate) {
+		runtime->hw.rate_min = chip->cur_rate;
+		runtime->hw.rate_max = chip->cur_rate;
+	}
+	if (chip->cur_format)
+		runtime->hw.formats = (1ULL << chip->cur_format);
+	mutex_unlock(&opened_mutex);
+	chip->playback_substream = substream;
+	return 0;
+}
+
+static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	mutex_lock(&opened_mutex);
+	chip->opened++;
+	runtime->hw = atmel_ac97c_hw;
+	if (chip->cur_rate) {
+		runtime->hw.rate_min = chip->cur_rate;
+		runtime->hw.rate_max = chip->cur_rate;
+	}
+	if (chip->cur_format)
+		runtime->hw.formats = (1ULL << chip->cur_format);
+	mutex_unlock(&opened_mutex);
+	chip->capture_substream = substream;
+	return 0;
+}
+
+static int atmel_ac97c_playback_close(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+
+	mutex_lock(&opened_mutex);
+	chip->opened--;
+	if (!chip->opened) {
+		chip->cur_rate = 0;
+		chip->cur_format = 0;
+	}
+	mutex_unlock(&opened_mutex);
+
+	chip->playback_substream = NULL;
+
+	return 0;
+}
+
+static int atmel_ac97c_capture_close(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+
+	mutex_lock(&opened_mutex);
+	chip->opened--;
+	if (!chip->opened) {
+		chip->cur_rate = 0;
+		chip->cur_format = 0;
+	}
+	mutex_unlock(&opened_mutex);
+
+	chip->capture_substream = NULL;
+
+	return 0;
+}
+
+static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *hw_params)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	int retval;
+
+	retval = snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+	if (retval < 0)
+		return retval;
+	/* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
+	if (retval == 1)
+		if (test_and_clear_bit(DMA_TX_READY, &chip->flags))
+			dw_dma_cyclic_free(chip->dma.tx_chan);
+
+	/* Set restrictions to params. */
+	mutex_lock(&opened_mutex);
+	chip->cur_rate = params_rate(hw_params);
+	chip->cur_format = params_format(hw_params);
+	mutex_unlock(&opened_mutex);
+
+	return retval;
+}
+
+static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *hw_params)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	int retval;
+
+	retval = snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+	if (retval < 0)
+		return retval;
+	/* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
+	if (retval == 1)
+		if (test_and_clear_bit(DMA_RX_READY, &chip->flags))
+			dw_dma_cyclic_free(chip->dma.rx_chan);
+
+	/* Set restrictions to params. */
+	mutex_lock(&opened_mutex);
+	chip->cur_rate = params_rate(hw_params);
+	chip->cur_format = params_format(hw_params);
+	mutex_unlock(&opened_mutex);
+
+	return retval;
+}
+
+static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	if (test_and_clear_bit(DMA_TX_READY, &chip->flags))
+		dw_dma_cyclic_free(chip->dma.tx_chan);
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	if (test_and_clear_bit(DMA_RX_READY, &chip->flags))
+		dw_dma_cyclic_free(chip->dma.rx_chan);
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned long word = 0;
+	int retval;
+
+	/* assign channels to AC97C channel A */
+	switch (runtime->channels) {
+	case 1:
+		word |= AC97C_CH_ASSIGN(PCM_LEFT, A);
+		break;
+	case 2:
+		word |= AC97C_CH_ASSIGN(PCM_LEFT, A)
+			| AC97C_CH_ASSIGN(PCM_RIGHT, A);
+		break;
+	default:
+		/* TODO: support more than two channels */
+		return -EINVAL;
+		break;
+	}
+	ac97c_writel(chip, OCA, word);
+
+	/* configure sample format and size */
+	word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
+
+	switch (runtime->format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		word |= AC97C_CMR_CEM_LITTLE;
+		break;
+	case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
+	default:
+		word &= ~(AC97C_CMR_CEM_LITTLE);
+		break;
+	}
+
+	ac97c_writel(chip, CAMR, word);
+
+	/* set variable rate if needed */
+	if (runtime->rate != 48000) {
+		word = ac97c_readl(chip, MR);
+		word |= AC97C_MR_VRA;
+		ac97c_writel(chip, MR, word);
+	} else {
+		word = ac97c_readl(chip, MR);
+		word &= ~(AC97C_MR_VRA);
+		ac97c_writel(chip, MR, word);
+	}
+
+	retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE,
+			runtime->rate);
+	if (retval)
+		dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n",
+				runtime->rate);
+
+	if (!test_bit(DMA_TX_READY, &chip->flags))
+		retval = atmel_ac97c_prepare_dma(chip, substream,
+				DMA_TO_DEVICE);
+
+	return retval;
+}
+
+static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned long word = 0;
+	int retval;
+
+	/* assign channels to AC97C channel A */
+	switch (runtime->channels) {
+	case 1:
+		word |= AC97C_CH_ASSIGN(PCM_LEFT, A);
+		break;
+	case 2:
+		word |= AC97C_CH_ASSIGN(PCM_LEFT, A)
+			| AC97C_CH_ASSIGN(PCM_RIGHT, A);
+		break;
+	default:
+		/* TODO: support more than two channels */
+		return -EINVAL;
+		break;
+	}
+	ac97c_writel(chip, ICA, word);
+
+	/* configure sample format and size */
+	word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
+
+	switch (runtime->format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		word |= AC97C_CMR_CEM_LITTLE;
+		break;
+	case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
+	default:
+		word &= ~(AC97C_CMR_CEM_LITTLE);
+		break;
+	}
+
+	ac97c_writel(chip, CAMR, word);
+
+	/* set variable rate if needed */
+	if (runtime->rate != 48000) {
+		word = ac97c_readl(chip, MR);
+		word |= AC97C_MR_VRA;
+		ac97c_writel(chip, MR, word);
+	} else {
+		word = ac97c_readl(chip, MR);
+		word &= ~(AC97C_MR_VRA);
+		ac97c_writel(chip, MR, word);
+	}
+
+	retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE,
+			runtime->rate);
+	if (retval)
+		dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n",
+				runtime->rate);
+
+	if (!test_bit(DMA_RX_READY, &chip->flags))
+		retval = atmel_ac97c_prepare_dma(chip, substream,
+				DMA_FROM_DEVICE);
+
+	return retval;
+}
+
+static int
+atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	unsigned long camr;
+	int retval = 0;
+
+	camr = ac97c_readl(chip, CAMR);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+	case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
+	case SNDRV_PCM_TRIGGER_START:
+		retval = dw_dma_cyclic_start(chip->dma.tx_chan);
+		if (retval)
+			goto out;
+		camr |= AC97C_CMR_CENA;
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+	case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
+	case SNDRV_PCM_TRIGGER_STOP:
+		dw_dma_cyclic_stop(chip->dma.tx_chan);
+		if (chip->opened <= 1)
+			camr &= ~AC97C_CMR_CENA;
+		break;
+	default:
+		retval = -EINVAL;
+		goto out;
+	}
+
+	ac97c_writel(chip, CAMR, camr);
+out:
+	return retval;
+}
+
+static int
+atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	unsigned long camr;
+	int retval = 0;
+
+	camr = ac97c_readl(chip, CAMR);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+	case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
+	case SNDRV_PCM_TRIGGER_START:
+		retval = dw_dma_cyclic_start(chip->dma.rx_chan);
+		if (retval)
+			goto out;
+		camr |= AC97C_CMR_CENA;
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+	case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
+	case SNDRV_PCM_TRIGGER_STOP:
+		dw_dma_cyclic_stop(chip->dma.rx_chan);
+		if (chip->opened <= 1)
+			camr &= ~AC97C_CMR_CENA;
+		break;
+	default:
+		retval = -EINVAL;
+		break;
+	}
+
+	ac97c_writel(chip, CAMR, camr);
+out:
+	return retval;
+}
+
+static snd_pcm_uframes_t
+atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c	*chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime	*runtime = substream->runtime;
+	snd_pcm_uframes_t	frames;
+	unsigned long		bytes;
+
+	bytes = dw_dma_get_src_addr(chip->dma.tx_chan);
+	bytes -= runtime->dma_addr;
+
+	frames = bytes_to_frames(runtime, bytes);
+	if (frames >= runtime->buffer_size)
+		frames -= runtime->buffer_size;
+	return frames;
+}
+
+static snd_pcm_uframes_t
+atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c	*chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime	*runtime = substream->runtime;
+	snd_pcm_uframes_t	frames;
+	unsigned long		bytes;
+
+	bytes = dw_dma_get_dst_addr(chip->dma.rx_chan);
+	bytes -= runtime->dma_addr;
+
+	frames = bytes_to_frames(runtime, bytes);
+	if (frames >= runtime->buffer_size)
+		frames -= runtime->buffer_size;
+	return frames;
+}
+
+static struct snd_pcm_ops atmel_ac97_playback_ops = {
+	.open		= atmel_ac97c_playback_open,
+	.close		= atmel_ac97c_playback_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= atmel_ac97c_playback_hw_params,
+	.hw_free	= atmel_ac97c_playback_hw_free,
+	.prepare	= atmel_ac97c_playback_prepare,
+	.trigger	= atmel_ac97c_playback_trigger,
+	.pointer	= atmel_ac97c_playback_pointer,
+};
+
+static struct snd_pcm_ops atmel_ac97_capture_ops = {
+	.open		= atmel_ac97c_capture_open,
+	.close		= atmel_ac97c_capture_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= atmel_ac97c_capture_hw_params,
+	.hw_free	= atmel_ac97c_capture_hw_free,
+	.prepare	= atmel_ac97c_capture_prepare,
+	.trigger	= atmel_ac97c_capture_trigger,
+	.pointer	= atmel_ac97c_capture_pointer,
+};
+
+static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
+{
+	struct snd_pcm		*pcm;
+	struct snd_pcm_hardware	hw = atmel_ac97c_hw;
+	int			capture, playback, retval;
+
+	capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
+	playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+
+	retval = snd_pcm_new(chip->card, chip->card->shortname,
+			chip->pdev->id, playback, capture, &pcm);
+	if (retval)
+		return retval;
+
+	if (capture)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+				&atmel_ac97_capture_ops);
+	if (playback)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				&atmel_ac97_playback_ops);
+
+	retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+			&chip->pdev->dev, hw.periods_min * hw.period_bytes_min,
+			hw.buffer_bytes_max);
+	if (retval)
+		return retval;
+
+	pcm->private_data = chip;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, chip->card->shortname);
+	chip->pcm = pcm;
+
+	return 0;
+}
+
+static int atmel_ac97c_mixer_new(struct atmel_ac97c *chip)
+{
+	struct snd_ac97_template template;
+	memset(&template, 0, sizeof(template));
+	template.private_data = chip;
+	return snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97);
+}
+
+static void atmel_ac97c_write(struct snd_ac97 *ac97, unsigned short reg,
+		unsigned short val)
+{
+	struct atmel_ac97c *chip = get_chip(ac97);
+	unsigned long word;
+	int timeout = 40;
+
+	word = (reg & 0x7f) << 16 | val;
+
+	do {
+		if (ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) {
+			ac97c_writel(chip, COTHR, word);
+			return;
+		}
+		udelay(1);
+	} while (--timeout);
+
+	dev_dbg(&chip->pdev->dev, "codec write timeout\n");
+}
+
+static unsigned short atmel_ac97c_read(struct snd_ac97 *ac97,
+		unsigned short reg)
+{
+	struct atmel_ac97c *chip = get_chip(ac97);
+	unsigned long word;
+	int timeout = 40;
+	int write = 10;
+
+	word = (0x80 | (reg & 0x7f)) << 16;
+
+	if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0)
+		ac97c_readl(chip, CORHR);
+
+retry_write:
+	timeout = 40;
+
+	do {
+		if ((ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) != 0) {
+			ac97c_writel(chip, COTHR, word);
+			goto read_reg;
+		}
+		udelay(10);
+	} while (--timeout);
+
+	if (!--write)
+		goto timed_out;
+	goto retry_write;
+
+read_reg:
+	do {
+		if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) {
+			unsigned short val = ac97c_readl(chip, CORHR);
+			return val;
+		}
+		udelay(10);
+	} while (--timeout);
+
+	if (!--write)
+		goto timed_out;
+	goto retry_write;
+
+timed_out:
+	dev_dbg(&chip->pdev->dev, "codec read timeout\n");
+	return 0xffff;
+}
+
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	struct dw_dma_slave *dws = slave;
+
+	if (dws->dma_dev == chan->device->dev) {
+		chan->private = dws;
+		return true;
+	} else
+		return false;
+}
+
+static void atmel_ac97c_reset(struct atmel_ac97c *chip)
+{
+	ac97c_writel(chip, MR, AC97C_MR_WRST);
+
+	if (gpio_is_valid(chip->reset_pin)) {
+		gpio_set_value(chip->reset_pin, 0);
+		/* AC97 v2.2 specifications says minimum 1 us. */
+		udelay(10);
+		gpio_set_value(chip->reset_pin, 1);
+	}
+
+	udelay(1);
+	ac97c_writel(chip, MR, AC97C_MR_ENA);
+}
+
+static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
+{
+	struct snd_card			*card;
+	struct atmel_ac97c		*chip;
+	struct resource			*regs;
+	struct ac97c_platform_data	*pdata;
+	struct clk			*pclk;
+	static struct snd_ac97_bus_ops	ops = {
+		.write	= atmel_ac97c_write,
+		.read	= atmel_ac97c_read,
+	};
+	int				retval;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_dbg(&pdev->dev, "no memory resource\n");
+		return -ENXIO;
+	}
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_dbg(&pdev->dev, "no platform data\n");
+		return -ENXIO;
+	}
+
+	pclk = clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(pclk)) {
+		dev_dbg(&pdev->dev, "no peripheral clock\n");
+		return PTR_ERR(pclk);
+	}
+	clk_enable(pclk);
+
+	retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			THIS_MODULE, sizeof(struct atmel_ac97c), &card);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not create sound card device\n");
+		goto err_snd_card_new;
+	}
+
+	chip = get_chip(card);
+
+	spin_lock_init(&chip->lock);
+
+	strcpy(card->driver, "Atmel AC97C");
+	strcpy(card->shortname, "Atmel AC97C");
+	sprintf(card->longname, "Atmel AC97 controller");
+
+	chip->card = card;
+	chip->pclk = pclk;
+	chip->pdev = pdev;
+	chip->regs = ioremap(regs->start, regs->end - regs->start + 1);
+
+	if (!chip->regs) {
+		dev_dbg(&pdev->dev, "could not remap register memory\n");
+		goto err_ioremap;
+	}
+
+	if (gpio_is_valid(pdata->reset_pin)) {
+		if (gpio_request(pdata->reset_pin, "reset_pin")) {
+			dev_dbg(&pdev->dev, "reset pin not available\n");
+			chip->reset_pin = -ENODEV;
+		} else {
+			gpio_direction_output(pdata->reset_pin, 1);
+			chip->reset_pin = pdata->reset_pin;
+		}
+	}
+
+	snd_card_set_dev(card, &pdev->dev);
+
+	retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register on ac97 bus\n");
+		goto err_ac97_bus;
+	}
+
+	atmel_ac97c_reset(chip);
+
+	retval = atmel_ac97c_mixer_new(chip);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register ac97 mixer\n");
+		goto err_ac97_bus;
+	}
+
+	if (pdata->rx_dws.dma_dev) {
+		struct dw_dma_slave *dws = &pdata->rx_dws;
+		dma_cap_mask_t mask;
+
+		dws->rx_reg = regs->start + AC97C_CARHR + 2;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		chip->dma.rx_chan = dma_request_channel(mask, filter, dws);
+
+		dev_info(&chip->pdev->dev, "using %s for DMA RX\n",
+					chip->dma.rx_chan->dev->device.bus_id);
+		set_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
+	}
+
+	if (pdata->tx_dws.dma_dev) {
+		struct dw_dma_slave *dws = &pdata->tx_dws;
+		dma_cap_mask_t mask;
+
+		dws->tx_reg = regs->start + AC97C_CATHR + 2;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		chip->dma.tx_chan = dma_request_channel(mask, filter, dws);
+
+		dev_info(&chip->pdev->dev, "using %s for DMA TX\n",
+					chip->dma.tx_chan->dev->device.bus_id);
+		set_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+	}
+
+	if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) &&
+			!test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) {
+		dev_dbg(&pdev->dev, "DMA not available\n");
+		retval = -ENODEV;
+		goto err_dma;
+	}
+
+	retval = atmel_ac97c_pcm_new(chip);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register ac97 pcm device\n");
+		goto err_dma;
+	}
+
+	retval = snd_card_register(card);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register sound card\n");
+		goto err_ac97_bus;
+	}
+
+	platform_set_drvdata(pdev, card);
+
+	dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p\n",
+			chip->regs);
+
+	return 0;
+
+err_dma:
+	if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags))
+		dma_release_channel(chip->dma.rx_chan);
+	if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags))
+		dma_release_channel(chip->dma.tx_chan);
+	clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
+	clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+	chip->dma.rx_chan = NULL;
+	chip->dma.tx_chan = NULL;
+err_ac97_bus:
+	snd_card_set_dev(card, NULL);
+
+	if (gpio_is_valid(chip->reset_pin))
+		gpio_free(chip->reset_pin);
+
+	iounmap(chip->regs);
+err_ioremap:
+	snd_card_free(card);
+err_snd_card_new:
+	clk_disable(pclk);
+	clk_put(pclk);
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_ac97c *chip = card->private_data;
+
+	if (test_bit(DMA_RX_READY, &chip->flags))
+		dw_dma_cyclic_stop(chip->dma.rx_chan);
+	if (test_bit(DMA_TX_READY, &chip->flags))
+		dw_dma_cyclic_stop(chip->dma.tx_chan);
+	clk_disable(chip->pclk);
+
+	return 0;
+}
+
+static int atmel_ac97c_resume(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_ac97c *chip = card->private_data;
+
+	clk_enable(chip->pclk);
+	if (test_bit(DMA_RX_READY, &chip->flags))
+		dw_dma_cyclic_start(chip->dma.rx_chan);
+	if (test_bit(DMA_TX_READY, &chip->flags))
+		dw_dma_cyclic_start(chip->dma.tx_chan);
+
+	return 0;
+}
+#else
+#define atmel_ac97c_suspend NULL
+#define atmel_ac97c_resume NULL
+#endif
+
+static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_ac97c *chip = get_chip(card);
+
+	if (gpio_is_valid(chip->reset_pin))
+		gpio_free(chip->reset_pin);
+
+	clk_disable(chip->pclk);
+	clk_put(chip->pclk);
+	iounmap(chip->regs);
+
+	if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags))
+		dma_release_channel(chip->dma.rx_chan);
+	if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags))
+		dma_release_channel(chip->dma.tx_chan);
+	clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
+	clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+	chip->dma.rx_chan = NULL;
+	chip->dma.tx_chan = NULL;
+
+	snd_card_set_dev(card, NULL);
+	snd_card_free(card);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver atmel_ac97c_driver = {
+	.remove		= __devexit_p(atmel_ac97c_remove),
+	.driver		= {
+		.name	= "atmel_ac97c",
+	},
+	.suspend	= atmel_ac97c_suspend,
+	.resume		= atmel_ac97c_resume,
+};
+
+static int __init atmel_ac97c_init(void)
+{
+	return platform_driver_probe(&atmel_ac97c_driver,
+			atmel_ac97c_probe);
+}
+module_init(atmel_ac97c_init);
+
+static void __exit atmel_ac97c_exit(void)
+{
+	platform_driver_unregister(&atmel_ac97c_driver);
+}
+module_exit(atmel_ac97c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for Atmel AC97 controller");
+MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
diff --git a/sound/atmel/ac97c.h b/sound/atmel/ac97c.h
new file mode 100644
index 0000000..c17bd58
--- /dev/null
+++ b/sound/atmel/ac97c.h
@@ -0,0 +1,71 @@
+/*
+ * Register definitions for the Atmel AC97C controller
+ *
+ * Copyright (C) 2005-2009 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 __SOUND_ATMEL_AC97C_H
+#define __SOUND_ATMEL_AC97C_H
+
+#define AC97C_MR		0x08
+#define AC97C_ICA		0x10
+#define AC97C_OCA		0x14
+#define AC97C_CARHR		0x20
+#define AC97C_CATHR		0x24
+#define AC97C_CASR		0x28
+#define AC97C_CAMR		0x2c
+#define AC97C_CBRHR		0x30
+#define AC97C_CBTHR		0x34
+#define AC97C_CBSR		0x38
+#define AC97C_CBMR		0x3c
+#define AC97C_CORHR		0x40
+#define AC97C_COTHR		0x44
+#define AC97C_COSR		0x48
+#define AC97C_COMR		0x4c
+#define AC97C_SR		0x50
+#define AC97C_IER		0x54
+#define AC97C_IDR		0x58
+#define AC97C_IMR		0x5c
+#define AC97C_VERSION		0xfc
+
+#define AC97C_CATPR		PDC_TPR
+#define AC97C_CATCR		PDC_TCR
+#define AC97C_CATNPR		PDC_TNPR
+#define AC97C_CATNCR		PDC_TNCR
+#define AC97C_CARPR		PDC_RPR
+#define AC97C_CARCR		PDC_RCR
+#define AC97C_CARNPR		PDC_RNPR
+#define AC97C_CARNCR		PDC_RNCR
+#define AC97C_PTCR		PDC_PTCR
+
+#define AC97C_MR_ENA		(1 << 0)
+#define AC97C_MR_WRST		(1 << 1)
+#define AC97C_MR_VRA		(1 << 2)
+
+#define AC97C_CSR_TXRDY		(1 << 0)
+#define AC97C_CSR_UNRUN		(1 << 2)
+#define AC97C_CSR_RXRDY		(1 << 4)
+#define AC97C_CSR_ENDTX		(1 << 10)
+#define AC97C_CSR_ENDRX		(1 << 14)
+
+#define AC97C_CMR_SIZE_20	(0 << 16)
+#define AC97C_CMR_SIZE_18	(1 << 16)
+#define AC97C_CMR_SIZE_16	(2 << 16)
+#define AC97C_CMR_SIZE_10	(3 << 16)
+#define AC97C_CMR_CEM_LITTLE	(1 << 18)
+#define AC97C_CMR_CEM_BIG	(0 << 18)
+#define AC97C_CMR_CENA		(1 << 21)
+#define AC97C_CMR_DMAEN		(1 << 22)
+
+#define AC97C_SR_CAEVT		(1 << 3)
+
+#define AC97C_CH_ASSIGN(slot, channel)					\
+	(AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3)))
+#define AC97C_CHANNEL_NONE	0x0
+#define AC97C_CHANNEL_A		0x1
+#define AC97C_CHANNEL_B		0x2
+
+#endif /* __SOUND_ATMEL_AC97C_H */
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 195cafc..a70ee7f 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -99,9 +99,6 @@
 	if (hw == NULL)
 		return -ENODEV;
 
-	if (!hw->ops.open)
-		return -ENXIO;
-
 	if (!try_module_get(hw->card->module))
 		return -EFAULT;
 
@@ -113,6 +110,10 @@
 			err = -EBUSY;
 			break;
 		}
+		if (!hw->ops.open) {
+			err = 0;
+			break;
+		}
 		err = hw->ops.open(hw, file);
 		if (err >= 0)
 			break;
@@ -151,7 +152,7 @@
 
 static int snd_hwdep_release(struct inode *inode, struct file * file)
 {
-	int err = -ENXIO;
+	int err = 0;
 	struct snd_hwdep *hw = file->private_data;
 	struct module *mod = hw->card->module;
 
diff --git a/sound/core/init.c b/sound/core/init.c
index 0d5520c..fd56afe 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -121,31 +121,44 @@
 #endif
 
 /**
- *  snd_card_new - create and initialize a soundcard structure
+ *  snd_card_create - create and initialize a soundcard structure
  *  @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
  *  @xid: card identification (ASCII string)
  *  @module: top level module for locking
  *  @extra_size: allocate this extra size after the main soundcard structure
+ *  @card_ret: the pointer to store the created card instance
  *
  *  Creates and initializes a soundcard structure.
  *
- *  Returns kmallocated snd_card structure. Creates the ALSA control interface
- *  (which is blocked until snd_card_register function is called).
+ *  The function allocates snd_card instance via kzalloc with the given
+ *  space for the driver to use freely.  The allocated struct is stored
+ *  in the given card_ret pointer.
+ *
+ *  Returns zero if successful or a negative error code.
  */
-struct snd_card *snd_card_new(int idx, const char *xid,
-			 struct module *module, int extra_size)
+int snd_card_create(int idx, const char *xid,
+		    struct module *module, int extra_size,
+		    struct snd_card **card_ret)
 {
 	struct snd_card *card;
 	int err, idx2;
 
+	if (snd_BUG_ON(!card_ret))
+		return -EINVAL;
+	*card_ret = NULL;
+
 	if (extra_size < 0)
 		extra_size = 0;
 	card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
-	if (card == NULL)
-		return NULL;
+	if (!card)
+		return -ENOMEM;
 	if (xid) {
-		if (!snd_info_check_reserved_words(xid))
+		if (!snd_info_check_reserved_words(xid)) {
+			snd_printk(KERN_ERR
+				   "given id string '%s' is reserved.\n", xid);
+			err = -EBUSY;
 			goto __error;
+		}
 		strlcpy(card->id, xid, sizeof(card->id));
 	}
 	err = 0;
@@ -195,6 +208,7 @@
 	INIT_LIST_HEAD(&card->controls);
 	INIT_LIST_HEAD(&card->ctl_files);
 	spin_lock_init(&card->files_lock);
+	INIT_LIST_HEAD(&card->files_list);
 	init_waitqueue_head(&card->shutdown_sleep);
 #ifdef CONFIG_PM
 	mutex_init(&card->power_lock);
@@ -202,26 +216,28 @@
 #endif
 	/* the control interface cannot be accessed from the user space until */
 	/* snd_cards_bitmask and snd_cards are set with snd_card_register */
-	if ((err = snd_ctl_create(card)) < 0) {
-		snd_printd("unable to register control minors\n");
+	err = snd_ctl_create(card);
+	if (err < 0) {
+		snd_printk(KERN_ERR "unable to register control minors\n");
 		goto __error;
 	}
-	if ((err = snd_info_card_create(card)) < 0) {
-		snd_printd("unable to create card info\n");
+	err = snd_info_card_create(card);
+	if (err < 0) {
+		snd_printk(KERN_ERR "unable to create card info\n");
 		goto __error_ctl;
 	}
 	if (extra_size > 0)
 		card->private_data = (char *)card + sizeof(struct snd_card);
-	return card;
+	*card_ret = card;
+	return 0;
 
       __error_ctl:
 	snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
       __error:
 	kfree(card);
-      	return NULL;
+  	return err;
 }
-
-EXPORT_SYMBOL(snd_card_new);
+EXPORT_SYMBOL(snd_card_create);
 
 /* return non-zero if a card is already locked */
 int snd_card_locked(int card)
@@ -259,6 +275,7 @@
 	list_for_each_entry(_df, &shutdown_files, shutdown_list) {
 		if (_df->file == file) {
 			df = _df;
+			list_del_init(&df->shutdown_list);
 			break;
 		}
 	}
@@ -347,8 +364,7 @@
 	/* phase 2: replace file->f_op with special dummy operations */
 	
 	spin_lock(&card->files_lock);
-	mfile = card->files;
-	while (mfile) {
+	list_for_each_entry(mfile, &card->files_list, list) {
 		file = mfile->file;
 
 		/* it's critical part, use endless loop */
@@ -361,8 +377,6 @@
 
 		mfile->file->f_op = &snd_shutdown_f_ops;
 		fops_get(mfile->file->f_op);
-		
-		mfile = mfile->next;
 	}
 	spin_unlock(&card->files_lock);	
 
@@ -442,7 +456,7 @@
 		return ret;
 
 	spin_lock(&card->files_lock);
-	if (card->files == NULL)
+	if (list_empty(&card->files_list))
 		free_now = 1;
 	else
 		card->free_on_last_close = 1;
@@ -462,7 +476,7 @@
 		return ret;
 
 	/* wait, until all devices are ready for the free operation */
-	wait_event(card->shutdown_sleep, card->files == NULL);
+	wait_event(card->shutdown_sleep, list_empty(&card->files_list));
 	snd_card_do_free(card);
 	return 0;
 }
@@ -809,15 +823,13 @@
 		return -ENOMEM;
 	mfile->file = file;
 	mfile->disconnected_f_op = NULL;
-	mfile->next = NULL;
 	spin_lock(&card->files_lock);
 	if (card->shutdown) {
 		spin_unlock(&card->files_lock);
 		kfree(mfile);
 		return -ENODEV;
 	}
-	mfile->next = card->files;
-	card->files = mfile;
+	list_add(&mfile->list, &card->files_list);
 	spin_unlock(&card->files_lock);
 	return 0;
 }
@@ -839,29 +851,20 @@
  */
 int snd_card_file_remove(struct snd_card *card, struct file *file)
 {
-	struct snd_monitor_file *mfile, *pfile = NULL;
+	struct snd_monitor_file *mfile, *found = NULL;
 	int last_close = 0;
 
 	spin_lock(&card->files_lock);
-	mfile = card->files;
-	while (mfile) {
+	list_for_each_entry(mfile, &card->files_list, list) {
 		if (mfile->file == file) {
-			if (pfile)
-				pfile->next = mfile->next;
-			else
-				card->files = mfile->next;
+			list_del(&mfile->list);
+			if (mfile->disconnected_f_op)
+				fops_put(mfile->disconnected_f_op);
+			found = mfile;
 			break;
 		}
-		pfile = mfile;
-		mfile = mfile->next;
 	}
-	if (mfile && mfile->disconnected_f_op) {
-		fops_put(mfile->disconnected_f_op);
-		spin_lock(&shutdown_lock);
-		list_del(&mfile->shutdown_list);
-		spin_unlock(&shutdown_lock);
-	}
-	if (card->files == NULL)
+	if (list_empty(&card->files_list))
 		last_close = 1;
 	spin_unlock(&card->files_lock);
 	if (last_close) {
@@ -869,11 +872,11 @@
 		if (card->free_on_last_close)
 			snd_card_do_free(card);
 	}
-	if (!mfile) {
+	if (!found) {
 		snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
 		return -ENOENT;
 	}
-	kfree(mfile);
+	kfree(found);
 	return 0;
 }
 
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 077a852..c8254c6 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -23,6 +23,14 @@
 #include <sound/jack.h>
 #include <sound/core.h>
 
+static int jack_types[] = {
+	SW_HEADPHONE_INSERT,
+	SW_MICROPHONE_INSERT,
+	SW_LINEOUT_INSERT,
+	SW_JACK_PHYSICAL_INSERT,
+	SW_VIDEOOUT_INSERT,
+};
+
 static int snd_jack_dev_free(struct snd_device *device)
 {
 	struct snd_jack *jack = device->device_data;
@@ -79,6 +87,7 @@
 {
 	struct snd_jack *jack;
 	int err;
+	int i;
 	static struct snd_device_ops ops = {
 		.dev_free = snd_jack_dev_free,
 		.dev_register = snd_jack_dev_register,
@@ -100,18 +109,10 @@
 
 	jack->type = type;
 
-	if (type & SND_JACK_HEADPHONE)
-		input_set_capability(jack->input_dev, EV_SW,
-				     SW_HEADPHONE_INSERT);
-	if (type & SND_JACK_LINEOUT)
-		input_set_capability(jack->input_dev, EV_SW,
-				     SW_LINEOUT_INSERT);
-	if (type & SND_JACK_MICROPHONE)
-		input_set_capability(jack->input_dev, EV_SW,
-				     SW_MICROPHONE_INSERT);
-	if (type & SND_JACK_MECHANICAL)
-		input_set_capability(jack->input_dev, EV_SW,
-				     SW_JACK_PHYSICAL_INSERT);
+	for (i = 0; i < ARRAY_SIZE(jack_types); i++)
+		if (type & (1 << i))
+			input_set_capability(jack->input_dev, EV_SW,
+					     jack_types[i]);
 
 	err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
 	if (err < 0)
@@ -154,21 +155,17 @@
  */
 void snd_jack_report(struct snd_jack *jack, int status)
 {
+	int i;
+
 	if (!jack)
 		return;
 
-	if (jack->type & SND_JACK_HEADPHONE)
-		input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT,
-				    status & SND_JACK_HEADPHONE);
-	if (jack->type & SND_JACK_LINEOUT)
-		input_report_switch(jack->input_dev, SW_LINEOUT_INSERT,
-				    status & SND_JACK_LINEOUT);
-	if (jack->type & SND_JACK_MICROPHONE)
-		input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT,
-				    status & SND_JACK_MICROPHONE);
-	if (jack->type & SND_JACK_MECHANICAL)
-		input_report_switch(jack->input_dev, SW_JACK_PHYSICAL_INSERT,
-				    status & SND_JACK_MECHANICAL);
+	for (i = 0; i < ARRAY_SIZE(jack_types); i++) {
+		int testbit = 1 << i;
+		if (jack->type & testbit)
+			input_report_switch(jack->input_dev, jack_types[i],
+					    status & testbit);
+	}
 
 	input_sync(jack->input_dev);
 }
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 38524f6..a9710e0 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -95,12 +95,14 @@
 {
 	const struct snd_pci_quirk *q;
 
-	for (q = list; q->subvendor; q++)
-		if (q->subvendor == pci->subsystem_vendor &&
-		    (!q->subdevice || q->subdevice == pci->subsystem_device))
+	for (q = list; q->subvendor; q++) {
+		if (q->subvendor != pci->subsystem_vendor)
+			continue;
+		if (!q->subdevice ||
+		    (pci->subsystem_device & q->subdevice_mask) == q->subdevice)
 			return q;
+	}
 	return NULL;
 }
-
 EXPORT_SYMBOL(snd_pci_quirk_lookup);
 #endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 4690b8b..e570649 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -692,6 +692,9 @@
 		snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
 		if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME)
 			snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right);
+	} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME) {
+		snd_mixer_oss_put_volume1_vol(fmixer, pslot,
+			slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right);
 	} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) {
 		snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right);
 	} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) {
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 0a1798e..2864cef 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1160,9 +1160,11 @@
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 #ifdef OSS_DEBUG
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
-				printk("pcm_oss: write: recovering from XRUN\n");
+				printk(KERN_DEBUG "pcm_oss: write: "
+				       "recovering from XRUN\n");
 			else
-				printk("pcm_oss: write: recovering from SUSPEND\n");
+				printk(KERN_DEBUG "pcm_oss: write: "
+				       "recovering from SUSPEND\n");
 #endif
 			ret = snd_pcm_oss_prepare(substream);
 			if (ret < 0)
@@ -1196,9 +1198,11 @@
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 #ifdef OSS_DEBUG
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
-				printk("pcm_oss: read: recovering from XRUN\n");
+				printk(KERN_DEBUG "pcm_oss: read: "
+				       "recovering from XRUN\n");
 			else
-				printk("pcm_oss: read: recovering from SUSPEND\n");
+				printk(KERN_DEBUG "pcm_oss: read: "
+				       "recovering from SUSPEND\n");
 #endif
 			ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
 			if (ret < 0)
@@ -1242,9 +1246,11 @@
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 #ifdef OSS_DEBUG
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
-				printk("pcm_oss: writev: recovering from XRUN\n");
+				printk(KERN_DEBUG "pcm_oss: writev: "
+				       "recovering from XRUN\n");
 			else
-				printk("pcm_oss: writev: recovering from SUSPEND\n");
+				printk(KERN_DEBUG "pcm_oss: writev: "
+				       "recovering from SUSPEND\n");
 #endif
 			ret = snd_pcm_oss_prepare(substream);
 			if (ret < 0)
@@ -1278,9 +1284,11 @@
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 #ifdef OSS_DEBUG
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
-				printk("pcm_oss: readv: recovering from XRUN\n");
+				printk(KERN_DEBUG "pcm_oss: readv: "
+				       "recovering from XRUN\n");
 			else
-				printk("pcm_oss: readv: recovering from SUSPEND\n");
+				printk(KERN_DEBUG "pcm_oss: readv: "
+				       "recovering from SUSPEND\n");
 #endif
 			ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
 			if (ret < 0)
@@ -1533,7 +1541,7 @@
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(&runtime->sleep, &wait);
 #ifdef OSS_DEBUG
-	printk("sync1: size = %li\n", size);
+	printk(KERN_DEBUG "sync1: size = %li\n", size);
 #endif
 	while (1) {
 		result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);
@@ -1590,7 +1598,7 @@
 		mutex_lock(&runtime->oss.params_lock);
 		if (runtime->oss.buffer_used > 0) {
 #ifdef OSS_DEBUG
-			printk("sync: buffer_used\n");
+			printk(KERN_DEBUG "sync: buffer_used\n");
 #endif
 			size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;
 			snd_pcm_format_set_silence(format,
@@ -1603,7 +1611,7 @@
 			}
 		} else if (runtime->oss.period_ptr > 0) {
 #ifdef OSS_DEBUG
-			printk("sync: period_ptr\n");
+			printk(KERN_DEBUG "sync: period_ptr\n");
 #endif
 			size = runtime->oss.period_bytes - runtime->oss.period_ptr;
 			snd_pcm_format_set_silence(format,
@@ -1952,7 +1960,7 @@
 	int err, cmd;
 
 #ifdef OSS_DEBUG
-	printk("pcm_oss: trigger = 0x%x\n", trigger);
+	printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger);
 #endif
 	
 	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
@@ -2170,7 +2178,9 @@
 	}
 
 #ifdef OSS_DEBUG
-	printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize);
+	printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, "
+	       "fragstotal = %i, fragsize = %i\n",
+	       info.bytes, info.fragments, info.fragstotal, info.fragsize);
 #endif
 	if (copy_to_user(_info, &info, sizeof(info)))
 		return -EFAULT;
@@ -2473,7 +2483,7 @@
 	if (((cmd >> 8) & 0xff) != 'P')
 		return -EINVAL;
 #ifdef OSS_DEBUG
-	printk("pcm_oss: ioctl = 0x%x\n", cmd);
+	printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd);
 #endif
 	switch (cmd) {
 	case SNDCTL_DSP_RESET:
@@ -2627,7 +2637,8 @@
 #else
 	{
 		ssize_t res = snd_pcm_oss_read1(substream, buf, count);
-		printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res);
+		printk(KERN_DEBUG "pcm_oss: read %li bytes "
+		       "(returned %li bytes)\n", (long)count, (long)res);
 		return res;
 	}
 #endif
@@ -2646,7 +2657,8 @@
 	substream->f_flags = file->f_flags & O_NONBLOCK;
 	result = snd_pcm_oss_write1(substream, buf, count);
 #ifdef OSS_DEBUG
-	printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
+	printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n",
+	       (long)count, (long)result);
 #endif
 	return result;
 }
@@ -2720,7 +2732,7 @@
 	int err;
 
 #ifdef OSS_DEBUG
-	printk("pcm_oss: mmap begin\n");
+	printk(KERN_DEBUG "pcm_oss: mmap begin\n");
 #endif
 	pcm_oss_file = file->private_data;
 	switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
@@ -2770,7 +2782,8 @@
 	runtime->silence_threshold = 0;
 	runtime->silence_size = 0;
 #ifdef OSS_DEBUG
-	printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes);
+	printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n",
+	       runtime->oss.mmap_bytes);
 #endif
 	/* In mmap mode we never stop */
 	runtime->stop_threshold = runtime->boundary;
@@ -2872,7 +2885,7 @@
 			setup = kmalloc(sizeof(*setup), GFP_KERNEL);
 			if (! setup) {
 				buffer->error = -ENOMEM;
-				mutex_lock(&pstr->oss.setup_mutex);
+				mutex_unlock(&pstr->oss.setup_mutex);
 				return;
 			}
 			if (pstr->oss.setup_list == NULL)
@@ -2886,7 +2899,7 @@
 			if (! template.task_name) {
 				kfree(setup);
 				buffer->error = -ENOMEM;
-				mutex_lock(&pstr->oss.setup_mutex);
+				mutex_unlock(&pstr->oss.setup_mutex);
 				return;
 			}
 		}
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index ca2f4c3..b9afab6 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -176,9 +176,9 @@
 #endif
 
 #ifdef PLUGIN_DEBUG
-#define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args)
+#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args)
 #else
-#define pdprintf( fmt, args... ) 
+#define pdprintf(fmt, args...)
 #endif
 
 #endif				/* __PCM_PLUGIN_H */
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 192a433..145931a 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -667,7 +667,6 @@
 		spin_lock_init(&substream->self_group.lock);
 		INIT_LIST_HEAD(&substream->self_group.substreams);
 		list_add_tail(&substream->link_list, &substream->self_group.substreams);
-		spin_lock_init(&substream->timer_lock);
 		atomic_set(&substream->mmap_count, 0);
 		prev = substream;
 	}
@@ -692,7 +691,7 @@
  *
  * Returns zero if successful, or a negative error code on failure.
  */
-int snd_pcm_new(struct snd_card *card, char *id, int device,
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
 		int playback_count, int capture_count,
 	        struct snd_pcm ** rpcm)
 {
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 9216910..fbb2e39 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -125,23 +125,32 @@
 	}
 }
 
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
+#define xrun_debug(substream)	((substream)->pstr->xrun_debug)
+#else
+#define xrun_debug(substream)	0
+#endif
+
+#define dump_stack_on_xrun(substream) do {	\
+		if (xrun_debug(substream) > 1)	\
+			dump_stack();		\
+	} while (0)
+
 static void xrun(struct snd_pcm_substream *substream)
 {
 	snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-	if (substream->pstr->xrun_debug) {
+	if (xrun_debug(substream)) {
 		snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
 			   substream->pcm->card->number,
 			   substream->pcm->device,
 			   substream->stream ? 'c' : 'p');
-		if (substream->pstr->xrun_debug > 1)
-			dump_stack();
+		dump_stack_on_xrun(substream);
 	}
-#endif
 }
 
-static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
-							  struct snd_pcm_runtime *runtime)
+static snd_pcm_uframes_t
+snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
+			  struct snd_pcm_runtime *runtime)
 {
 	snd_pcm_uframes_t pos;
 
@@ -150,17 +159,21 @@
 	pos = substream->ops->pointer(substream);
 	if (pos == SNDRV_PCM_POS_XRUN)
 		return pos; /* XRUN */
-#ifdef CONFIG_SND_DEBUG
 	if (pos >= runtime->buffer_size) {
-		snd_printk(KERN_ERR  "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
+		if (printk_ratelimit()) {
+			snd_printd(KERN_ERR  "BUG: stream = %i, pos = 0x%lx, "
+				   "buffer size = 0x%lx, period size = 0x%lx\n",
+				   substream->stream, pos, runtime->buffer_size,
+				   runtime->period_size);
+		}
+		pos = 0;
 	}
-#endif
 	pos -= pos % runtime->min_align;
 	return pos;
 }
 
-static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
-					     struct snd_pcm_runtime *runtime)
+static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
+				      struct snd_pcm_runtime *runtime)
 {
 	snd_pcm_uframes_t avail;
 
@@ -182,11 +195,21 @@
 	return 0;
 }
 
-static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
+#define hw_ptr_error(substream, fmt, args...)				\
+	do {								\
+		if (xrun_debug(substream)) {				\
+			if (printk_ratelimit()) {			\
+				snd_printd("PCM: " fmt, ##args);	\
+			}						\
+			dump_stack_on_xrun(substream);			\
+		}							\
+	} while (0)
+
+static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	snd_pcm_uframes_t pos;
-	snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt;
+	snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base;
 	snd_pcm_sframes_t delta;
 
 	pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
@@ -194,36 +217,53 @@
 		xrun(substream);
 		return -EPIPE;
 	}
-	if (runtime->period_size == runtime->buffer_size)
-		goto __next_buf;
-	new_hw_ptr = runtime->hw_ptr_base + pos;
+	hw_base = runtime->hw_ptr_base;
+	new_hw_ptr = hw_base + pos;
 	hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
-
-	delta = hw_ptr_interrupt - new_hw_ptr;
-	if (delta > 0) {
-		if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-			if (runtime->periods > 1 && substream->pstr->xrun_debug) {
-				snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
-				if (substream->pstr->xrun_debug > 1)
-					dump_stack();
-			}
-#endif
-			return 0;
-		}
-	      __next_buf:
-		runtime->hw_ptr_base += runtime->buffer_size;
-		if (runtime->hw_ptr_base == runtime->boundary)
-			runtime->hw_ptr_base = 0;
-		new_hw_ptr = runtime->hw_ptr_base + pos;
+	delta = new_hw_ptr - hw_ptr_interrupt;
+	if (hw_ptr_interrupt >= runtime->boundary) {
+		hw_ptr_interrupt -= runtime->boundary;
+		if (hw_base < runtime->boundary / 2)
+			/* hw_base was already lapped; recalc delta */
+			delta = new_hw_ptr - hw_ptr_interrupt;
 	}
-
+	if (delta < 0) {
+		delta += runtime->buffer_size;
+		if (delta < 0) {
+			hw_ptr_error(substream, 
+				     "Unexpected hw_pointer value "
+				     "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
+				     substream->stream, (long)pos,
+				     (long)hw_ptr_interrupt);
+			/* rebase to interrupt position */
+			hw_base = new_hw_ptr = hw_ptr_interrupt;
+			/* align hw_base to buffer_size */
+			hw_base -= hw_base % runtime->buffer_size;
+			delta = 0;
+		} else {
+			hw_base += runtime->buffer_size;
+			if (hw_base >= runtime->boundary)
+				hw_base = 0;
+			new_hw_ptr = hw_base + pos;
+		}
+	}
+	if (delta > runtime->period_size) {
+		hw_ptr_error(substream,
+			     "Lost interrupts? "
+			     "(stream=%i, delta=%ld, intr_ptr=%ld)\n",
+			     substream->stream, (long)delta,
+			     (long)hw_ptr_interrupt);
+		/* rebase hw_ptr_interrupt */
+		hw_ptr_interrupt =
+			new_hw_ptr - new_hw_ptr % runtime->period_size;
+	}
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	    runtime->silence_size > 0)
 		snd_pcm_playback_silence(substream, new_hw_ptr);
 
+	runtime->hw_ptr_base = hw_base;
 	runtime->status->hw_ptr = new_hw_ptr;
-	runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size;
+	runtime->hw_ptr_interrupt = hw_ptr_interrupt;
 
 	return snd_pcm_update_hw_ptr_post(substream, runtime);
 }
@@ -233,7 +273,7 @@
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	snd_pcm_uframes_t pos;
-	snd_pcm_uframes_t old_hw_ptr, new_hw_ptr;
+	snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
 	snd_pcm_sframes_t delta;
 
 	old_hw_ptr = runtime->status->hw_ptr;
@@ -242,29 +282,38 @@
 		xrun(substream);
 		return -EPIPE;
 	}
-	new_hw_ptr = runtime->hw_ptr_base + pos;
+	hw_base = runtime->hw_ptr_base;
+	new_hw_ptr = hw_base + pos;
 
-	delta = old_hw_ptr - new_hw_ptr;
-	if (delta > 0) {
-		if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-			if (runtime->periods > 2 && substream->pstr->xrun_debug) {
-				snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
-				if (substream->pstr->xrun_debug > 1)
-					dump_stack();
-			}
-#endif
+	delta = new_hw_ptr - old_hw_ptr;
+	if (delta < 0) {
+		delta += runtime->buffer_size;
+		if (delta < 0) {
+			hw_ptr_error(substream, 
+				     "Unexpected hw_pointer value [2] "
+				     "(stream=%i, pos=%ld, old_ptr=%ld)\n",
+				     substream->stream, (long)pos,
+				     (long)old_hw_ptr);
 			return 0;
 		}
-		runtime->hw_ptr_base += runtime->buffer_size;
-		if (runtime->hw_ptr_base == runtime->boundary)
-			runtime->hw_ptr_base = 0;
-		new_hw_ptr = runtime->hw_ptr_base + pos;
+		hw_base += runtime->buffer_size;
+		if (hw_base >= runtime->boundary)
+			hw_base = 0;
+		new_hw_ptr = hw_base + pos;
+	}
+	if (delta > runtime->period_size && runtime->periods > 1) {
+		hw_ptr_error(substream,
+			     "hw_ptr skipping! "
+			     "(pos=%ld, delta=%ld, period=%ld)\n",
+			     (long)pos, (long)delta,
+			     (long)runtime->period_size);
+		return 0;
 	}
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	    runtime->silence_size > 0)
 		snd_pcm_playback_silence(substream, new_hw_ptr);
 
+	runtime->hw_ptr_base = hw_base;
 	runtime->status->hw_ptr = new_hw_ptr;
 
 	return snd_pcm_update_hw_ptr_post(substream, runtime);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a789efc..d9b8f53 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -186,7 +186,7 @@
 		if (!(params->rmask & (1 << k)))
 			continue;
 #ifdef RULES_DEBUG
-		printk("%s = ", snd_pcm_hw_param_names[k]);
+		printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
 		printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
 #endif
 		changed = snd_mask_refine(m, constrs_mask(constrs, k));
@@ -206,7 +206,7 @@
 		if (!(params->rmask & (1 << k)))
 			continue;
 #ifdef RULES_DEBUG
-		printk("%s = ", snd_pcm_hw_param_names[k]);
+		printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
 		if (i->empty)
 			printk("empty");
 		else
@@ -251,7 +251,7 @@
 			if (!doit)
 				continue;
 #ifdef RULES_DEBUG
-			printk("Rule %d [%p]: ", k, r->func);
+			printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func);
 			if (r->var >= 0) {
 				printk("%s = ", snd_pcm_hw_param_names[r->var]);
 				if (hw_is_mask(r->var)) {
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index 2c89c04..ca8068b 100644
--- a/sound/core/pcm_timer.c
+++ b/sound/core/pcm_timer.c
@@ -85,25 +85,19 @@
 
 static int snd_pcm_timer_start(struct snd_timer * timer)
 {
-	unsigned long flags;
 	struct snd_pcm_substream *substream;
 	
 	substream = snd_timer_chip(timer);
-	spin_lock_irqsave(&substream->timer_lock, flags);
 	substream->timer_running = 1;
-	spin_unlock_irqrestore(&substream->timer_lock, flags);
 	return 0;
 }
 
 static int snd_pcm_timer_stop(struct snd_timer * timer)
 {
-	unsigned long flags;
 	struct snd_pcm_substream *substream;
 	
 	substream = snd_timer_chip(timer);
-	spin_lock_irqsave(&substream->timer_lock, flags);
 	substream->timer_running = 0;
-	spin_unlock_irqrestore(&substream->timer_lock, flags);
 	return 0;
 }
 
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 002777b..473247c 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -224,156 +224,143 @@
 	return 0;
 }
 
+/* look for an available substream for the given stream direction;
+ * if a specific subdevice is given, try to assign it
+ */
+static int assign_substream(struct snd_rawmidi *rmidi, int subdevice,
+			    int stream, int mode,
+			    struct snd_rawmidi_substream **sub_ret)
+{
+	struct snd_rawmidi_substream *substream;
+	struct snd_rawmidi_str *s = &rmidi->streams[stream];
+	static unsigned int info_flags[2] = {
+		[SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT,
+		[SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT,
+	};
+
+	if (!(rmidi->info_flags & info_flags[stream]))
+		return -ENXIO;
+	if (subdevice >= 0 && subdevice >= s->substream_count)
+		return -ENODEV;
+	if (s->substream_opened >= s->substream_count)
+		return -EAGAIN;
+
+	list_for_each_entry(substream, &s->substreams, list) {
+		if (substream->opened) {
+			if (stream == SNDRV_RAWMIDI_STREAM_INPUT ||
+			    !(mode & SNDRV_RAWMIDI_LFLG_APPEND))
+				continue;
+		}
+		if (subdevice < 0 || subdevice == substream->number) {
+			*sub_ret = substream;
+			return 0;
+		}
+	}
+	return -EAGAIN;
+}
+
+/* open and do ref-counting for the given substream */
+static int open_substream(struct snd_rawmidi *rmidi,
+			  struct snd_rawmidi_substream *substream,
+			  int mode)
+{
+	int err;
+
+	err = snd_rawmidi_runtime_create(substream);
+	if (err < 0)
+		return err;
+	err = substream->ops->open(substream);
+	if (err < 0)
+		return err;
+	substream->opened = 1;
+	if (substream->use_count++ == 0)
+		substream->active_sensing = 1;
+	if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
+		substream->append = 1;
+	rmidi->streams[substream->stream].substream_opened++;
+	return 0;
+}
+
+static void close_substream(struct snd_rawmidi *rmidi,
+			    struct snd_rawmidi_substream *substream,
+			    int cleanup);
+
+static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
+			     struct snd_rawmidi_file *rfile)
+{
+	struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL;
+	int err;
+
+	rfile->input = rfile->output = NULL;
+	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
+		err = assign_substream(rmidi, subdevice,
+				       SNDRV_RAWMIDI_STREAM_INPUT,
+				       mode, &sinput);
+		if (err < 0)
+			goto __error;
+	}
+	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
+		err = assign_substream(rmidi, subdevice,
+				       SNDRV_RAWMIDI_STREAM_OUTPUT,
+				       mode, &soutput);
+		if (err < 0)
+			goto __error;
+	}
+
+	if (sinput) {
+		err = open_substream(rmidi, sinput, mode);
+		if (err < 0)
+			goto __error;
+	}
+	if (soutput) {
+		err = open_substream(rmidi, soutput, mode);
+		if (err < 0) {
+			if (sinput)
+				close_substream(rmidi, sinput, 0);
+			goto __error;
+		}
+	}
+
+	rfile->rmidi = rmidi;
+	rfile->input = sinput;
+	rfile->output = soutput;
+	return 0;
+
+      __error:
+	if (sinput && sinput->runtime)
+		snd_rawmidi_runtime_free(sinput);
+	if (soutput && soutput->runtime)
+		snd_rawmidi_runtime_free(soutput);
+	return err;
+}
+
+/* called from sound/core/seq/seq_midi.c */
 int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
 			    int mode, struct snd_rawmidi_file * rfile)
 {
 	struct snd_rawmidi *rmidi;
-	struct list_head *list1, *list2;
-	struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL;
-	struct snd_rawmidi_runtime *input = NULL, *output = NULL;
 	int err;
 
-	if (rfile)
-		rfile->input = rfile->output = NULL;
+	if (snd_BUG_ON(!rfile))
+		return -EINVAL;
+
 	mutex_lock(&register_mutex);
 	rmidi = snd_rawmidi_search(card, device);
-	mutex_unlock(&register_mutex);
 	if (rmidi == NULL) {
-		err = -ENODEV;
-		goto __error1;
+		mutex_unlock(&register_mutex);
+		return -ENODEV;
 	}
 	if (!try_module_get(rmidi->card->module)) {
-		err = -EFAULT;
-		goto __error1;
+		mutex_unlock(&register_mutex);
+		return -ENXIO;
 	}
-	if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
-		mutex_lock(&rmidi->open_mutex);
-	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
-		if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT)) {
-			err = -ENXIO;
-			goto __error;
-		}
-		if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) {
-			err = -ENODEV;
-			goto __error;
-		}
-		if (rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened >=
-		    rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) {
-			err = -EAGAIN;
-			goto __error;
-		}
-	}
-	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
-		if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT)) {
-			err = -ENXIO;
-			goto __error;
-		}
-		if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) {
-			err = -ENODEV;
-			goto __error;
-		}
-		if (rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened >=
-		    rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) {
-			err = -EAGAIN;
-			goto __error;
-		}
-	}
-	list1 = rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams.next;
-	while (1) {
-		if (list1 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
-			sinput = NULL;
-			if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
-				err = -EAGAIN;
-				goto __error;
-			}
-			break;
-		}
-		sinput = list_entry(list1, struct snd_rawmidi_substream, list);
-		if ((mode & SNDRV_RAWMIDI_LFLG_INPUT) && sinput->opened)
-			goto __nexti;
-		if (subdevice < 0 || (subdevice >= 0 && subdevice == sinput->number))
-			break;
-	      __nexti:
-		list1 = list1->next;
-	}
-	list2 = rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams.next;
-	while (1) {
-		if (list2 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
-			soutput = NULL;
-			if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
-				err = -EAGAIN;
-				goto __error;
-			}
-			break;
-		}
-		soutput = list_entry(list2, struct snd_rawmidi_substream, list);
-		if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
-			if (mode & SNDRV_RAWMIDI_LFLG_APPEND) {
-				if (soutput->opened && !soutput->append)
-					goto __nexto;
-			} else {
-				if (soutput->opened)
-					goto __nexto;
-			}
-		}
-		if (subdevice < 0 || (subdevice >= 0 && subdevice == soutput->number))
-			break;
-	      __nexto:
-		list2 = list2->next;
-	}
-	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
-		if ((err = snd_rawmidi_runtime_create(sinput)) < 0)
-			goto __error;
-		input = sinput->runtime;
-		if ((err = sinput->ops->open(sinput)) < 0)
-			goto __error;
-		sinput->opened = 1;
-		rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++;
-	} else {
-		sinput = NULL;
-	}
-	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
-		if (soutput->opened)
-			goto __skip_output;
-		if ((err = snd_rawmidi_runtime_create(soutput)) < 0) {
-			if (mode & SNDRV_RAWMIDI_LFLG_INPUT)
-				sinput->ops->close(sinput);
-			goto __error;
-		}
-		output = soutput->runtime;
-		if ((err = soutput->ops->open(soutput)) < 0) {
-			if (mode & SNDRV_RAWMIDI_LFLG_INPUT)
-				sinput->ops->close(sinput);
-			goto __error;
-		}
-	      __skip_output:
-		soutput->opened = 1;
-		if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
-			soutput->append = 1;
-	      	if (soutput->use_count++ == 0)
-			soutput->active_sensing = 1;
-		rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened++;
-	} else {
-		soutput = NULL;
-	}
-	if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
-		mutex_unlock(&rmidi->open_mutex);
-	if (rfile) {
-		rfile->rmidi = rmidi;
-		rfile->input = sinput;
-		rfile->output = soutput;
-	}
-	return 0;
+	mutex_unlock(&register_mutex);
 
-      __error:
-	if (input != NULL)
-		snd_rawmidi_runtime_free(sinput);
-	if (output != NULL)
-		snd_rawmidi_runtime_free(soutput);
-	module_put(rmidi->card->module);
-	if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
-		mutex_unlock(&rmidi->open_mutex);
-      __error1:
+	mutex_lock(&rmidi->open_mutex);
+	err = rawmidi_open_priv(rmidi, subdevice, mode, rfile);
+	mutex_unlock(&rmidi->open_mutex);
+	if (err < 0)
+		module_put(rmidi->card->module);
 	return err;
 }
 
@@ -385,10 +372,13 @@
 	unsigned short fflags;
 	int err;
 	struct snd_rawmidi *rmidi;
-	struct snd_rawmidi_file *rawmidi_file;
+	struct snd_rawmidi_file *rawmidi_file = NULL;
 	wait_queue_t wait;
 	struct snd_ctl_file *kctl;
 
+	if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) 
+		return -EINVAL;		/* invalid combination */
+
 	if (maj == snd_major) {
 		rmidi = snd_lookup_minor_data(iminor(inode),
 					      SNDRV_DEVICE_TYPE_RAWMIDI);
@@ -402,24 +392,25 @@
 
 	if (rmidi == NULL)
 		return -ENODEV;
-	if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) 
-		return -EINVAL;		/* invalid combination */
+
+	if (!try_module_get(rmidi->card->module))
+		return -ENXIO;
+
+	mutex_lock(&rmidi->open_mutex);
 	card = rmidi->card;
 	err = snd_card_file_add(card, file);
 	if (err < 0)
-		return -ENODEV;
+		goto __error_card;
 	fflags = snd_rawmidi_file_flags(file);
 	if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */
 		fflags |= SNDRV_RAWMIDI_LFLG_APPEND;
-	fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK;
 	rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL);
 	if (rawmidi_file == NULL) {
-		snd_card_file_remove(card, file);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto __error;
 	}
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(&rmidi->open_wait, &wait);
-	mutex_lock(&rmidi->open_mutex);
 	while (1) {
 		subdevice = -1;
 		read_lock(&card->ctl_files_rwlock);
@@ -431,8 +422,7 @@
 			}
 		}
 		read_unlock(&card->ctl_files_rwlock);
-		err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device,
-					      subdevice, fflags, rawmidi_file);
+		err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file);
 		if (err >= 0)
 			break;
 		if (err == -EAGAIN) {
@@ -451,67 +441,89 @@
 			break;
 		}
 	}
+	remove_wait_queue(&rmidi->open_wait, &wait);
+	if (err < 0) {
+		kfree(rawmidi_file);
+		goto __error;
+	}
 #ifdef CONFIG_SND_OSSEMUL
 	if (rawmidi_file->input && rawmidi_file->input->runtime)
 		rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR);
 	if (rawmidi_file->output && rawmidi_file->output->runtime)
 		rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR);
 #endif
-	remove_wait_queue(&rmidi->open_wait, &wait);
-	if (err >= 0) {
-		file->private_data = rawmidi_file;
-	} else {
-		snd_card_file_remove(card, file);
-		kfree(rawmidi_file);
-	}
+	file->private_data = rawmidi_file;
 	mutex_unlock(&rmidi->open_mutex);
+	return 0;
+
+ __error:
+	snd_card_file_remove(card, file);
+ __error_card:
+	mutex_unlock(&rmidi->open_mutex);
+	module_put(rmidi->card->module);
 	return err;
 }
 
-int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile)
+static void close_substream(struct snd_rawmidi *rmidi,
+			    struct snd_rawmidi_substream *substream,
+			    int cleanup)
 {
-	struct snd_rawmidi *rmidi;
-	struct snd_rawmidi_substream *substream;
-	struct snd_rawmidi_runtime *runtime;
+	rmidi->streams[substream->stream].substream_opened--;
+	if (--substream->use_count)
+		return;
 
-	if (snd_BUG_ON(!rfile))
-		return -ENXIO;
-	rmidi = rfile->rmidi;
-	mutex_lock(&rmidi->open_mutex);
-	if (rfile->input != NULL) {
-		substream = rfile->input;
-		rfile->input = NULL;
-		runtime = substream->runtime;
-		snd_rawmidi_input_trigger(substream, 0);
-		substream->ops->close(substream);
-		if (runtime->private_free != NULL)
-			runtime->private_free(substream);
-		snd_rawmidi_runtime_free(substream);
-		substream->opened = 0;
-		rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--;
-	}
-	if (rfile->output != NULL) {
-		substream = rfile->output;
-		rfile->output = NULL;
-		if (--substream->use_count == 0) {
-			runtime = substream->runtime;
+	if (cleanup) {
+		if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
+			snd_rawmidi_input_trigger(substream, 0);
+		else {
 			if (substream->active_sensing) {
 				unsigned char buf = 0xfe;
-				/* sending single active sensing message to shut the device up */
+				/* sending single active sensing message
+				 * to shut the device up
+				 */
 				snd_rawmidi_kernel_write(substream, &buf, 1);
 			}
 			if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS)
 				snd_rawmidi_output_trigger(substream, 0);
-			substream->ops->close(substream);
-			if (runtime->private_free != NULL)
-				runtime->private_free(substream);
-			snd_rawmidi_runtime_free(substream);
-			substream->opened = 0;
-			substream->append = 0;
 		}
-		rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--;
 	}
+	substream->ops->close(substream);
+	if (substream->runtime->private_free)
+		substream->runtime->private_free(substream);
+	snd_rawmidi_runtime_free(substream);
+	substream->opened = 0;
+	substream->append = 0;
+}
+
+static void rawmidi_release_priv(struct snd_rawmidi_file *rfile)
+{
+	struct snd_rawmidi *rmidi;
+
+	rmidi = rfile->rmidi;
+	mutex_lock(&rmidi->open_mutex);
+	if (rfile->input) {
+		close_substream(rmidi, rfile->input, 1);
+		rfile->input = NULL;
+	}
+	if (rfile->output) {
+		close_substream(rmidi, rfile->output, 1);
+		rfile->output = NULL;
+	}
+	rfile->rmidi = NULL;
 	mutex_unlock(&rmidi->open_mutex);
+	wake_up(&rmidi->open_wait);
+}
+
+/* called from sound/core/seq/seq_midi.c */
+int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile)
+{
+	struct snd_rawmidi *rmidi;
+
+	if (snd_BUG_ON(!rfile))
+		return -ENXIO;
+	
+	rmidi = rfile->rmidi;
+	rawmidi_release_priv(rfile);
 	module_put(rmidi->card->module);
 	return 0;
 }
@@ -520,15 +532,14 @@
 {
 	struct snd_rawmidi_file *rfile;
 	struct snd_rawmidi *rmidi;
-	int err;
 
 	rfile = file->private_data;
-	err = snd_rawmidi_kernel_release(rfile);
 	rmidi = rfile->rmidi;
-	wake_up(&rmidi->open_wait);
+	rawmidi_release_priv(rfile);
 	kfree(rfile);
 	snd_card_file_remove(rmidi->card, file);
-	return err;
+	module_put(rmidi->card->module);
+	return 0;
 }
 
 static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,
diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h
index bf8d2b4..c0154a9 100644
--- a/sound/core/seq/oss/seq_oss_device.h
+++ b/sound/core/seq/oss/seq_oss_device.h
@@ -181,7 +181,7 @@
 /* for debug */
 #ifdef SNDRV_SEQ_OSS_DEBUG
 extern int seq_oss_debug;
-#define debug_printk(x)	do { if (seq_oss_debug > 0) snd_printk x; } while (0)
+#define debug_printk(x)	do { if (seq_oss_debug > 0) snd_printd x; } while (0)
 #else
 #define debug_printk(x)	/**/
 #endif
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index 0101a8b..29896ab 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -321,7 +321,8 @@
 			freeprev = cell;
 		} else {
 #if 0
-			printk("type = %i, source = %i, dest = %i, client = %i\n",
+			printk(KERN_DEBUG "type = %i, source = %i, dest = %i, "
+			       "client = %i\n",
 				cell->event.type,
 				cell->event.source.client,
 				cell->event.dest.client,
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index d4564ed..4e7ec2b 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -38,6 +38,10 @@
 	if (! sgbuf)
 		return -EINVAL;
 
+	if (dmab->area)
+		vunmap(dmab->area);
+	dmab->area = NULL;
+
 	tmpb.dev.type = SNDRV_DMA_TYPE_DEV;
 	tmpb.dev.dev = sgbuf->dev;
 	for (i = 0; i < sgbuf->pages; i++) {
@@ -48,9 +52,6 @@
 		tmpb.bytes = (sgbuf->table[i].addr & ~PAGE_MASK) << PAGE_SHIFT;
 		snd_dma_free_pages(&tmpb);
 	}
-	if (dmab->area)
-		vunmap(dmab->area);
-	dmab->area = NULL;
 
 	kfree(sgbuf->table);
 	kfree(sgbuf->page_table);
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 4cc57f9..257624b 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -50,18 +50,38 @@
 	struct link_master *master;
 	struct link_ctl_info info;
 	int vals[2];		/* current values */
+	unsigned int flags;
 	struct snd_kcontrol slave; /* the copy of original control entry */
 };
 
+static int slave_update(struct link_slave *slave)
+{
+	struct snd_ctl_elem_value *uctl;
+	int err, ch;
+
+	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;
+}
+
 /* 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;
+	int err;
 
-	if (slave->info.count)
-		return 0; /* already initialized */
+	if (slave->info.count) {
+		/* already initialized */
+		if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE)
+			return slave_update(slave);
+		return 0;
+	}
 
 	uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
 	if (!uinfo)
@@ -85,15 +105,7 @@
 	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;
+	return slave_update(slave);
 }
 
 /* initialize master volume */
@@ -229,7 +241,8 @@
  * - 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)
+int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
+		       unsigned int flags)
 {
 	struct link_master *master_link = snd_kcontrol_chip(master);
 	struct link_slave *srec;
@@ -241,6 +254,7 @@
 	srec->slave = *slave;
 	memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
 	srec->master = master_link;
+	srec->flags = flags;
 
 	/* override callbacks */
 	slave->info = slave_info;
@@ -254,8 +268,7 @@
 	list_add_tail(&srec->list, &master_link->slaves);
 	return 0;
 }
-
-EXPORT_SYMBOL(snd_ctl_add_slave);
+EXPORT_SYMBOL(_snd_ctl_add_slave);
 
 /*
  * ctl callbacks for master controls
@@ -327,8 +340,20 @@
 }
 
 
-/*
- * Create a virtual master control with the given name
+/**
+ * snd_ctl_make_virtual_master - Create a virtual master control
+ * @name: name string of the control element to create
+ * @tlv: optional TLV int array for dB information
+ *
+ * Creates a virtual matster control with the given name string.
+ * Returns the created control element, or NULL for errors (ENOMEM).
+ *
+ * After creating a vmaster element, you can add the slave controls
+ * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
+ *
+ * The optional argument @tlv can be used to specify the TLV information
+ * for dB scale of the master control.  It should be a single element
+ * with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB.
  */
 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 						 const unsigned int *tlv)
@@ -367,5 +392,4 @@
 
 	return kctl;
 }
-
 EXPORT_SYMBOL(snd_ctl_make_virtual_master);
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 73be7e1..54239d2 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -588,10 +588,10 @@
 	int idx, err;
 	int dev = devptr->id;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_dummy));
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_dummy), &card);
+	if (err < 0)
+		return err;
 	dummy = card->private_data;
 	dummy->card = card;
 	for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) {
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
index 7783843..1950ffc 100644
--- a/sound/drivers/ml403-ac97cr.c
+++ b/sound/drivers/ml403-ac97cr.c
@@ -1279,9 +1279,9 @@
 	if (!enable[dev])
 		return -ENOENT;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr);
 	if (err < 0) {
 		PDEBUG(INIT_FAILURE, "probe(): create failed!\n");
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 5b996f3..149d05a 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -73,9 +73,9 @@
 		snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n");
 
 	*rcard = NULL;
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	strcpy(card->driver, "MPU-401 UART");
 	strcpy(card->shortname, card->driver);
 	sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]);
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 48b64e6..2f8f295 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -303,8 +303,10 @@
 
 		snd_mtpav_send_byte(mtp_card, 0xf5);
 		snd_mtpav_send_byte(mtp_card, portp->hwport);
-		//snd_printk("new outport: 0x%x\n", (unsigned int) portp->hwport);
-
+		/*
+		snd_printk(KERN_DEBUG "new outport: 0x%x\n",
+			   (unsigned int) portp->hwport);
+		*/
 		if (!(outbyte & 0x80) && portp->running_status)
 			snd_mtpav_send_byte(mtp_card, portp->running_status);
 	}
@@ -540,7 +542,7 @@
 
 	u8 sbyt = snd_mtpav_getreg(mcrd, SREG);
 
-	//printk("snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt);
+	/* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */
 
 	if (!(sbyt & SIGS_BYTE))
 		return;
@@ -585,12 +587,12 @@
 static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
 {
 	if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
-		snd_printk("MTVAP port 0x%lx is busy\n", port);
+		snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
 		return -EBUSY;
 	}
 	mcard->port = port;
 	if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) {
-		snd_printk("MTVAP IRQ %d busy\n", irq);
+		snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
 		return -EBUSY;
 	}
 	mcard->irq = irq;
@@ -696,9 +698,9 @@
 	int err;
 	struct mtpav *mtp_card;
 
-	card = snd_card_new(index, id, THIS_MODULE, sizeof(*mtp_card));
-	if (! card)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, sizeof(*mtp_card), &card);
+	if (err < 0)
+		return err;
 
 	mtp_card = card->private_data;
 	spin_lock_init(&mtp_card->spinlock);
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index 87ba1dd..9284829 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -957,10 +957,10 @@
 	if ((err = snd_mts64_probe_port(p)) < 0)
 		return err;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL) {
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0) {
 		snd_printd("Cannot create card\n");
-		return -ENOMEM;
+		return err;
 	}
 	strcpy(card->driver, DRIVER_NAME);
 	strcpy(card->shortname, "ESI " CARD_NAME);
@@ -1015,7 +1015,7 @@
 		goto __err;
 	}
 
-	snd_printk("ESI Miditerminal 4140 on 0x%lx\n", p->base);
+	snd_printk(KERN_INFO "ESI Miditerminal 4140 on 0x%lx\n", p->base);
 	return 0;
 
 __err:
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index 7805823..6e31e46 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -302,7 +302,7 @@
 	opl3 = hw->private_data;
 	status = inb(opl3->l_port);
 #if 0
-	snd_printk("AdLib IRQ status = 0x%x\n", status);
+	snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status);
 #endif
 	if (!(status & 0x80))
 		return;
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 16feafa..6e7d09a 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -125,7 +125,7 @@
 	int i;
 	char *str = "x.24";
 
-	printk("time %.5i: %s [%.2i]: ", opl3->use_time, s, voice);
+	printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice);
 	for (i = 0; i < opl3->max_voices; i++)
 		printk("%c", *(str + opl3->voices[i].state + 1));
 	printk("\n");
@@ -218,7 +218,7 @@
 	for (i = 0; i < END; i++) {
 		if (best[i].voice >= 0) {
 #ifdef DEBUG_ALLOC
-			printk("%s %iop allocation on voice %i\n",
+			printk(KERN_DEBUG "%s %iop allocation on voice %i\n",
 			       alloc_type[i], instr_4op ? 4 : 2,
 			       best[i].voice);
 #endif
@@ -317,7 +317,7 @@
 	opl3 = p;
 
 #ifdef DEBUG_MIDI
-	snd_printk("Note on, ch %i, inst %i, note %i, vel %i\n",
+	snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n",
 		   chan->number, chan->midi_program, note, vel);
 #endif
 
@@ -372,7 +372,7 @@
 		return;
 	}
 #ifdef DEBUG_MIDI
-	snd_printk("  --> OPL%i instrument: %s\n",
+	snd_printk(KERN_DEBUG "  --> OPL%i instrument: %s\n",
 		   instr_4op ? 3 : 2, patch->name);
 #endif
 	/* in SYNTH mode, application takes care of voices */
@@ -431,7 +431,7 @@
 	}
 
 #ifdef DEBUG_MIDI
-	snd_printk("  --> setting OPL3 connection: 0x%x\n",
+	snd_printk(KERN_DEBUG "  --> setting OPL3 connection: 0x%x\n",
 		   opl3->connection_reg);
 #endif
 	/*
@@ -466,7 +466,7 @@
 	/* Program the FM voice characteristics */
 	for (i = 0; i < (instr_4op ? 4 : 2); i++) {
 #ifdef DEBUG_MIDI
-		snd_printk("  --> programming operator %i\n", i);
+		snd_printk(KERN_DEBUG "  --> programming operator %i\n", i);
 #endif
 		op_offset = snd_opl3_regmap[voice_offset][i];
 
@@ -546,7 +546,7 @@
 	blocknum |= OPL3_KEYON_BIT;
 
 #ifdef DEBUG_MIDI
-	snd_printk("  --> trigger voice %i\n", voice);
+	snd_printk(KERN_DEBUG "  --> trigger voice %i\n", voice);
 #endif
 	/* Set OPL3 KEYON_BLOCK register of requested voice */ 
 	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
@@ -602,7 +602,7 @@
 			prg = extra_prg - 1;
 		}
 #ifdef DEBUG_MIDI
-		snd_printk(" *** allocating extra program\n");
+		snd_printk(KERN_DEBUG " *** allocating extra program\n");
 #endif
 		goto __extra_prg;
 	}
@@ -633,7 +633,7 @@
 
 	/* kill voice */
 #ifdef DEBUG_MIDI
-	snd_printk("  --> kill voice %i\n", voice);
+	snd_printk(KERN_DEBUG "  --> kill voice %i\n", voice);
 #endif
 	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
 	/* clear Key ON bit */
@@ -670,7 +670,7 @@
 	opl3 = p;
 
 #ifdef DEBUG_MIDI
-	snd_printk("Note off, ch %i, inst %i, note %i\n",
+	snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n",
 		   chan->number, chan->midi_program, note);
 #endif
 
@@ -709,7 +709,7 @@
 
 	opl3 = p;
 #ifdef DEBUG_MIDI
-	snd_printk("Key pressure, ch#: %i, inst#: %i\n",
+	snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
 #endif
 }
@@ -723,7 +723,7 @@
 
 	opl3 = p;
 #ifdef DEBUG_MIDI
-	snd_printk("Terminate note, ch#: %i, inst#: %i\n",
+	snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
 #endif
 }
@@ -812,7 +812,7 @@
 
 	opl3 = p;
 #ifdef DEBUG_MIDI
-	snd_printk("Controller, TYPE = %i, ch#: %i, inst#: %i\n",
+	snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n",
 		   type, chan->number, chan->midi_program);
 #endif
 
@@ -849,7 +849,7 @@
 
 	opl3 = p;
 #ifdef DEBUG_MIDI
-	snd_printk("NRPN, ch#: %i, inst#: %i\n",
+	snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
 #endif
 }
@@ -864,6 +864,6 @@
 
 	opl3 = p;
 #ifdef DEBUG_MIDI
-	snd_printk("SYSEX\n");
+	snd_printk(KERN_DEBUG "SYSEX\n");
 #endif
 }
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index 9a2271d..a54b1dc 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -220,14 +220,14 @@
 		return -EINVAL;
 
 	if (count < (int)sizeof(sbi)) {
-		snd_printk("FM Error: Patch record too short\n");
+		snd_printk(KERN_ERR "FM Error: Patch record too short\n");
 		return -EINVAL;
 	}
 	if (copy_from_user(&sbi, buf, sizeof(sbi)))
 		return -EFAULT;
 
 	if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) {
-		snd_printk("FM Error: Invalid instrument number %d\n",
+		snd_printk(KERN_ERR "FM Error: Invalid instrument number %d\n",
 			   sbi.channel);
 		return -EINVAL;
 	}
@@ -254,7 +254,9 @@
 	opl3 = arg->private_data;
 	switch (cmd) {
 		case SNDCTL_FM_LOAD_INSTR:
-			snd_printk("OPL3: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n");
+			snd_printk(KERN_ERR "OPL3: "
+				   "Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. "
+				   "Fix the program.\n");
 			return -EINVAL;
 
 		case SNDCTL_SYNTH_MEMAVL:
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
index 962bb9c..6d57b6441 100644
--- a/sound/drivers/opl3/opl3_synth.c
+++ b/sound/drivers/opl3/opl3_synth.c
@@ -168,7 +168,7 @@
 
 #ifdef CONFIG_SND_DEBUG
 	default:
-		snd_printk("unknown IOCTL: 0x%x\n", cmd);
+		snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd);
 #endif
 	}
 	return -ENOTTY;
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index a4049eb..b60cef2 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -57,7 +57,7 @@
 	else
 		min_div = MAX_DIV;
 #if PCSP_DEBUG
-	printk("PCSP: lpj=%li, min_div=%i, res=%li\n",
+	printk(KERN_DEBUG "PCSP: lpj=%li, min_div=%i, res=%li\n",
 	       loops_per_jiffy, min_div, tp.tv_nsec);
 #endif
 
@@ -98,9 +98,9 @@
 	hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	pcsp_chip.timer.function = pcsp_do_timer;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (!card)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	err = snd_pcsp_create(card);
 	if (err < 0) {
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
index b1c047e..60158e2 100644
--- a/sound/drivers/portman2x4.c
+++ b/sound/drivers/portman2x4.c
@@ -746,10 +746,10 @@
 	if ((err = snd_portman_probe_port(p)) < 0)
 		return err;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL) {
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0) {
 		snd_printd("Cannot create card\n");
-		return -ENOMEM;
+		return err;
 	}
 	strcpy(card->driver, DRIVER_NAME);
 	strcpy(card->shortname, CARD_NAME);
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index d8aab9d..b2b6d50 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -241,7 +241,8 @@
 			snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
 
 		if (status & UART_LSR_OE)
-			snd_printk("%s: Overrun on device at 0x%lx\n",
+			snd_printk(KERN_WARNING
+				   "%s: Overrun on device at 0x%lx\n",
 			       uart->rmidi->name, uart->base);
 	}
 
@@ -636,7 +637,8 @@
 		}
 	} else {
 		if (!snd_uart16550_write_buffer(uart, midi_byte)) {
-			snd_printk("%s: Buffer overrun on device at 0x%lx\n",
+			snd_printk(KERN_WARNING
+				   "%s: Buffer overrun on device at 0x%lx\n",
 				   uart->rmidi->name, uart->base);
 			return 0;
 		}
@@ -815,7 +817,8 @@
 	if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
 		if (request_irq(irq, snd_uart16550_interrupt,
 				IRQF_DISABLED, "Serial MIDI", uart)) {
-			snd_printk("irq %d busy. Using Polling.\n", irq);
+			snd_printk(KERN_WARNING
+				   "irq %d busy. Using Polling.\n", irq);
 		} else {
 			uart->irq = irq;
 		}
@@ -919,26 +922,29 @@
 	case SNDRV_SERIAL_GENERIC:
 		break;
 	default:
-		snd_printk("Adaptor type is out of range 0-%d (%d)\n",
+		snd_printk(KERN_ERR
+			   "Adaptor type is out of range 0-%d (%d)\n",
 			   SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]);
 		return -ENODEV;
 	}
 
 	if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) {
-		snd_printk("Count of outputs is out of range 1-%d (%d)\n",
+		snd_printk(KERN_ERR
+			   "Count of outputs is out of range 1-%d (%d)\n",
 			   SNDRV_SERIAL_MAX_OUTS, outs[dev]);
 		return -ENODEV;
 	}
 
 	if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) {
-		snd_printk("Count of inputs is out of range 1-%d (%d)\n",
+		snd_printk(KERN_ERR
+			   "Count of inputs is out of range 1-%d (%d)\n",
 			   SNDRV_SERIAL_MAX_INS, ins[dev]);
 		return -ENODEV;
 	}
 
-	card  = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err  = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "Serial");
 	strcpy(card->shortname, "Serial MIDI (UART16550A)");
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index f79e361..0e631c3 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -90,15 +90,17 @@
 	int idx, err;
 	int dev = devptr->id;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_card_virmidi));
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_card_virmidi), &card);
+	if (err < 0)
+		return err;
 	vmidi = (struct snd_card_virmidi *)card->private_data;
 	vmidi->card = card;
 
 	if (midi_devs[dev] > MAX_MIDI_DEVICES) {
-		snd_printk("too much midi devices for virmidi %d: force to use %d\n", dev, MAX_MIDI_DEVICES);
+		snd_printk(KERN_WARNING
+			   "too much midi devices for virmidi %d: "
+			   "force to use %d\n", dev, MAX_MIDI_DEVICES);
 		midi_devs[dev] = MAX_MIDI_DEVICES;
 	}
 	for (idx = 0; idx < midi_devs[dev]; idx++) {
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 14e3354..19c6e37 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -688,7 +688,8 @@
 		image = dsp->data + i;
 		/* Wait DSP ready for a new read */
 		if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) {
-			printk("dsp loading error at position %d\n", i);
+			printk(KERN_ERR
+			       "dsp loading error at position %d\n", i);
 			return err;
 		}
 		cptr = image;
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index 8d6362e..46df881 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -119,16 +119,6 @@
 
 #else /* old style firmware loading */
 
-static int vx_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
-static int vx_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
 static int vx_hwdep_dsp_status(struct snd_hwdep *hw,
 			       struct snd_hwdep_dsp_status *info)
 {
@@ -243,8 +233,6 @@
 
 	hw->iface = SNDRV_HWDEP_IFACE_VX;
 	hw->private_data = chip;
-	hw->ops.open = vx_hwdep_open;
-	hw->ops.release = vx_hwdep_release;
 	hw->ops.dsp_status = vx_hwdep_dsp_status;
 	hw->ops.dsp_load = vx_hwdep_dsp_load;
 	hw->exclusive = 1;
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c
index 0e1ba9b..b0560fec 100644
--- a/sound/drivers/vx/vx_uer.c
+++ b/sound/drivers/vx/vx_uer.c
@@ -103,7 +103,7 @@
  * returns the frequency of UER, or 0 if not sync,
  * or a negative error code.
  */
-static int vx_read_uer_status(struct vx_core *chip, int *mode)
+static int vx_read_uer_status(struct vx_core *chip, unsigned int *mode)
 {
 	int val, freq;
 
diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile
index 37970666..36879bf 100644
--- a/sound/i2c/Makefile
+++ b/sound/i2c/Makefile
@@ -7,8 +7,6 @@
 snd-cs8427-objs := cs8427.o
 snd-tea6330t-objs := tea6330t.o
 
-obj-$(CONFIG_L3) += l3/
-
 obj-$(CONFIG_SND) += other/
 
 # Toplevel Module Dependency
diff --git a/sound/i2c/l3/Makefile b/sound/i2c/l3/Makefile
deleted file mode 100644
index 49455b8..0000000
--- a/sound/i2c/l3/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for ALSA
-#
-
-snd-uda1341-objs := uda1341.o
-
-# Module Dependency
-obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-uda1341.o
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
deleted file mode 100644
index 9840eb4..0000000
--- a/sound/i2c/l3/uda1341.c
+++ /dev/null
@@ -1,935 +0,0 @@
-/*
- * Philips UDA1341 mixer device driver
- * Copyright (c) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
- *
- * Portions are Copyright (C) 2000 Lernout & Hauspie Speech Products, N.V.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License.
- *
- * History:
- *
- * 2002-03-13   Tomas Kasparek  initial release - based on uda1341.c from OSS
- * 2002-03-28   Tomas Kasparek  basic mixer is working (volume, bass, treble)
- * 2002-03-30   Tomas Kasparek  proc filesystem support, complete mixer and DSP
- *                              features support
- * 2002-04-12	Tomas Kasparek	proc interface update, code cleanup
- * 2002-05-12   Tomas Kasparek  another code cleanup
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/ioctl.h>
-
-#include <asm/uaccess.h>
-
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/initval.h>
-#include <sound/info.h>
-
-#include <linux/l3/l3.h>
-
-#include <sound/uda1341.h>
-
-/* {{{ HW regs definition */
-
-#define STAT0                   0x00
-#define STAT1			0x80
-#define STAT_MASK               0x80
-
-#define DATA0_0			0x00
-#define DATA0_1			0x40
-#define DATA0_2			0x80
-#define DATA_MASK               0xc0
-
-#define IS_DATA0(x)     ((x) >= data0_0 && (x) <= data0_2)
-#define IS_DATA1(x)     ((x) == data1)
-#define IS_STATUS(x)    ((x) == stat0 || (x) == stat1)
-#define IS_EXTEND(x)   ((x) >= ext0 && (x) <= ext6)
-
-/* }}} */
-
-
-static const char *peak_names[] = {
-	"before",
-	"after",
-};
-
-static const char *filter_names[] = {
-	"flat",
-	"min",
-	"min",
-	"max",
-};
-
-static const char *mixer_names[] = {
-	"double differential",
-	"input channel 1 (line in)",
-	"input channel 2 (microphone)",
-	"digital mixer",
-};
-
-static const char *deemp_names[] = {
-	"none",
-	"32 kHz",
-	"44.1 kHz",
-	"48 kHz",        
-};
-
-enum uda1341_regs_names {
-	stat0,
-	stat1,
-	data0_0,
-	data0_1,
-	data0_2,
-	data1,
-	ext0,
-	ext1,
-	ext2,
-	empty,
-	ext4,
-	ext5,
-	ext6,
-	uda1341_reg_last,
-};
-
-static const char *uda1341_reg_names[] = {
-	"stat 0 ",
-	"stat 1 ",
-	"data 00",
-	"data 01",
-	"data 02",
-	"data 1 ",
-	"ext 0",
-	"ext 1",
-	"ext 2",
-	"empty",
-	"ext 4",
-	"ext 5",
-	"ext 6",
-};
-
-static const int uda1341_enum_items[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	2, //peak - before/after
-	4, //deemp - none/32/44.1/48
-	0,
-	4, //filter - flat/min/min/max
-	0, 0, 0,
-	4, //mixer - differ/line/mic/mixer
-	0, 0, 0, 0, 0,
-};
-
-static const char ** uda1341_enum_names[] = {
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	peak_names, //peak - before/after
-	deemp_names, //deemp - none/32/44.1/48
-	NULL,
-	filter_names, //filter - flat/min/min/max
-	NULL, NULL, NULL,
-	mixer_names, //mixer - differ/line/mic/mixer
-	NULL, NULL, NULL, NULL, NULL,
-};
-
-typedef int uda1341_cfg[CMD_LAST];
-
-struct uda1341 {
-	int (*write) (struct l3_client *uda1341, unsigned short reg, unsigned short val);
-	int (*read) (struct l3_client *uda1341, unsigned short reg);        
-	unsigned char regs[uda1341_reg_last];
-	int active;
-	spinlock_t reg_lock;
-	struct snd_card *card;
-	uda1341_cfg cfg;
-#ifdef CONFIG_PM
-	unsigned char suspend_regs[uda1341_reg_last];
-	uda1341_cfg suspend_cfg;
-#endif
-};
-
-/* transfer 8bit integer into string with binary representation */
-static void int2str_bin8(uint8_t val, char *buf)
-{
-	const int size = sizeof(val) * 8;
-	int i;
-
-	for (i= 0; i < size; i++){
-		*(buf++) = (val >> (size - 1)) ? '1' : '0';
-		val <<= 1;
-	}
-	*buf = '\0'; //end the string with zero
-}
-
-/* {{{ HW manipulation routines */
-
-static int snd_uda1341_codec_write(struct l3_client *clnt, unsigned short reg, unsigned short val)
-{
-	struct uda1341 *uda = clnt->driver_data;
-	unsigned char buf[2] = { 0xc0, 0xe0 }; // for EXT addressing
-	int err = 0;
-
-	uda->regs[reg] = val;
-
-	if (uda->active) {
-		if (IS_DATA0(reg)) {
-			err = l3_write(clnt, UDA1341_DATA0, (const unsigned char *)&val, 1);
-		} else if (IS_DATA1(reg)) {
-			err = l3_write(clnt, UDA1341_DATA1, (const unsigned char *)&val, 1);
-		} else if (IS_STATUS(reg)) {
-			err = l3_write(clnt, UDA1341_STATUS, (const unsigned char *)&val, 1);
-		} else if (IS_EXTEND(reg)) {
-			buf[0] |= (reg - ext0) & 0x7;   //EXT address
-			buf[1] |= val;                  //EXT data
-			err = l3_write(clnt, UDA1341_DATA0, (const unsigned char *)buf, 2);
-		}
-	} else
-		printk(KERN_ERR "UDA1341 codec not active!\n");
-	return err;
-}
-
-static int snd_uda1341_codec_read(struct l3_client *clnt, unsigned short reg)
-{
-	unsigned char val;
-	int err;
-
-	err = l3_read(clnt, reg, &val, 1);
-	if (err == 1)
-		// use just 6bits - the rest is address of the reg
-		return val & 63;
-	return err < 0 ? err : -EIO;
-}
-
-static inline int snd_uda1341_valid_reg(struct l3_client *clnt, unsigned short reg)
-{
-	return reg < uda1341_reg_last;
-}
-
-static int snd_uda1341_update_bits(struct l3_client *clnt, unsigned short reg,
-				   unsigned short mask, unsigned short shift,
-				   unsigned short value, int flush)
-{
-	int change;
-	unsigned short old, new;
-	struct uda1341 *uda = clnt->driver_data;
-
-#if 0
-	printk(KERN_DEBUG "update_bits: reg: %s mask: %d shift: %d val: %d\n",
-	       uda1341_reg_names[reg], mask, shift, value);
-#endif
-        
-	if (!snd_uda1341_valid_reg(clnt, reg))
-		return -EINVAL;
-	spin_lock(&uda->reg_lock);
-	old = uda->regs[reg];
-	new = (old & ~(mask << shift)) | (value << shift);
-	change = old != new;
-	if (change) {
-		if (flush) uda->write(clnt, reg, new);
-		uda->regs[reg] = new;
-	}
-	spin_unlock(&uda->reg_lock);
-	return change;
-}
-
-static int snd_uda1341_cfg_write(struct l3_client *clnt, unsigned short what,
-				 unsigned short value, int flush)
-{
-	struct uda1341 *uda = clnt->driver_data;
-	int ret = 0;
-#ifdef CONFIG_PM
-	int reg;
-#endif
-
-#if 0
-	printk(KERN_DEBUG "cfg_write what: %d value: %d\n", what, value);
-#endif
-
-	uda->cfg[what] = value;
-        
-	switch(what) {
-	case CMD_RESET:
-		ret = snd_uda1341_update_bits(clnt, data0_2, 1, 2, 1, flush);	// MUTE
-		ret = snd_uda1341_update_bits(clnt, stat0, 1, 6, 1, flush);	// RESET
-		ret = snd_uda1341_update_bits(clnt, stat0, 1, 6, 0, flush);	// RESTORE
-		uda->cfg[CMD_RESET]=0;
-		break;
-	case CMD_FS:
-		ret = snd_uda1341_update_bits(clnt, stat0, 3, 4, value, flush);
-		break;
-	case CMD_FORMAT:
-		ret = snd_uda1341_update_bits(clnt, stat0, 7, 1, value, flush);
-		break;
-	case CMD_OGAIN:
-		ret = snd_uda1341_update_bits(clnt, stat1, 1, 6, value, flush);
-		break;
-	case CMD_IGAIN:
-		ret = snd_uda1341_update_bits(clnt, stat1, 1, 5, value, flush);
-		break;
-	case CMD_DAC:
-		ret = snd_uda1341_update_bits(clnt, stat1, 1, 0, value, flush);
-		break;
-	case CMD_ADC:
-		ret = snd_uda1341_update_bits(clnt, stat1, 1, 1, value, flush);
-		break;
-	case CMD_VOLUME:
-		ret = snd_uda1341_update_bits(clnt, data0_0, 63, 0, value, flush);
-		break;
-	case CMD_BASS:
-		ret = snd_uda1341_update_bits(clnt, data0_1, 15, 2, value, flush);
-		break;
-	case CMD_TREBBLE:
-		ret = snd_uda1341_update_bits(clnt, data0_1, 3, 0, value, flush);
-		break;
-	case CMD_PEAK:
-		ret = snd_uda1341_update_bits(clnt, data0_2, 1, 5, value, flush);
-		break;
-	case CMD_DEEMP:
-		ret = snd_uda1341_update_bits(clnt, data0_2, 3, 3, value, flush);
-		break;
-	case CMD_MUTE:
-		ret = snd_uda1341_update_bits(clnt, data0_2, 1, 2, value, flush);
-		break;
-	case CMD_FILTER:
-		ret = snd_uda1341_update_bits(clnt, data0_2, 3, 0, value, flush);
-		break;
-	case CMD_CH1:
-		ret = snd_uda1341_update_bits(clnt, ext0, 31, 0, value, flush);
-		break;
-	case CMD_CH2:
-		ret = snd_uda1341_update_bits(clnt, ext1, 31, 0, value, flush);
-		break;
-	case CMD_MIC:
-		ret = snd_uda1341_update_bits(clnt, ext2, 7, 2, value, flush);
-		break;
-	case CMD_MIXER:
-		ret = snd_uda1341_update_bits(clnt, ext2, 3, 0, value, flush);
-		break;
-	case CMD_AGC:
-		ret = snd_uda1341_update_bits(clnt, ext4, 1, 4, value, flush);
-		break;
-	case CMD_IG:
-		ret = snd_uda1341_update_bits(clnt, ext4, 3, 0, value & 0x3, flush);
-		ret = snd_uda1341_update_bits(clnt, ext5, 31, 0, value >> 2, flush);
-		break;
-	case CMD_AGC_TIME:
-		ret = snd_uda1341_update_bits(clnt, ext6, 7, 2, value, flush);
-		break;
-	case CMD_AGC_LEVEL:
-		ret = snd_uda1341_update_bits(clnt, ext6, 3, 0, value, flush);
-		break;
-#ifdef CONFIG_PM		
-	case CMD_SUSPEND:
-		for (reg = stat0; reg < uda1341_reg_last; reg++)
-			uda->suspend_regs[reg] = uda->regs[reg];
-		for (reg = 0; reg < CMD_LAST; reg++)
-			uda->suspend_cfg[reg] = uda->cfg[reg];
-		break;
-	case CMD_RESUME:
-		for (reg = stat0; reg < uda1341_reg_last; reg++)
-			snd_uda1341_codec_write(clnt, reg, uda->suspend_regs[reg]);
-		for (reg = 0; reg < CMD_LAST; reg++)
-			uda->cfg[reg] = uda->suspend_cfg[reg];
-		break;
-#endif
-	default:
-		ret = -EINVAL;
-		break;
-	}
-                
-	if (!uda->active)
-		printk(KERN_ERR "UDA1341 codec not active!\n");                
-	return ret;
-}
-
-/* }}} */
-
-/* {{{ Proc interface */
-#ifdef CONFIG_PROC_FS
-
-static const char *format_names[] = {
-	"I2S-bus",
-	"LSB 16bits",
-	"LSB 18bits",
-	"LSB 20bits",
-	"MSB",
-	"in LSB 16bits/out MSB",
-	"in LSB 18bits/out MSB",
-	"in LSB 20bits/out MSB",        
-};
-
-static const char *fs_names[] = {
-	"512*fs",
-	"384*fs",
-	"256*fs",
-	"Unused - bad value!",
-};
-
-static const char* bass_values[][16] = {
-	{"0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB",
-	 "0 dB", "0 dB", "0 dB", "0 dB", "undefined", }, //flat
-	{"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
-	 "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
-	{"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
-	 "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
-	{"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "20 dB",
-	 "22 dB", "24 dB", "24 dB", "24 dB", "undefined",}, // max
-};
-
-static const char *mic_sens_value[] = {
-	"-3 dB", "0 dB", "3 dB", "9 dB", "15 dB", "21 dB", "27 dB", "not used",
-};
-
-static const unsigned short AGC_atime[] = {
-	11, 16, 11, 16, 21, 11, 16, 21,
-};
-
-static const unsigned short AGC_dtime[] = {
-	100, 100, 200, 200, 200, 400, 400, 400,
-};
-
-static const char *AGC_level[] = {
-	"-9.0", "-11.5", "-15.0", "-17.5",
-};
-
-static const char *ig_small_value[] = {
-	"-3.0", "-2.5", "-2.0", "-1.5", "-1.0", "-0.5",
-};
-
-/*
- * this was computed as peak_value[i] = pow((63-i)*1.42,1.013)
- *
- * UDA1341 datasheet on page 21: Peak value (dB) = (Peak level - 63.5)*5*log2
- * There is an table with these values [level]=value: [3]=-90.31, [7]=-84.29
- * [61]=-2.78, [62] = -1.48, [63] = 0.0
- * I tried to compute it, but using but even using logarithm with base either 10 or 2
- * i was'n able to get values in the table from the formula. So I constructed another
- * formula (see above) to interpolate the values as good as possible. If there is some
- * mistake, please contact me on tomas.kasparek@seznam.cz. Thanks.
- * UDA1341TS datasheet is available at:
- *   http://www-us9.semiconductors.com/acrobat/datasheets/UDA1341TS_3.pdf 
- */
-static const char *peak_value[] = {
-	"-INF dB", "N.A.", "N.A", "90.31 dB", "N.A.", "N.A.", "N.A.", "-84.29 dB",
-	"-82.65 dB", "-81.13 dB", "-79.61 dB", "-78.09 dB", "-76.57 dB", "-75.05 dB", "-73.53 dB",
-	"-72.01 dB", "-70.49 dB", "-68.97 dB", "-67.45 dB", "-65.93 dB", "-64.41 dB", "-62.90 dB",
-	"-61.38 dB", "-59.86 dB", "-58.35 dB", "-56.83 dB", "-55.32 dB", "-53.80 dB", "-52.29 dB",
-	"-50.78 dB", "-49.26 dB", "-47.75 dB", "-46.24 dB", "-44.73 dB", "-43.22 dB", "-41.71 dB",
-	"-40.20 dB", "-38.69 dB", "-37.19 dB", "-35.68 dB", "-34.17 dB", "-32.67 dB", "-31.17 dB",
-	"-29.66 dB", "-28.16 dB", "-26.66 dB", "-25.16 dB", "-23.66 dB", "-22.16 dB", "-20.67 dB",
-	"-19.17 dB", "-17.68 dB", "-16.19 dB", "-14.70 dB", "-13.21 dB", "-11.72 dB", "-10.24 dB",
-	"-8.76 dB", "-7.28 dB", "-5.81 dB", "-4.34 dB", "-2.88 dB", "-1.43 dB", "0.00 dB",
-};
-
-static void snd_uda1341_proc_read(struct snd_info_entry *entry, 
-				  struct snd_info_buffer *buffer)
-{
-	struct l3_client *clnt = entry->private_data;
-	struct uda1341 *uda = clnt->driver_data;
-	int peak;
-
-	peak = snd_uda1341_codec_read(clnt, UDA1341_DATA1);
-	if (peak < 0)
-		peak = 0;
-	
-	snd_iprintf(buffer, "%s\n\n", uda->card->longname);
-
-	// for information about computed values see UDA1341TS datasheet pages 15 - 21
-	snd_iprintf(buffer, "DAC power           : %s\n", uda->cfg[CMD_DAC] ? "on" : "off");
-	snd_iprintf(buffer, "ADC power           : %s\n", uda->cfg[CMD_ADC] ? "on" : "off");
- 	snd_iprintf(buffer, "Clock frequency     : %s\n", fs_names[uda->cfg[CMD_FS]]);
-	snd_iprintf(buffer, "Data format         : %s\n\n", format_names[uda->cfg[CMD_FORMAT]]);
-
-	snd_iprintf(buffer, "Filter mode         : %s\n", filter_names[uda->cfg[CMD_FILTER]]);
-	snd_iprintf(buffer, "Mixer mode          : %s\n", mixer_names[uda->cfg[CMD_MIXER]]);
-	snd_iprintf(buffer, "De-emphasis         : %s\n", deemp_names[uda->cfg[CMD_DEEMP]]);	
-	snd_iprintf(buffer, "Peak detection pos. : %s\n", uda->cfg[CMD_PEAK] ? "after" : "before");
-	snd_iprintf(buffer, "Peak value          : %s\n\n", peak_value[peak]);		
-	
-	snd_iprintf(buffer, "Automatic Gain Ctrl : %s\n", uda->cfg[CMD_AGC] ? "on" : "off");
-	snd_iprintf(buffer, "AGC attack time     : %d ms\n", AGC_atime[uda->cfg[CMD_AGC_TIME]]);
-	snd_iprintf(buffer, "AGC decay time      : %d ms\n", AGC_dtime[uda->cfg[CMD_AGC_TIME]]);
-	snd_iprintf(buffer, "AGC output level    : %s dB\n\n", AGC_level[uda->cfg[CMD_AGC_LEVEL]]);
-
-	snd_iprintf(buffer, "Mute                : %s\n", uda->cfg[CMD_MUTE] ? "on" : "off");
-
-	if (uda->cfg[CMD_VOLUME] == 0)
-		snd_iprintf(buffer, "Volume              : 0 dB\n");
-	else if (uda->cfg[CMD_VOLUME] < 62)
-		snd_iprintf(buffer, "Volume              : %d dB\n", -1*uda->cfg[CMD_VOLUME] +1);
-	else
-		snd_iprintf(buffer, "Volume              : -INF dB\n");
-	snd_iprintf(buffer, "Bass                : %s\n", bass_values[uda->cfg[CMD_FILTER]][uda->cfg[CMD_BASS]]);
-	snd_iprintf(buffer, "Trebble             : %d dB\n", uda->cfg[CMD_FILTER] ? 2*uda->cfg[CMD_TREBBLE] : 0);
-	snd_iprintf(buffer, "Input Gain (6dB)    : %s\n", uda->cfg[CMD_IGAIN] ? "on" : "off");
-	snd_iprintf(buffer, "Output Gain (6dB)   : %s\n", uda->cfg[CMD_OGAIN] ? "on" : "off");
-	snd_iprintf(buffer, "Mic sensitivity     : %s\n", mic_sens_value[uda->cfg[CMD_MIC]]);
-
-	
-	if(uda->cfg[CMD_CH1] < 31)
-		snd_iprintf(buffer, "Mixer gain channel 1: -%d.%c dB\n",
-			    ((uda->cfg[CMD_CH1] >> 1) * 3) + (uda->cfg[CMD_CH1] & 1),
-			    uda->cfg[CMD_CH1] & 1 ? '5' : '0');
-	else
-		snd_iprintf(buffer, "Mixer gain channel 1: -INF dB\n");
-	if(uda->cfg[CMD_CH2] < 31)
-		snd_iprintf(buffer, "Mixer gain channel 2: -%d.%c dB\n",
-			    ((uda->cfg[CMD_CH2] >> 1) * 3) + (uda->cfg[CMD_CH2] & 1),
-			    uda->cfg[CMD_CH2] & 1 ? '5' : '0');
-	else
-		snd_iprintf(buffer, "Mixer gain channel 2: -INF dB\n");
-
-	if(uda->cfg[CMD_IG] > 5)
-		snd_iprintf(buffer, "Input Amp. Gain ch 2: %d.%c dB\n",
-			    (uda->cfg[CMD_IG] >> 1) -3, uda->cfg[CMD_IG] & 1 ? '5' : '0');
-	else
-		snd_iprintf(buffer, "Input Amp. Gain ch 2: %s dB\n",  ig_small_value[uda->cfg[CMD_IG]]);
-}
-
-static void snd_uda1341_proc_regs_read(struct snd_info_entry *entry, 
-				       struct snd_info_buffer *buffer)
-{
-	struct l3_client *clnt = entry->private_data;
-	struct uda1341 *uda = clnt->driver_data;		
-	int reg;
-	char buf[12];
-
-	for (reg = 0; reg < uda1341_reg_last; reg ++) {
-		if (reg == empty)
-			continue;
-		int2str_bin8(uda->regs[reg], buf);
-		snd_iprintf(buffer, "%s = %s\n", uda1341_reg_names[reg], buf);
-	}
-
-	int2str_bin8(snd_uda1341_codec_read(clnt, UDA1341_DATA1), buf);
-	snd_iprintf(buffer, "DATA1 = %s\n", buf);
-}
-#endif /* CONFIG_PROC_FS */
-
-static void __devinit snd_uda1341_proc_init(struct snd_card *card, struct l3_client *clnt)
-{
-	struct snd_info_entry *entry;
-
-	if (! snd_card_proc_new(card, "uda1341", &entry))
-		snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_read);
-	if (! snd_card_proc_new(card, "uda1341-regs", &entry))
-		snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_regs_read);
-}
-
-/* }}} */
-
-/* {{{ Mixer controls setting */
-
-/* {{{ UDA1341 single functions */
-
-#define UDA1341_SINGLE(xname, where, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_single, \
-  .get = snd_uda1341_get_single, .put = snd_uda1341_put_single, \
-  .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \
-}
-
-static int snd_uda1341_info_single(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_info *uinfo)
-{
-	int mask = (kcontrol->private_value >> 12) & 63;
-
-	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = mask;
-	return 0;
-}
-
-static int snd_uda1341_get_single(struct snd_kcontrol *kcontrol,
-				  struct snd_ctl_elem_value *ucontrol)
-{
-	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
-	struct uda1341 *uda = clnt->driver_data;
-	int where = kcontrol->private_value & 31;        
-	int mask = (kcontrol->private_value >> 12) & 63;
-	int invert = (kcontrol->private_value >> 18) & 1;
-        
-	ucontrol->value.integer.value[0] = uda->cfg[where];
-	if (invert)
-		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
-
-	return 0;
-}
-
-static int snd_uda1341_put_single(struct snd_kcontrol *kcontrol,
-				  struct snd_ctl_elem_value *ucontrol)
-{
-	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
-	struct uda1341 *uda = clnt->driver_data;
-	int where = kcontrol->private_value & 31;        
-	int reg = (kcontrol->private_value >> 5) & 15;
-	int shift = (kcontrol->private_value >> 9) & 7;
-	int mask = (kcontrol->private_value >> 12) & 63;
-	int invert = (kcontrol->private_value >> 18) & 1;
-	unsigned short val;
-
-	val = (ucontrol->value.integer.value[0] & mask);
-	if (invert)
-		val = mask - val;
-
-	uda->cfg[where] = val;
-	return snd_uda1341_update_bits(clnt, reg, mask, shift, val, FLUSH);
-}
-
-/* }}} */
-
-/* {{{ UDA1341 enum functions */
-
-#define UDA1341_ENUM(xname, where, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_enum, \
-  .get = snd_uda1341_get_enum, .put = snd_uda1341_put_enum, \
-  .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \
-}
-
-static int snd_uda1341_info_enum(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_info *uinfo)
-{
-	int where = kcontrol->private_value & 31;
-	const char **texts;
-	
-	// this register we don't handle this way
-	if (!uda1341_enum_items[where])
-		return -EINVAL;
-
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = uda1341_enum_items[where];
-
-	if (uinfo->value.enumerated.item >= uda1341_enum_items[where])
-		uinfo->value.enumerated.item = uda1341_enum_items[where] - 1;
-
-	texts = uda1341_enum_names[where];
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-	return 0;
-}
-
-static int snd_uda1341_get_enum(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
-	struct uda1341 *uda = clnt->driver_data;
-	int where = kcontrol->private_value & 31;        
-        
-	ucontrol->value.enumerated.item[0] = uda->cfg[where];	
-	return 0;
-}
-
-static int snd_uda1341_put_enum(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
-	struct uda1341 *uda = clnt->driver_data;
-	int where = kcontrol->private_value & 31;        
-	int reg = (kcontrol->private_value >> 5) & 15;
-	int shift = (kcontrol->private_value >> 9) & 7;
-	int mask = (kcontrol->private_value >> 12) & 63;
-
-	uda->cfg[where] = (ucontrol->value.enumerated.item[0] & mask);
-	
-	return snd_uda1341_update_bits(clnt, reg, mask, shift, uda->cfg[where], FLUSH);
-}
-
-/* }}} */
-
-/* {{{ UDA1341 2regs functions */
-
-#define UDA1341_2REGS(xname, where, reg_1, reg_2, shift_1, shift_2, mask_1, mask_2, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_uda1341_info_2regs, \
-  .get = snd_uda1341_get_2regs, .put = snd_uda1341_put_2regs, \
-  .private_value = where | (reg_1 << 5) | (reg_2 << 9) | (shift_1 << 13) | (shift_2 << 16) | \
-                         (mask_1 << 19) | (mask_2 << 25) | (invert << 31) \
-}
-
-
-static int snd_uda1341_info_2regs(struct snd_kcontrol *kcontrol,
-				  struct snd_ctl_elem_info *uinfo)
-{
-	int mask_1 = (kcontrol->private_value >> 19) & 63;
-	int mask_2 = (kcontrol->private_value >> 25) & 63;
-	int mask;
-        
-	mask = (mask_2 + 1) * (mask_1 + 1) - 1;
-	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = mask;
-	return 0;
-}
-
-static int snd_uda1341_get_2regs(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
-	struct uda1341 *uda = clnt->driver_data;
-	int where = kcontrol->private_value & 31;
-	int mask_1 = (kcontrol->private_value >> 19) & 63;
-	int mask_2 = (kcontrol->private_value >> 25) & 63;        
-	int invert = (kcontrol->private_value >> 31) & 1;
-	int mask;
-
-	mask = (mask_2 + 1) * (mask_1 + 1) - 1;
-
-	ucontrol->value.integer.value[0] = uda->cfg[where];
-	if (invert)
-		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
-	return 0;
-}
-
-static int snd_uda1341_put_2regs(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
-	struct uda1341 *uda = clnt->driver_data;        
-	int where = kcontrol->private_value & 31;        
-	int reg_1 = (kcontrol->private_value >> 5) & 15;
-	int reg_2 = (kcontrol->private_value >> 9) & 15;        
-	int shift_1 = (kcontrol->private_value >> 13) & 7;
-	int shift_2 = (kcontrol->private_value >> 16) & 7;
-	int mask_1 = (kcontrol->private_value >> 19) & 63;
-	int mask_2 = (kcontrol->private_value >> 25) & 63;        
-	int invert = (kcontrol->private_value >> 31) & 1;
-	int mask;
-	unsigned short val1, val2, val;
-
-	val = ucontrol->value.integer.value[0];
-         
-	mask = (mask_2 + 1) * (mask_1 + 1) - 1;
-
-	val1 = val & mask_1;
-	val2 = (val / (mask_1 + 1)) & mask_2;        
-
-	if (invert) {
-		val1 = mask_1 - val1;
-		val2 = mask_2 - val2;
-	}
-
-	uda->cfg[where] = invert ? mask - val : val;
-        
-	//FIXME - return value
-	snd_uda1341_update_bits(clnt, reg_1, mask_1, shift_1, val1, FLUSH);
-	return snd_uda1341_update_bits(clnt, reg_2, mask_2, shift_2, val2, FLUSH);
-}
-
-/* }}} */
-  
-static struct snd_kcontrol_new snd_uda1341_controls[] = {
-	UDA1341_SINGLE("Master Playback Switch", CMD_MUTE, data0_2, 2, 1, 1),
-	UDA1341_SINGLE("Master Playback Volume", CMD_VOLUME, data0_0, 0, 63, 1),
-
-	UDA1341_SINGLE("Bass Playback Volume", CMD_BASS, data0_1, 2, 15, 0),
-	UDA1341_SINGLE("Treble Playback Volume", CMD_TREBBLE, data0_1, 0, 3, 0),
-
-	UDA1341_SINGLE("Input Gain Switch", CMD_IGAIN, stat1, 5, 1, 0),
-	UDA1341_SINGLE("Output Gain Switch", CMD_OGAIN, stat1, 6, 1, 0),
-
-	UDA1341_SINGLE("Mixer Gain Channel 1 Volume", CMD_CH1, ext0, 0, 31, 1),
-	UDA1341_SINGLE("Mixer Gain Channel 2 Volume", CMD_CH2, ext1, 0, 31, 1),
-
-	UDA1341_SINGLE("Mic Sensitivity Volume", CMD_MIC, ext2, 2, 7, 0),
-
-	UDA1341_SINGLE("AGC Output Level", CMD_AGC_LEVEL, ext6, 0, 3, 0),
-	UDA1341_SINGLE("AGC Time Constant", CMD_AGC_TIME, ext6, 2, 7, 0),
-	UDA1341_SINGLE("AGC Time Constant Switch", CMD_AGC, ext4, 4, 1, 0),
-
-	UDA1341_SINGLE("DAC Power", CMD_DAC, stat1, 0, 1, 0),
-	UDA1341_SINGLE("ADC Power", CMD_ADC, stat1, 1, 1, 0),
-
-	UDA1341_ENUM("Peak detection", CMD_PEAK, data0_2, 5, 1, 0),
-	UDA1341_ENUM("De-emphasis", CMD_DEEMP, data0_2, 3, 3, 0),
-	UDA1341_ENUM("Mixer mode", CMD_MIXER, ext2, 0, 3, 0),
-	UDA1341_ENUM("Filter mode", CMD_FILTER, data0_2, 0, 3, 0),
-
-	UDA1341_2REGS("Gain Input Amplifier Gain (channel 2)", CMD_IG, ext4, ext5, 0, 0, 3, 31, 0),
-};
-
-static void uda1341_free(struct l3_client *clnt)
-{
-	l3_detach_client(clnt); // calls kfree for driver_data (struct uda1341)
-	kfree(clnt);
-}
-
-static int uda1341_dev_free(struct snd_device *device)
-{
-	struct l3_client *clnt = device->device_data;
-	uda1341_free(clnt);
-	return 0;
-}
-
-int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **clntp)
-{
-	static struct snd_device_ops ops = {
-		.dev_free =     uda1341_dev_free,
-	};
-	struct l3_client *clnt;
-	int idx, err;
-
-	if (snd_BUG_ON(!card))
-		return -EINVAL;
-
-	clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
-	if (clnt == NULL)
-		return -ENOMEM;
-         
-	if ((err = l3_attach_client(clnt, "l3-bit-sa1100-gpio", UDA1341_ALSA_NAME))) {
-		kfree(clnt);
-		return err;
-	}
-
-	for (idx = 0; idx < ARRAY_SIZE(snd_uda1341_controls); idx++) {
-		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], clnt))) < 0) {
-			uda1341_free(clnt);
-			return err;
-		}
-	}
-
-	if ((err = snd_device_new(card, SNDRV_DEV_CODEC, clnt, &ops)) < 0) {
-		uda1341_free(clnt);
-		return err;
-	}
-
-	*clntp = clnt;
-	strcpy(card->mixername, "UDA1341TS Mixer");
-	((struct uda1341 *)clnt->driver_data)->card = card;
-        
-	snd_uda1341_proc_init(card, clnt);
-        
-	return 0;
-}
-
-/* }}} */
-
-/* {{{ L3 operations */
-
-static int uda1341_attach(struct l3_client *clnt)
-{
-	struct uda1341 *uda;
-
-	uda = kzalloc(sizeof(*uda), 0, GFP_KERNEL);
-	if (!uda)
-		return -ENOMEM;
-
-	/* init fixed parts of my copy of registers */
-	uda->regs[stat0]   = STAT0;
-	uda->regs[stat1]   = STAT1;
-
-	uda->regs[data0_0] = DATA0_0;
-	uda->regs[data0_1] = DATA0_1;
-	uda->regs[data0_2] = DATA0_2;
-
-	uda->write = snd_uda1341_codec_write;
-	uda->read = snd_uda1341_codec_read;
-  
-	spin_lock_init(&uda->reg_lock);
-        
-	clnt->driver_data = uda;
-	return 0;
-}
-
-static void uda1341_detach(struct l3_client *clnt)
-{
-	kfree(clnt->driver_data);
-}
-
-static int
-uda1341_command(struct l3_client *clnt, int cmd, void *arg)
-{
-	if (cmd != CMD_READ_REG)
-		return snd_uda1341_cfg_write(clnt, cmd, (int) arg, FLUSH);
-
-	return snd_uda1341_codec_read(clnt, (int) arg);
-}
-
-static int uda1341_open(struct l3_client *clnt)
-{
-	struct uda1341 *uda = clnt->driver_data;
-
-	uda->active = 1;
-
-	/* init default configuration */
-	snd_uda1341_cfg_write(clnt, CMD_RESET, 0, REGS_ONLY);
-	snd_uda1341_cfg_write(clnt, CMD_FS, F256, FLUSH);       // unknown state after reset
-	snd_uda1341_cfg_write(clnt, CMD_FORMAT, LSB16, FLUSH);  // unknown state after reset
-	snd_uda1341_cfg_write(clnt, CMD_OGAIN, ON, FLUSH);      // default off after reset
-	snd_uda1341_cfg_write(clnt, CMD_IGAIN, ON, FLUSH);      // default off after reset
-	snd_uda1341_cfg_write(clnt, CMD_DAC, ON, FLUSH);	// ??? default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_ADC, ON, FLUSH);	// ??? default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_VOLUME, 20, FLUSH);     // default 0dB after reset
-	snd_uda1341_cfg_write(clnt, CMD_BASS, 0, REGS_ONLY);    // default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_TREBBLE, 0, REGS_ONLY); // default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_PEAK, AFTER, REGS_ONLY);// default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_DEEMP, NONE, REGS_ONLY);// default value after reset
-	//at this moment should be QMUTED by h3600_audio_init
-	snd_uda1341_cfg_write(clnt, CMD_MUTE, OFF, REGS_ONLY);  // default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_FILTER, MAX, FLUSH);    // defaul flat after reset
-	snd_uda1341_cfg_write(clnt, CMD_CH1, 31, FLUSH);        // default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_CH2, 4, FLUSH);         // default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_MIC, 4, FLUSH);         // default 0dB after reset
-	snd_uda1341_cfg_write(clnt, CMD_MIXER, MIXER, FLUSH);   // default doub.dif.mode          
-	snd_uda1341_cfg_write(clnt, CMD_AGC, OFF, FLUSH);       // default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_IG, 0, FLUSH);          // unknown state after reset
-	snd_uda1341_cfg_write(clnt, CMD_AGC_TIME, 0, FLUSH);    // default value after reset
-	snd_uda1341_cfg_write(clnt, CMD_AGC_LEVEL, 0, FLUSH);   // default value after reset
-
-	return 0;
-}
-
-static void uda1341_close(struct l3_client *clnt)
-{
-	struct uda1341 *uda = clnt->driver_data;
-
-	uda->active = 0;
-}
-
-/* }}} */
-
-/* {{{ Module and L3 initialization */
-
-static struct l3_ops uda1341_ops = {
-	.open =		uda1341_open,
-	.command =	uda1341_command,
-	.close =	uda1341_close,
-};
-
-static struct l3_driver uda1341_driver = {
-	.name =		UDA1341_ALSA_NAME,
-	.attach_client = uda1341_attach,
-	.detach_client = uda1341_detach,
-	.ops =		&uda1341_ops,
-	.owner =	THIS_MODULE,
-};
-
-static int __init uda1341_init(void)
-{
-	return l3_add_driver(&uda1341_driver);
-}
-
-static void __exit uda1341_exit(void)
-{
-	l3_del_driver(&uda1341_driver);
-}
-
-module_init(uda1341_init);
-module_exit(uda1341_exit);
-
-MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Philips UDA1341 CODEC driver for ALSA");
-MODULE_SUPPORTED_DEVICE("{{UDA1341,UDA1341TS}}");
-
-EXPORT_SYMBOL(snd_chip_uda1341_mixer_new);
-
-/* }}} */
-
-/*
- * Local variables:
- * indent-tabs-mode: t
- * End:
- */
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index ce0aa04..c5c9a92 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -56,8 +56,8 @@
 	  Say Y here to include support for AD1848 (Analog Devices) or
 	  CS4248 (Cirrus Logic - Crystal Semiconductors) chips.
 	  
-	  For newer chips from Cirrus Logic, use the CS4231, CS4232 or
-	  CS4236+ drivers.
+	  For newer chips from Cirrus Logic, use the CS4231 or CS4232+
+	  drivers.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-ad1848.
@@ -94,6 +94,8 @@
 	tristate "C-Media CMI8330"
 	select SND_WSS_LIB
 	select SND_SB16_DSP
+	select SND_OPL3_LIB
+	select SND_MPU401_UART
 	help
 	  Say Y here to include support for soundcards based on the
 	  C-Media CMI8330 chip.
@@ -112,26 +114,15 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-cs4231.
 
-config SND_CS4232
-	tristate "Generic Cirrus Logic CS4232 driver"
-	select SND_OPL3_LIB
-	select SND_MPU401_UART
-	select SND_WSS_LIB
-	help
-	  Say Y here to include support for CS4232 chips from Cirrus
-	  Logic - Crystal Semiconductors.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called snd-cs4232.
-
 config SND_CS4236
-	tristate "Generic Cirrus Logic CS4236+ driver"
+	tristate "Generic Cirrus Logic CS4232/CS4236+ driver"
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_WSS_LIB
 	help
-	  Say Y to include support for CS4235,CS4236,CS4237B,CS4238B,
-	  CS4239 chips from Cirrus Logic - Crystal Semiconductors.
+	  Say Y to include support for CS4232,CS4235,CS4236,CS4237B,
+	  CS4238B,CS4239 chips from Cirrus Logic - Crystal
+	  Semiconductors.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-cs4236.
@@ -377,14 +368,17 @@
 	  will be called snd-sgalaxy.
 
 config SND_SSCAPE
-	tristate "Ensoniq SoundScape PnP driver"
+	tristate "Ensoniq SoundScape driver"
 	select SND_HWDEP
 	select SND_MPU401_UART
 	select SND_WSS_LIB
 	help
-	  Say Y here to include support for Ensoniq SoundScape PnP
+	  Say Y here to include support for Ensoniq SoundScape 
 	  soundcards.
 
+	  The PCM audio is supported on SoundScape Classic, Elite, PnP
+	  and VIVO cards. The MIDI support is very experimental.
+
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-sscape.
 
@@ -411,5 +405,36 @@
 	  you need to install the firmware files from the
 	  alsa-firmware package.
 
+config SND_MSND_PINNACLE
+	tristate "Turtle Beach MultiSound Pinnacle/Fiji driver"
+	depends on X86 && EXPERIMENTAL
+	select FW_LOADER
+	select SND_MPU401_UART
+	select SND_PCM
+	help
+	  Say Y to include support for Turtle Beach MultiSound Pinnacle/
+	  Fiji soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-msnd-pinnacle.
+
+config SND_MSND_CLASSIC
+	tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
+	depends on X86 && EXPERIMENTAL
+	select FW_LOADER
+	select SND_MPU401_UART
+	select SND_PCM
+	help
+	  Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
+	  Monterey (not for the Pinnacle or Fiji).
+
+	  See <file:Documentation/sound/oss/MultiSound> for important information
+	  about this driver.  Note that it has been discontinued, but the
+	  Voyetra Turtle Beach knowledge base entry for it is still available
+	  at <http://www.turtlebeach.com/site/kb_ftp/790.asp>.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-msnd-classic.
+
 endif	# SND_ISA
 
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index 63af13d..b906b9a 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -26,5 +26,5 @@
 obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o
 obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o
 
-obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ opti9xx/ \
+obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ msnd/ opti9xx/ \
 		     sb/ wavefront/ wss/
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 7752424..bbcbf92 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -156,10 +156,12 @@
 	struct snd_card_ad1816a *acard;
 	struct snd_ad1816a *chip;
 	struct snd_opl3 *opl3;
+	struct snd_timer *timer;
 
-	if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-				 sizeof(struct snd_card_ad1816a))) == NULL)
-		return -ENOMEM;
+	error = snd_card_create(index[dev], id[dev], THIS_MODULE,
+				sizeof(struct snd_card_ad1816a), &card);
+	if (error < 0)
+		return error;
 	acard = (struct snd_card_ad1816a *)card->private_data;
 
 	if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) {
@@ -194,6 +196,12 @@
 		return error;
 	}
 
+	error = snd_ad1816a_timer(chip, 0, &timer);
+	if (error < 0) {
+		snd_card_free(card);
+		return error;
+	}
+
 	if (mpu_port[dev] > 0) {
 		if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
 					mpu_port[dev], 0, mpu_irq[dev], IRQF_DISABLED,
@@ -207,11 +215,8 @@
 				    OPL3_HW_AUTO, 0, &opl3) < 0) {
 			printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2);
 		} else {
-			if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) {
-				snd_card_free(card);
-				return error;
-			}
-			if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
+			error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
+			if (error < 0) {
 				snd_card_free(card);
 				return error;
 			}
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 3bfca7c..05aef8b 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -37,7 +37,7 @@
 		if (inb(AD1816A_REG(AD1816A_CHIP_STATUS)) & AD1816A_READY)
 			return 0;
 
-	snd_printk("chip busy.\n");
+	snd_printk(KERN_WARNING "chip busy.\n");
 	return -EBUSY;
 }
 
@@ -196,7 +196,7 @@
 		spin_unlock(&chip->lock);
 		break;
 	default:
-		snd_printk("invalid trigger mode 0x%x.\n", what);
+		snd_printk(KERN_WARNING "invalid trigger mode 0x%x.\n", what);
 		error = -EINVAL;
 	}
 
@@ -377,7 +377,6 @@
 	.fifo_size =		0,
 };
 
-#if 0 /* not used now */
 static int snd_ad1816a_timer_close(struct snd_timer *timer)
 {
 	struct snd_ad1816a *chip = snd_timer_chip(timer);
@@ -442,8 +441,6 @@
 	.start =	snd_ad1816a_timer_start,
 	.stop =		snd_ad1816a_timer_stop,
 };
-#endif /* not used now */
-
 
 static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream)
 {
@@ -568,7 +565,7 @@
 	case AD1816A_HW_AD1815:	return "AD1815";
 	case AD1816A_HW_AD18MAX10: return "AD18max10";
 	default:
-		snd_printk("Unknown chip version %d:%d.\n",
+		snd_printk(KERN_WARNING "Unknown chip version %d:%d.\n",
 			chip->version, chip->hardware);
 		return "AD1816A - unknown";
 	}
@@ -687,7 +684,6 @@
 	return 0;
 }
 
-#if 0 /* not used now */
 int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer)
 {
 	struct snd_timer *timer;
@@ -709,7 +705,6 @@
 		*rtimer = timer;
 	return 0;
 }
-#endif /* not used now */
 
 /*
  *
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 223a6c0..4beeb6f 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -91,9 +91,9 @@
 	struct snd_pcm *pcm;
 	int error;
 
-	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
-	if (!card)
-		return -EINVAL;
+	error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card);
+	if (error < 0)
+		return error;
 
 	error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1,
 			thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT,
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
index 374b717..7465ae0 100644
--- a/sound/isa/adlib.c
+++ b/sound/isa/adlib.c
@@ -53,10 +53,10 @@
 	struct snd_opl3 *opl3;
 	int error;
 
-	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
-	if (!card) {
+	error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card);
+	if (error < 0) {
 		dev_err(dev, "could not create card\n");
-		return -EINVAL;
+		return error;
 	}
 
 	card->private_data = request_region(port[n], 4, CRD_NAME);
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index f1ce30f..5fd52e4 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -163,9 +163,10 @@
 	struct snd_card_als100 *acard;
 	struct snd_opl3 *opl3;
 
-	if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-				 sizeof(struct snd_card_als100))) == NULL)
-		return -ENOMEM;
+	error = snd_card_create(index[dev], id[dev], THIS_MODULE,
+				sizeof(struct snd_card_als100), &card);
+	if (error < 0)
+		return error;
 	acard = card->private_data;
 
 	if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) {
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index 3e74d1a..f7aa637 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -184,9 +184,10 @@
 	struct snd_wss *chip;
 	struct snd_opl3 *opl3;
 
-	if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-				 sizeof(struct snd_card_azt2320))) == NULL)
-		return -ENOMEM;
+	error = snd_card_create(index[dev], id[dev], THIS_MODULE,
+				sizeof(struct snd_card_azt2320), &card);
+	if (error < 0)
+		return error;
 	acard = (struct snd_card_azt2320 *)card->private_data;
 
 	if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) {
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index e49aec7..de83608 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -31,11 +31,11 @@
  *  To quickly load the module,
  *
  *  modprobe -a snd-cmi8330 sbport=0x220 sbirq=5 sbdma8=1
- *    sbdma16=5 wssport=0x530 wssirq=11 wssdma=0
+ *    sbdma16=5 wssport=0x530 wssirq=11 wssdma=0 fmport=0x388
  *
  *  This card has two mixers and two PCM devices.  I've cheesed it such
  *  that recording and playback can be done through the same device.
- *  The driver "magically" routes the capturing to the AD1848 codec,
+ *  The driver "magically" routes the capturing to the CMI8330 codec,
  *  and playback to the SB16 codec.  This allows for full-duplex mode
  *  to some extent.
  *  The utilities in alsa-utils are aware of both devices, so passing
@@ -51,6 +51,8 @@
 #include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/wss.h>
+#include <sound/opl3.h>
+#include <sound/mpu401.h>
 #include <sound/sb.h>
 #include <sound/initval.h>
 
@@ -79,6 +81,9 @@
 static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
 static int wssirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
 static int wssdma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
+static long fmport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static long mpuport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static int mpuirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard.");
@@ -107,6 +112,12 @@
 module_param_array(wssdma, int, NULL, 0444);
 MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
 
+module_param_array(fmport, long, NULL, 0444);
+MODULE_PARM_DESC(fmport, "FM port # for CMI8330 driver.");
+module_param_array(mpuport, long, NULL, 0444);
+MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330 driver.");
+module_param_array(mpuirq, int, NULL, 0444);
+MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330 MPU-401 port.");
 #ifdef CONFIG_PNP
 static int isa_registered;
 static int pnp_registered;
@@ -149,6 +160,7 @@
 #ifdef CONFIG_PNP
 	struct pnp_dev *cap;
 	struct pnp_dev *play;
+	struct pnp_dev *mpu;
 #endif
 	struct snd_card *card;
 	struct snd_wss *wss;
@@ -165,7 +177,7 @@
 #ifdef CONFIG_PNP
 
 static struct pnp_card_device_id snd_cmi8330_pnpids[] = {
-	{ .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" } } },
+	{ .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } } },
 	{ .id = "" }
 };
 
@@ -219,8 +231,10 @@
 		CMI8330_RMUX3D, 5, 1, 1),
 WSS_SINGLE("PC Speaker Playback Volume", 0,
 		CMI8330_OUTPUTVOL, 3, 3, 0),
-WSS_SINGLE("FM Playback Switch", 0,
-		CMI8330_RECMUX, 3, 1, 1),
+WSS_DOUBLE("FM Playback Switch", 0,
+		CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("FM Playback Volume", 0,
+		CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
 WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0,
 		CMI8330_RMUX3D, 7, 1, 1),
 WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0,
@@ -323,16 +337,21 @@
 	if (acard->play == NULL)
 		return -EBUSY;
 
+	acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL);
+	if (acard->play == NULL)
+		return -EBUSY;
+
 	pdev = acard->cap;
 
 	err = pnp_activate_dev(pdev);
 	if (err < 0) {
-		snd_printk(KERN_ERR "CMI8330/C3D (AD1848) PnP configure failure\n");
+		snd_printk(KERN_ERR "CMI8330/C3D PnP configure failure\n");
 		return -EBUSY;
 	}
 	wssport[dev] = pnp_port_start(pdev, 0);
 	wssdma[dev] = pnp_dma(pdev, 0);
 	wssirq[dev] = pnp_irq(pdev, 0);
+	fmport[dev] = pnp_port_start(pdev, 1);
 
 	/* allocate SB16 resources */
 	pdev = acard->play;
@@ -347,6 +366,17 @@
 	sbdma16[dev] = pnp_dma(pdev, 1);
 	sbirq[dev] = pnp_irq(pdev, 0);
 
+	/* allocate MPU-401 resources */
+	pdev = acard->mpu;
+
+	err = pnp_activate_dev(pdev);
+	if (err < 0) {
+		snd_printk(KERN_ERR
+			   "CMI8330/C3D (MPU-401) PnP configure failure\n");
+		return -EBUSY;
+	}
+	mpuport[dev] = pnp_port_start(pdev, 0);
+	mpuirq[dev] = pnp_irq(pdev, 0);
 	return 0;
 }
 #endif
@@ -467,26 +497,29 @@
 
 #define PFX	"cmi8330: "
 
-static struct snd_card *snd_cmi8330_card_new(int dev)
+static int snd_cmi8330_card_new(int dev, struct snd_card **cardp)
 {
 	struct snd_card *card;
 	struct snd_cmi8330 *acard;
+	int err;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_cmi8330));
-	if (card == NULL) {
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_cmi8330), &card);
+	if (err < 0) {
 		snd_printk(KERN_ERR PFX "could not get a new card\n");
-		return NULL;
+		return err;
 	}
 	acard = card->private_data;
 	acard->card = card;
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
 {
 	struct snd_cmi8330 *acard;
 	int i, err;
+	struct snd_opl3 *opl3;
 
 	acard = card->private_data;
 	err = snd_wss_create(card, wssport[dev] + 4, -1,
@@ -494,11 +527,11 @@
 			     wssdma[dev], -1,
 			     WSS_HW_DETECT, 0, &acard->wss);
 	if (err < 0) {
-		snd_printk(KERN_ERR PFX "(AD1848) device busy??\n");
+		snd_printk(KERN_ERR PFX "(CMI8330) device busy??\n");
 		return err;
 	}
 	if (acard->wss->hardware != WSS_HW_CMI8330) {
-		snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n");
+		snd_printk(KERN_ERR PFX "(CMI8330) not found during probe\n");
 		return -ENODEV;
 	}
 
@@ -530,6 +563,27 @@
 		snd_printk(KERN_ERR PFX "failed to create pcms\n");
 		return err;
 	}
+	if (fmport[dev] != SNDRV_AUTO_PORT) {
+		if (snd_opl3_create(card,
+				    fmport[dev], fmport[dev] + 2,
+				    OPL3_HW_AUTO, 0, &opl3) < 0) {
+			snd_printk(KERN_ERR PFX
+				   "no OPL device at 0x%lx-0x%lx ?\n",
+				   fmport[dev], fmport[dev] + 2);
+		} else {
+			err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
+			if (err < 0)
+				return err;
+		}
+	}
+
+	if (mpuport[dev] != SNDRV_AUTO_PORT) {
+		if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
+					mpuport[dev], 0, mpuirq[dev],
+					IRQF_DISABLED, NULL) < 0)
+			printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n",
+				mpuport[dev]);
+	}
 
 	strcpy(card->driver, "CMI8330/C3D");
 	strcpy(card->shortname, "C-Media CMI8330/C3D");
@@ -564,9 +618,9 @@
 	struct snd_card *card;
 	int err;
 
-	card = snd_cmi8330_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_cmi8330_card_new(dev, &card);
+	if (err < 0)
+		return err;
 	snd_card_set_dev(card, pdev);
 	if ((err = snd_cmi8330_probe(card, dev)) < 0) {
 		snd_card_free(card);
@@ -628,9 +682,9 @@
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
 			       
-	card = snd_cmi8330_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	res = snd_cmi8330_card_new(dev, &card);
+	if (res < 0)
+		return res;
 	if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) {
 		snd_printk(KERN_ERR PFX "PnP detection failed\n");
 		snd_card_free(card);
diff --git a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile
index 5870ca2..6d397e8 100644
--- a/sound/isa/cs423x/Makefile
+++ b/sound/isa/cs423x/Makefile
@@ -3,13 +3,11 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
 #
 
-snd-cs4236-lib-objs := cs4236_lib.o
 snd-cs4231-objs := cs4231.o
-snd-cs4232-objs := cs4232.o
-snd-cs4236-objs := cs4236.o
+snd-cs4236-objs := cs4236.o cs4236_lib.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_CS4231) += snd-cs4231.o
-obj-$(CONFIG_SND_CS4232) += snd-cs4232.o
-obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o
+obj-$(CONFIG_SND_CS4236) += snd-cs4236.o
+
 
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index f019d44..cb9153e 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -95,9 +95,9 @@
 	struct snd_pcm *pcm;
 	int error;
 
-	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
-	if (!card)
-		return -EINVAL;
+	error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card);
+	if (error < 0)
+		return error;
 
 	error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
 			WSS_HW_DETECT, 0, &chip);
diff --git a/sound/isa/cs423x/cs4232.c b/sound/isa/cs423x/cs4232.c
deleted file mode 100644
index 9fad2e6..0000000
--- a/sound/isa/cs423x/cs4232.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define CS4232
-#include "cs4236.c"
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 019c940..a076a6c 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -33,17 +33,14 @@
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_LICENSE("GPL");
-#ifdef CS4232
-MODULE_DESCRIPTION("Cirrus Logic CS4232");
+MODULE_DESCRIPTION("Cirrus Logic CS4232-9");
 MODULE_SUPPORTED_DEVICE("{{Turtle Beach,TBS-2000},"
 		"{Turtle Beach,Tropez Plus},"
 		"{SIC CrystalWave 32},"
 		"{Hewlett Packard,Omnibook 5500},"
 		"{TerraTec,Maestro 32/96},"
-		"{Philips,PCA70PS}}");
-#else
-MODULE_DESCRIPTION("Cirrus Logic CS4235-9");
-MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235},"
+		"{Philips,PCA70PS}},"
+		"{{Crystal Semiconductors,CS4235},"
 		"{Crystal Semiconductors,CS4236},"
 		"{Crystal Semiconductors,CS4237},"
 		"{Crystal Semiconductors,CS4238},"
@@ -70,15 +67,11 @@
 		"{Typhoon Soundsystem,CS4236B},"
 		"{Turtle Beach,Malibu},"
 		"{Unknown,Digital PC 5000 Onboard}}");
-#endif
 
-#ifdef CS4232
-#define IDENT "CS4232"
-#define DEV_NAME "cs4232"
-#else
-#define IDENT "CS4236+"
-#define DEV_NAME "cs4236"
-#endif
+MODULE_ALIAS("snd_cs4232");
+
+#define IDENT "CS4232+"
+#define DEV_NAME "cs4232+"
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -128,9 +121,7 @@
 #ifdef CONFIG_PNP
 static int isa_registered;
 static int pnpc_registered;
-#ifdef CS4232
 static int pnp_registered;
-#endif
 #endif /* CONFIG_PNP */
 
 struct snd_card_cs4236 {
@@ -145,11 +136,10 @@
 
 #ifdef CONFIG_PNP
 
-#ifdef CS4232
 /*
  * PNP BIOS
  */
-static const struct pnp_device_id snd_cs4232_pnpbiosids[] = {
+static const struct pnp_device_id snd_cs423x_pnpbiosids[] = {
 	{ .id = "CSC0100" },
 	{ .id = "CSC0000" },
 	/* Guillemot Turtlebeach something appears to be cs4232 compatible
@@ -157,10 +147,8 @@
 	{ .id = "GIM0100" },
 	{ .id = "" }
 };
-MODULE_DEVICE_TABLE(pnp, snd_cs4232_pnpbiosids);
-#endif /* CS4232 */
+MODULE_DEVICE_TABLE(pnp, snd_cs423x_pnpbiosids);
 
-#ifdef CS4232
 #define CS423X_ISAPNP_DRIVER	"cs4232_isapnp"
 static struct pnp_card_device_id snd_cs423x_pnpids[] = {
 	/* Philips PCA70PS */
@@ -179,12 +167,6 @@
 	{ .id = "CSCf032", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
 	/* Netfinity 3000 on-board soundcard */
 	{ .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC010f" } } },
-	/* --- */
-	{ .id = "" }	/* end */
-};
-#else /* CS4236 */
-#define CS423X_ISAPNP_DRIVER	"cs4236_isapnp"
-static struct pnp_card_device_id snd_cs423x_pnpids[] = {
 	/* Intel Marlin Spike Motherboard - CS4235 */
 	{ .id = "CSC0225", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
 	/* Intel Marlin Spike Motherboard (#2) - CS4235 */
@@ -266,7 +248,6 @@
 	/* --- */
 	{ .id = "" }	/* end */
 };
-#endif
 
 MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids);
 
@@ -323,17 +304,19 @@
 	return 0;
 }
 
-#ifdef CS4232
-static int __devinit snd_card_cs4232_pnp(int dev, struct snd_card_cs4236 *acard,
-					 struct pnp_dev *pdev)
+static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
+					 struct pnp_dev *pdev,
+					 struct pnp_dev *cdev)
 {
 	acard->wss = pdev;
 	if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0)
 		return -EBUSY;
-	cport[dev] = -1;
+	if (cdev)
+		cport[dev] = pnp_port_start(cdev, 0);
+	else
+		cport[dev] = -1;
 	return 0;
 }
-#endif
 
 static int __devinit snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
 					  struct pnp_card_link *card,
@@ -382,16 +365,18 @@
 	release_and_free_resource(acard->res_sb_port);
 }
 
-static struct snd_card *snd_cs423x_card_new(int dev)
+static int snd_cs423x_card_new(int dev, struct snd_card **cardp)
 {
 	struct snd_card *card;
+	int err;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_card_cs4236));
-	if (card == NULL)
-		return NULL;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_card_cs4236), &card);
+	if (err < 0)
+		return err;
 	card->private_free = snd_card_cs4236_free;
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
@@ -409,40 +394,39 @@
 			return -EBUSY;
 		}
 
-#ifdef CS4232
 	err = snd_wss_create(card, port[dev], cport[dev],
 			     irq[dev],
 			     dma1[dev], dma2[dev],
-			     WSS_HW_DETECT, 0, &chip);
+			     WSS_HW_DETECT3, 0, &chip);
 	if (err < 0)
 		return err;
-	acard->chip = chip;
+	if (chip->hardware & WSS_HW_CS4236B_MASK) {
+		snd_wss_free(chip);
+		err = snd_cs4236_create(card,
+					port[dev], cport[dev],
+					irq[dev], dma1[dev], dma2[dev],
+					WSS_HW_DETECT, 0, &chip);
+		if (err < 0)
+			return err;
+		acard->chip = chip;
 
-	err = snd_wss_pcm(chip, 0, &pcm);
-	if (err < 0)
-		return err;
+		err = snd_cs4236_pcm(chip, 0, &pcm);
+		if (err < 0)
+			return err;
 
-	err = snd_wss_mixer(chip);
-	if (err < 0)
-		return err;
+		err = snd_cs4236_mixer(chip);
+		if (err < 0)
+			return err;
+	} else {
+		acard->chip = chip;
+		err = snd_wss_pcm(chip, 0, &pcm);
+		if (err < 0)
+			return err;
 
-#else /* CS4236 */
-	err = snd_cs4236_create(card,
-				port[dev], cport[dev],
-				irq[dev], dma1[dev], dma2[dev],
-				WSS_HW_DETECT, 0, &chip);
-	if (err < 0)
-		return err;
-	acard->chip = chip;
-
-	err = snd_cs4236_pcm(chip, 0, &pcm);
-	if (err < 0)
-		return err;
-
-	err = snd_cs4236_mixer(chip);
-	if (err < 0)
-		return err;
-#endif
+		err = snd_wss_mixer(chip);
+		if (err < 0)
+			return err;
+	}
 	strcpy(card->driver, pcm->name);
 	strcpy(card->shortname, pcm->name);
 	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i",
@@ -512,9 +496,9 @@
 	struct snd_card *card;
 	int err;
 
-	card = snd_cs423x_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_cs423x_card_new(dev, &card);
+	if (err < 0)
+		return err;
 	snd_card_set_dev(card, pdev);
 	if ((err = snd_cs423x_probe(card, dev)) < 0) {
 		snd_card_free(card);
@@ -577,13 +561,14 @@
 
 
 #ifdef CONFIG_PNP
-#ifdef CS4232
-static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev,
+static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
 					       const struct pnp_device_id *id)
 {
 	static int dev;
 	int err;
 	struct snd_card *card;
+	struct pnp_dev *cdev;
+	char cid[PNP_ID_LEN];
 
 	if (pnp_device_is_isapnp(pdev))
 		return -ENOENT;	/* we have another procedure - card */
@@ -594,10 +579,19 @@
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
 
-	card = snd_cs423x_card_new(dev);
-	if (! card)
-		return -ENOMEM;
-	if ((err = snd_card_cs4232_pnp(dev, card->private_data, pdev)) < 0) {
+	/* prepare second id */
+	strcpy(cid, pdev->id[0].id);
+	cid[5] = '1';
+	cdev = NULL;
+	list_for_each_entry(cdev, &(pdev->protocol->devices), protocol_list) {
+		if (!strcmp(cdev->id[0].id, cid))
+			break;
+	}
+	err = snd_cs423x_card_new(dev, &card);
+	if (err < 0)
+		return err;
+	err = snd_card_cs423x_pnp(dev, card->private_data, pdev, cdev);
+	if (err < 0) {
 		printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n");
 		snd_card_free(card);
 		return err;
@@ -612,35 +606,34 @@
 	return 0;
 }
 
-static void __devexit snd_cs4232_pnp_remove(struct pnp_dev * pdev)
+static void __devexit snd_cs423x_pnp_remove(struct pnp_dev *pdev)
 {
 	snd_card_free(pnp_get_drvdata(pdev));
 	pnp_set_drvdata(pdev, NULL);
 }
 
 #ifdef CONFIG_PM
-static int snd_cs4232_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
+static int snd_cs423x_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
 {
 	return snd_cs423x_suspend(pnp_get_drvdata(pdev));
 }
 
-static int snd_cs4232_pnp_resume(struct pnp_dev *pdev)
+static int snd_cs423x_pnp_resume(struct pnp_dev *pdev)
 {
 	return snd_cs423x_resume(pnp_get_drvdata(pdev));
 }
 #endif
 
-static struct pnp_driver cs4232_pnp_driver = {
-	.name = "cs4232-pnpbios",
-	.id_table = snd_cs4232_pnpbiosids,
-	.probe = snd_cs4232_pnpbios_detect,
-	.remove = __devexit_p(snd_cs4232_pnp_remove),
+static struct pnp_driver cs423x_pnp_driver = {
+	.name = "cs423x-pnpbios",
+	.id_table = snd_cs423x_pnpbiosids,
+	.probe = snd_cs423x_pnpbios_detect,
+	.remove = __devexit_p(snd_cs423x_pnp_remove),
 #ifdef CONFIG_PM
-	.suspend	= snd_cs4232_pnp_suspend,
-	.resume		= snd_cs4232_pnp_resume,
+	.suspend	= snd_cs423x_pnp_suspend,
+	.resume		= snd_cs423x_pnp_resume,
 #endif
 };
-#endif /* CS4232 */
 
 static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
 					    const struct pnp_card_device_id *pid)
@@ -656,9 +649,9 @@
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
 
-	card = snd_cs423x_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	res = snd_cs423x_card_new(dev, &card);
+	if (res < 0)
+		return res;
 	if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) {
 		printk(KERN_ERR "isapnp detection failed and probing for " IDENT
 		       " is not supported\n");
@@ -714,18 +707,14 @@
 #ifdef CONFIG_PNP
 	if (!err)
 		isa_registered = 1;
-#ifdef CS4232
-	err = pnp_register_driver(&cs4232_pnp_driver);
+	err = pnp_register_driver(&cs423x_pnp_driver);
 	if (!err)
 		pnp_registered = 1;
-#endif
 	err = pnp_register_card_driver(&cs423x_pnpc_driver);
 	if (!err)
 		pnpc_registered = 1;
-#ifdef CS4232
 	if (pnp_registered)
 		err = 0;
-#endif
 	if (isa_registered)
 		err = 0;
 #endif
@@ -737,10 +726,8 @@
 #ifdef CONFIG_PNP
 	if (pnpc_registered)
 		pnp_unregister_card_driver(&cs423x_pnpc_driver);
-#ifdef CS4232
 	if (pnp_registered)
-		pnp_unregister_driver(&cs4232_pnp_driver);
-#endif
+		pnp_unregister_driver(&cs423x_pnp_driver);
 	if (isa_registered)
 #endif
 		isa_unregister_driver(&cs423x_isa_driver);
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index 6a85fdc..38835f3 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -88,10 +88,6 @@
 #include <sound/wss.h>
 #include <sound/asoundef.h>
 
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips");
-MODULE_LICENSE("GPL");
-
 /*
  *
  */
@@ -286,7 +282,8 @@
 	if (hardware == WSS_HW_DETECT)
 		hardware = WSS_HW_DETECT3;
 	if (cport < 0x100) {
-		snd_printk("please, specify control port for CS4236+ chips\n");
+		snd_printk(KERN_ERR "please, specify control port "
+			   "for CS4236+ chips\n");
 		return -ENODEV;
 	}
 	err = snd_wss_create(card, port, cport,
@@ -295,7 +292,8 @@
 		return err;
 
 	if (!(chip->hardware & WSS_HW_CS4236B_MASK)) {
-	        snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%x\n",chip->hardware);
+		snd_printk(KERN_ERR "CS4236+: MODE3 and extended registers "
+			   "not available, hardware=0x%x\n", chip->hardware);
 		snd_device_free(card, chip);
 		return -ENODEV;
 	}
@@ -303,16 +301,19 @@
 	{
 		int idx;
 		for (idx = 0; idx < 8; idx++)
-			snd_printk("CD%i = 0x%x\n", idx, inb(chip->cport + idx));
+			snd_printk(KERN_DEBUG "CD%i = 0x%x\n",
+				   idx, inb(chip->cport + idx));
 		for (idx = 0; idx < 9; idx++)
-			snd_printk("C%i = 0x%x\n", idx, snd_cs4236_ctrl_in(chip, idx));
+			snd_printk(KERN_DEBUG "C%i = 0x%x\n",
+				   idx, snd_cs4236_ctrl_in(chip, idx));
 	}
 #endif
 	ver1 = snd_cs4236_ctrl_in(chip, 1);
 	ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION);
 	snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", cport, ver1, ver2);
 	if (ver1 != ver2) {
-		snd_printk("CS4236+ chip detected, but control port 0x%lx is not valid\n", cport);
+		snd_printk(KERN_ERR "CS4236+ chip detected, but "
+			   "control port 0x%lx is not valid\n", cport);
 		snd_device_free(card, chip);
 		return -ENODEV;
 	}
@@ -883,7 +884,8 @@
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0;
 #if 0
-	printk("get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
+	printk(KERN_DEBUG "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, "
+	       "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
 			snd_wss_in(chip, CS4231_ALT_FEATURE_1),
 			snd_cs4236_ctrl_in(chip, 3),
 			snd_cs4236_ctrl_in(chip, 4),
@@ -920,7 +922,8 @@
 	mutex_unlock(&chip->mce_mutex);
 
 #if 0
-	printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
+	printk(KERN_DEBUG "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, "
+	       "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
 			snd_wss_in(chip, CS4231_ALT_FEATURE_1),
 			snd_cs4236_ctrl_in(chip, 3),
 			snd_cs4236_ctrl_in(chip, 4),
@@ -1015,23 +1018,3 @@
 	}
 	return 0;
 }
-
-EXPORT_SYMBOL(snd_cs4236_create);
-EXPORT_SYMBOL(snd_cs4236_pcm);
-EXPORT_SYMBOL(snd_cs4236_mixer);
-
-/*
- *  INIT part
- */
-
-static int __init alsa_cs4236_init(void)
-{
-	return 0;
-}
-
-static void __exit alsa_cs4236_exit(void)
-{
-}
-
-module_init(alsa_cs4236_init)
-module_exit(alsa_cs4236_exit)
diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c
index a0242c3..80f5b1a 100644
--- a/sound/isa/dt019x.c
+++ b/sound/isa/dt019x.c
@@ -150,9 +150,10 @@
 	struct snd_card_dt019x *acard;
 	struct snd_opl3 *opl3;
 
-	if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-				 sizeof(struct snd_card_dt019x))) == NULL)
-		return -ENOMEM;
+	error = snd_card_create(index[dev], id[dev], THIS_MODULE,
+				sizeof(struct snd_card_dt019x), &card);
+	if (error < 0)
+		return error;
 	acard = card->private_data;
 
 	snd_card_set_dev(card, &pcard->card->dev);
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index b463771..442b081 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -49,6 +49,7 @@
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;	/* Enable this card */
 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* 0x220,0x240,0x260 */
+static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* Usually 0x388 */
 static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 5,7,9,10 */
 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 5,7,9,10 */
@@ -65,6 +66,8 @@
 module_param_array(mpu_port, long, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
 module_param_array(irq, int, NULL, 0444);
+module_param_array(fm_port, long, NULL, 0444);
+MODULE_PARM_DESC(fm_port, "FM port # for ES1688 driver.");
 MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
 module_param_array(mpu_irq, int, NULL, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
@@ -122,9 +125,9 @@
 	struct snd_pcm *pcm;
 	int error;
 
-	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
-	if (!card)
-		return -EINVAL;
+	error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card);
+	if (error < 0)
+		return error;
 
 	error = snd_es1688_legacy_create(card, dev, n, &chip);
 	if (error < 0)
@@ -143,13 +146,19 @@
 	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name,
 		chip->port, chip->irq, chip->dma8);
 
-	if (snd_opl3_create(card, chip->port, chip->port + 2,
-			OPL3_HW_OPL3, 0, &opl3) < 0)
-		dev_warn(dev, "opl3 not detected at 0x%lx\n", chip->port);
-	else {
-		error =	snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-		if (error < 0)
-			goto out;
+	if (fm_port[n] == SNDRV_AUTO_PORT)
+		fm_port[n] = port[n];	/* share the same port */
+
+	if (fm_port[n] > 0) {
+		if (snd_opl3_create(card, fm_port[n], fm_port[n] + 2,
+				OPL3_HW_OPL3, 0, &opl3) < 0)
+			dev_warn(dev,
+				 "opl3 not detected at 0x%lx\n", fm_port[n]);
+		else {
+			error =	snd_opl3_hwdep_new(opl3, 0, 1, NULL);
+			if (error < 0)
+				goto out;
+		}
 	}
 
 	if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ &&
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 4fbb508..4c6e14f 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -45,7 +45,7 @@
 			return 1;
 		}
 #ifdef CONFIG_SND_DEBUG
-	printk("snd_es1688_dsp_command: timeout (0x%x)\n", val);
+	printk(KERN_DEBUG "snd_es1688_dsp_command: timeout (0x%x)\n", val);
 #endif
 	return 0;
 }
@@ -167,13 +167,16 @@
 	hw = ES1688_HW_AUTO;
 	switch (chip->version & 0xfff0) {
 	case 0x4880:
-		snd_printk("[0x%lx] ESS: AudioDrive ES488 detected, but driver is in another place\n", chip->port);
+		snd_printk(KERN_ERR "[0x%lx] ESS: AudioDrive ES488 detected, "
+			   "but driver is in another place\n", chip->port);
 		return -ENODEV;
 	case 0x6880:
 		hw = (chip->version & 0x0f) >= 8 ? ES1688_HW_1688 : ES1688_HW_688;
 		break;
 	default:
-		snd_printk("[0x%lx] ESS: unknown AudioDrive chip with version 0x%x (Jazz16 soundcard?)\n", chip->port, chip->version);
+		snd_printk(KERN_ERR "[0x%lx] ESS: unknown AudioDrive chip "
+			   "with version 0x%x (Jazz16 soundcard?)\n",
+			   chip->port, chip->version);
 		return -ENODEV;
 	}
 
@@ -223,7 +226,7 @@
 		}
 	}
 #if 0
-	snd_printk("mpu cfg = 0x%x\n", cfg);
+	snd_printk(KERN_DEBUG "mpu cfg = 0x%x\n", cfg);
 #endif
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	snd_es1688_mixer_write(chip, 0x40, cfg);
@@ -237,7 +240,9 @@
 		cfg = 0xf0;	/* enable only DMA counter interrupt */
 		irq_bits = irqs[chip->irq & 0x0f];
 		if (irq_bits < 0) {
-			snd_printk("[0x%lx] ESS: bad IRQ %d for ES1688 chip!!\n", chip->port, chip->irq);
+			snd_printk(KERN_ERR "[0x%lx] ESS: bad IRQ %d "
+				   "for ES1688 chip!!\n",
+				   chip->port, chip->irq);
 #if 0
 			irq_bits = 0;
 			cfg = 0x10;
@@ -250,7 +255,8 @@
 		cfg = 0xf0;	/* extended mode DMA enable */
 		dma = chip->dma8;
 		if (dma > 3 || dma == 2) {
-			snd_printk("[0x%lx] ESS: bad DMA channel %d for ES1688 chip!!\n", chip->port, dma);
+			snd_printk(KERN_ERR "[0x%lx] ESS: bad DMA channel %d "
+				   "for ES1688 chip!!\n", chip->port, dma);
 #if 0
 			dma_bits = 0;
 			cfg = 0x00;	/* disable all DMA */
@@ -341,8 +347,9 @@
 		return -EINVAL;	/* something is wrong */
 	}
 #if 0
-	printk("trigger: val = 0x%x, value = 0x%x\n", val, value);
-	printk("trigger: pointer = 0x%x\n", snd_dma_pointer(chip->dma8, chip->dma_size));
+	printk(KERN_DEBUG "trigger: val = 0x%x, value = 0x%x\n", val, value);
+	printk(KERN_DEBUG "trigger: pointer = 0x%x\n",
+	       snd_dma_pointer(chip->dma8, chip->dma_size));
 #endif
 	snd_es1688_write(chip, 0xb8, (val & 0xf0) | value);
 	spin_unlock(&chip->reg_lock);
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 90498e4..8cfbff7 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -2125,10 +2125,10 @@
 #define is_isapnp_selected(dev)		0
 #endif
 
-static struct snd_card *snd_es18xx_card_new(int dev)
+static int snd_es18xx_card_new(int dev, struct snd_card **cardp)
 {
-	return snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_audiodrive));
+	return snd_card_create(index[dev], id[dev], THIS_MODULE,
+			       sizeof(struct snd_audiodrive), cardp);
 }
 
 static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
@@ -2197,9 +2197,9 @@
 	struct snd_card *card;
 	int err;
 
-	card = snd_es18xx_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_es18xx_card_new(dev, &card);
+	if (err < 0)
+		return err;
 	snd_card_set_dev(card, devptr);
 	if ((err = snd_audiodrive_probe(card, dev)) < 0) {
 		snd_card_free(card);
@@ -2303,9 +2303,9 @@
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
 
-	card = snd_es18xx_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_es18xx_card_new(dev, &card);
+	if (err < 0)
+		return err;
 	if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) {
 		snd_card_free(card);
 		return err;
@@ -2362,9 +2362,9 @@
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
 
-	card = snd_es18xx_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	res = snd_es18xx_card_new(dev, &card);
+	if (res < 0)
+		return res;
 
 	if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) {
 		snd_card_free(card);
diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c
index f45f611..36c27c8 100644
--- a/sound/isa/gus/gus_dma.c
+++ b/sound/isa/gus/gus_dma.c
@@ -45,7 +45,8 @@
 	unsigned char dma_cmd;
 	unsigned int address_high;
 
-	// snd_printk("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", addr, (long) buf, count);
+	snd_printdd("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n",
+		    addr, buf_addr, count);
 
 	if (gus->gf1.dma1 > 3) {
 		if (gus->gf1.enh_mode) {
@@ -77,7 +78,8 @@
 	snd_gf1_dma_ack(gus);
 	snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE);
 #if 0
-	snd_printk("address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", address << 1, count, dma_cmd);
+	snd_printk(KERN_DEBUG "address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n",
+		   address << 1, count, dma_cmd);
 #endif
 	spin_lock_irqsave(&gus->reg_lock, flags);
 	if (gus->gf1.enh_mode) {
@@ -142,7 +144,9 @@
 	snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd);
 	kfree(block);
 #if 0
-	printk("program dma (IRQ) - addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", addr, (long) buffer, count, cmd);
+	snd_printd(KERN_DEBUG "program dma (IRQ) - "
+		   "addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n",
+		   block->addr, block->buf_addr, block->count, block->cmd);
 #endif
 }
 
@@ -203,13 +207,16 @@
 	}
 	*block = *__block;
 	block->next = NULL;
-#if 0
-	printk("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", block->addr, (long) block->buffer, block->count, block->cmd);
-#endif
-#if 0
-	printk("gus->gf1.dma_data_pcm_last = 0x%lx\n", (long)gus->gf1.dma_data_pcm_last);
-	printk("gus->gf1.dma_data_pcm = 0x%lx\n", (long)gus->gf1.dma_data_pcm);
-#endif
+
+	snd_printdd("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n",
+		    block->addr, (long) block->buffer, block->count,
+		    block->cmd);
+
+	snd_printdd("gus->gf1.dma_data_pcm_last = 0x%lx\n",
+		    (long)gus->gf1.dma_data_pcm_last);
+	snd_printdd("gus->gf1.dma_data_pcm = 0x%lx\n",
+		    (long)gus->gf1.dma_data_pcm);
+
 	spin_lock_irqsave(&gus->dma_lock, flags);
 	if (synth) {
 		if (gus->gf1.dma_data_synth_last) {
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
index 041894d..2055aff 100644
--- a/sound/isa/gus/gus_irq.c
+++ b/sound/isa/gus/gus_irq.c
@@ -41,7 +41,7 @@
 	if (status == 0)
 		return IRQ_RETVAL(handled);
 	handled = 1;
-	// snd_printk("IRQ: status = 0x%x\n", status);
+	/* snd_printk(KERN_DEBUG "IRQ: status = 0x%x\n", status); */
 	if (status & 0x02) {
 		STAT_ADD(gus->gf1.interrupt_stat_midi_in);
 		if (gus->gf1.interrupt_handler_midi_in)
@@ -65,7 +65,9 @@
 				continue;	/* multi request */
 			already |= _current_;	/* mark request */
 #if 0
-			printk("voice = %i, voice_status = 0x%x, voice_verify = %i\n", voice, voice_status, inb(GUSP(gus, GF1PAGE)));
+			printk(KERN_DEBUG "voice = %i, voice_status = 0x%x, "
+			       "voice_verify = %i\n",
+			       voice, voice_status, inb(GUSP(gus, GF1PAGE)));
 #endif
 			pvoice = &gus->gf1.voices[voice]; 
 			if (pvoice->use) {
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 38510ae..edb11ee 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -82,7 +82,10 @@
 
 	count += offset & 31;
 	offset &= ~31;
-	// snd_printk("block change - offset = 0x%x, count = 0x%x\n", offset, count);
+	/*
+	snd_printk(KERN_DEBUG "block change - offset = 0x%x, count = 0x%x\n",
+		   offset, count);
+	*/
 	memset(&block, 0, sizeof(block));
 	block.cmd = SNDRV_GF1_DMA_IRQ;
 	if (snd_pcm_format_unsigned(runtime->format))
@@ -135,7 +138,11 @@
 		curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels;
 		end = curr + (pcmp->block_size / runtime->channels);
 		end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1;
-		// snd_printk("init: curr=0x%x, begin=0x%x, end=0x%x, ctrl=0x%x, ramp=0x%x, rate=0x%x\n", curr, begin, end, voice_ctrl, ramp_ctrl, rate);
+		/*
+		snd_printk(KERN_DEBUG "init: curr=0x%x, begin=0x%x, end=0x%x, "
+			   "ctrl=0x%x, ramp=0x%x, rate=0x%x\n",
+			   curr, begin, end, voice_ctrl, ramp_ctrl, rate);
+		*/
 		pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8;
 		vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
 		spin_lock_irqsave(&gus->reg_lock, flags);
@@ -205,9 +212,11 @@
 	ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03;
 #if 0
 	snd_gf1_select_voice(gus, pvoice->number);
-	printk("position = 0x%x\n", (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
+	printk(KERN_DEBUG "position = 0x%x\n",
+	       (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
 	snd_gf1_select_voice(gus, pcmp->pvoices[1]->number);
-	printk("position = 0x%x\n", (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
+	printk(KERN_DEBUG "position = 0x%x\n",
+	       (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
 	snd_gf1_select_voice(gus, pvoice->number);
 #endif
 	pcmp->bpos++;
@@ -299,7 +308,11 @@
 	unsigned int len;
 	unsigned long flags;
 
-	// printk("poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n", (int)buf, pos, count, gus->gf1.port);
+	/*
+	printk(KERN_DEBUG
+	       "poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n",
+	       (int)buf, pos, count, gus->gf1.port);
+	*/
 	while (count > 0) {
 		len = count;
 		if (len > 512)		/* limit, to allow IRQ */
@@ -680,7 +693,8 @@
 	runtime->private_free = snd_gf1_pcm_playback_free;
 
 #if 0
-	printk("playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer);
+	printk(KERN_DEBUG "playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n",
+	       (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer);
 #endif
 	if ((err = snd_gf1_dma_init(gus)) < 0)
 		return err;
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c
index f0af3f7..21cc42e 100644
--- a/sound/isa/gus/gus_uart.c
+++ b/sound/isa/gus/gus_uart.c
@@ -129,8 +129,14 @@
 	}
 	spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
 #if 0
-	snd_printk("read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus));
-	snd_printk("[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x (page = 0x%x)\n", gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102));
+	snd_printk(KERN_DEBUG
+		   "read init - enable = %i, cmd = 0x%x, stat = 0x%x\n",
+		   gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus));
+	snd_printk(KERN_DEBUG
+		   "[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x "
+		   "(page = 0x%x)\n",
+		   gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100),
+		   inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102));
 #endif
 	return 0;
 }
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 426532a..086b8f0 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -148,9 +148,9 @@
 	struct snd_gus_card *gus;
 	int error;
 
-	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
-	if (!card)
-		return -EINVAL;
+	error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card);
+	if (error < 0)
+		return error;
 
 	if (pcm_channels[n] < 2)
 		pcm_channels[n] = 2;
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index 7ad4c3b..180a8de 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -241,9 +241,9 @@
 	struct snd_opl3 *opl3;
 	int error;
 
-	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
-	if (!card)
-		return -EINVAL;
+	error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card);
+	if (error < 0)
+		return error;
 
 	if (mpu_port[n] == SNDRV_AUTO_PORT)
 		mpu_port[n] = 0;
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index f94c197..f26eac8 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -214,10 +214,10 @@
 	struct snd_wss *wss;
 	struct snd_gusmax *maxcard;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_gusmax));
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_gusmax), &card);
+	if (err < 0)
+		return err;
 	card->private_free = snd_gusmax_free;
 	maxcard = (struct snd_gusmax *)card->private_data;
 	maxcard->card = card;
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 5faecfb..534a6ec 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -170,7 +170,7 @@
 	unsigned long port = bus->private_value;
 
 #if 0
-	printk("i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data);
+	printk(KERN_DEBUG "i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data);
 #endif
 	outb((data << 1) | ctrl, port);
 	udelay(10);
@@ -183,7 +183,7 @@
 
 	res = inb(port) & 1;
 #if 0
-	printk("i2c_getclockline - 0x%lx -> %i\n", port, res);
+	printk(KERN_DEBUG "i2c_getclockline - 0x%lx -> %i\n", port, res);
 #endif
 	return res;
 }
@@ -197,7 +197,7 @@
 		udelay(10);
 	res = (inb(port) & 2) >> 1;
 #if 0
-	printk("i2c_getdataline - 0x%lx -> %i\n", port, res);
+	printk(KERN_DEBUG "i2c_getdataline - 0x%lx -> %i\n", port, res);
 #endif
 	return res;
 }
@@ -342,7 +342,8 @@
 			snd_gf1_poke(gus, local, d);
 			snd_gf1_poke(gus, local + 1, d + 1);
 #if 0
-			printk("d = 0x%x, local = 0x%x, local + 1 = 0x%x, idx << 22 = 0x%x\n",
+			printk(KERN_DEBUG "d = 0x%x, local = 0x%x, "
+			       "local + 1 = 0x%x, idx << 22 = 0x%x\n",
 			       d,
 			       snd_gf1_peek(gus, local),
 			       snd_gf1_peek(gus, local + 1),
@@ -356,7 +357,8 @@
 		}
 	}
 #if 0
-	printk("sizes: %i %i %i %i\n", sizes[0], sizes[1], sizes[2], sizes[3]);
+	printk(KERN_DEBUG "sizes: %i %i %i %i\n",
+	       sizes[0], sizes[1], sizes[2], sizes[3]);
 #endif
 }
 
@@ -410,12 +412,12 @@
 		lmct = (psizes[3] << 24) | (psizes[2] << 16) |
 		    (psizes[1] << 8) | psizes[0];
 #if 0
-		printk("lmct = 0x%08x\n", lmct);
+		printk(KERN_DEBUG "lmct = 0x%08x\n", lmct);
 #endif
 		for (i = 0; i < ARRAY_SIZE(lmc); i++)
 			if (lmct == lmc[i]) {
 #if 0
-				printk("found !!! %i\n", i);
+				printk(KERN_DEBUG "found !!! %i\n", i);
 #endif
 				snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | i);
 				snd_interwave_bank_sizes(gus, psizes);
@@ -626,20 +628,22 @@
 		free_irq(iwcard->irq, (void *)iwcard);
 }
 
-static struct snd_card *snd_interwave_card_new(int dev)
+static int snd_interwave_card_new(int dev, struct snd_card **cardp)
 {
 	struct snd_card *card;
 	struct snd_interwave *iwcard;
+	int err;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_interwave));
-	if (card == NULL)
-		return NULL;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_interwave), &card);
+	if (err < 0)
+		return err;
 	iwcard = card->private_data;
 	iwcard->card = card;
 	iwcard->irq = -1;
 	card->private_free = snd_interwave_free;
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
@@ -778,9 +782,9 @@
 	struct snd_card *card;
 	int err;
 
-	card = snd_interwave_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_interwave_card_new(dev, &card);
+	if (err < 0)
+		return err;
 
 	snd_card_set_dev(card, devptr);
 	if ((err = snd_interwave_probe(card, dev)) < 0) {
@@ -876,9 +880,9 @@
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
 				
-	card = snd_interwave_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	res = snd_interwave_card_new(dev, &card);
+	if (res < 0)
+		return res;
 
 	if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) {
 		snd_card_free(card);
diff --git a/sound/isa/msnd/Makefile b/sound/isa/msnd/Makefile
new file mode 100644
index 0000000..2171c0a
--- /dev/null
+++ b/sound/isa/msnd/Makefile
@@ -0,0 +1,9 @@
+
+snd-msnd-lib-objs := msnd.o msnd_midi.o msnd_pinnacle_mixer.o
+snd-msnd-pinnacle-objs := msnd_pinnacle.o
+snd-msnd-classic-objs := msnd_classic.o
+
+# Toplevel Module Dependency
+obj-$(CONFIG_SND_MSND_PINNACLE) += snd-msnd-pinnacle.o snd-msnd-lib.o
+obj-$(CONFIG_SND_MSND_CLASSIC) += snd-msnd-classic.o snd-msnd-lib.o
+
diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c
new file mode 100644
index 0000000..9064544
--- /dev/null
+++ b/sound/isa/msnd/msnd.c
@@ -0,0 +1,705 @@
+/*********************************************************************
+ *
+ * 2002/06/30 Karsten Wiese:
+ *	removed kernel-version dependencies.
+ *	ripped from linux kernel 2.4.18 (OSS Implementation) by me.
+ *	In the OSS Version, this file is compiled to a separate MODULE,
+ *	that is used by the pinnacle and the classic driver.
+ *	since there is no classic driver for alsa yet (i dont have a classic
+ *	& writing one blindfold is difficult) this file's object is statically
+ *	linked into the pinnacle-driver-module for now.	look for the string
+ *		"uncomment this to make this a module again"
+ *	to do guess what.
+ *
+ * the following is a copy of the 2.4.18 OSS FREE file-heading comment:
+ *
+ * msnd.c - Driver Base
+ *
+ * Turtle Beach MultiSound Sound Card Driver for Linux
+ *
+ * Copyright (C) 1998 Andrew Veliath
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "msnd.h"
+
+#define LOGNAME			"msnd"
+
+
+void snd_msnd_init_queue(void *base, int start, int size)
+{
+	writew(PCTODSP_BASED(start), base + JQS_wStart);
+	writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize);
+	writew(0, base + JQS_wHead);
+	writew(0, base + JQS_wTail);
+}
+EXPORT_SYMBOL(snd_msnd_init_queue);
+
+static int snd_msnd_wait_TXDE(struct snd_msnd *dev)
+{
+	unsigned int io = dev->io;
+	int timeout = 1000;
+
+	while (timeout-- > 0)
+		if (inb(io + HP_ISR) & HPISR_TXDE)
+			return 0;
+
+	return -EIO;
+}
+
+static int snd_msnd_wait_HC0(struct snd_msnd *dev)
+{
+	unsigned int io = dev->io;
+	int timeout = 1000;
+
+	while (timeout-- > 0)
+		if (!(inb(io + HP_CVR) & HPCVR_HC))
+			return 0;
+
+	return -EIO;
+}
+
+int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	if (snd_msnd_wait_HC0(dev) == 0) {
+		outb(cmd, dev->io + HP_CVR);
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return 0;
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	snd_printd(KERN_ERR LOGNAME ": Send DSP command timeout\n");
+
+	return -EIO;
+}
+EXPORT_SYMBOL(snd_msnd_send_dsp_cmd);
+
+int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high,
+		   unsigned char mid, unsigned char low)
+{
+	unsigned int io = dev->io;
+
+	if (snd_msnd_wait_TXDE(dev) == 0) {
+		outb(high, io + HP_TXH);
+		outb(mid, io + HP_TXM);
+		outb(low, io + HP_TXL);
+		return 0;
+	}
+
+	snd_printd(KERN_ERR LOGNAME ": Send host word timeout\n");
+
+	return -EIO;
+}
+EXPORT_SYMBOL(snd_msnd_send_word);
+
+int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len)
+{
+	int i;
+
+	if (len % 3 != 0) {
+		snd_printk(KERN_ERR LOGNAME
+			   ": Upload host data not multiple of 3!\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < len; i += 3)
+		if (snd_msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2]))
+			return -EIO;
+
+	inb(dev->io + HP_RXL);
+	inb(dev->io + HP_CVR);
+
+	return 0;
+}
+EXPORT_SYMBOL(snd_msnd_upload_host);
+
+int snd_msnd_enable_irq(struct snd_msnd *dev)
+{
+	unsigned long flags;
+
+	if (dev->irq_ref++)
+		return 0;
+
+	snd_printdd(LOGNAME ": Enabling IRQ\n");
+
+	spin_lock_irqsave(&dev->lock, flags);
+	if (snd_msnd_wait_TXDE(dev) == 0) {
+		outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
+		if (dev->type == msndClassic)
+			outb(dev->irqid, dev->io + HP_IRQM);
+
+		outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
+		outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
+		enable_irq(dev->irq);
+		snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff,
+				    dev->dspq_buff_size);
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return 0;
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	snd_printd(KERN_ERR LOGNAME ": Enable IRQ failed\n");
+
+	return -EIO;
+}
+EXPORT_SYMBOL(snd_msnd_enable_irq);
+
+int snd_msnd_disable_irq(struct snd_msnd *dev)
+{
+	unsigned long flags;
+
+	if (--dev->irq_ref > 0)
+		return 0;
+
+	if (dev->irq_ref < 0)
+		snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n",
+			   dev->irq_ref);
+
+	snd_printdd(LOGNAME ": Disabling IRQ\n");
+
+	spin_lock_irqsave(&dev->lock, flags);
+	if (snd_msnd_wait_TXDE(dev) == 0) {
+		outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
+		if (dev->type == msndClassic)
+			outb(HPIRQ_NONE, dev->io + HP_IRQM);
+		disable_irq(dev->irq);
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return 0;
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	snd_printd(KERN_ERR LOGNAME ": Disable IRQ failed\n");
+
+	return -EIO;
+}
+EXPORT_SYMBOL(snd_msnd_disable_irq);
+
+static inline long get_play_delay_jiffies(struct snd_msnd *chip, long size)
+{
+	long tmp = (size * HZ * chip->play_sample_size) / 8;
+	return tmp / (chip->play_sample_rate * chip->play_channels);
+}
+
+static void snd_msnd_dsp_write_flush(struct snd_msnd *chip)
+{
+	if (!(chip->mode & FMODE_WRITE) || !test_bit(F_WRITING, &chip->flags))
+		return;
+	set_bit(F_WRITEFLUSH, &chip->flags);
+/*	interruptible_sleep_on_timeout(
+		&chip->writeflush,
+		get_play_delay_jiffies(&chip, chip->DAPF.len));*/
+	clear_bit(F_WRITEFLUSH, &chip->flags);
+	if (!signal_pending(current))
+		schedule_timeout_interruptible(
+			get_play_delay_jiffies(chip, chip->play_period_bytes));
+	clear_bit(F_WRITING, &chip->flags);
+}
+
+void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file)
+{
+	if ((file ? file->f_mode : chip->mode) & FMODE_READ) {
+		clear_bit(F_READING, &chip->flags);
+		snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
+		snd_msnd_disable_irq(chip);
+		if (file) {
+			snd_printd(KERN_INFO LOGNAME
+				   ": Stopping read for %p\n", file);
+			chip->mode &= ~FMODE_READ;
+		}
+		clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
+	}
+	if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) {
+		if (test_bit(F_WRITING, &chip->flags)) {
+			snd_msnd_dsp_write_flush(chip);
+			snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
+		}
+		snd_msnd_disable_irq(chip);
+		if (file) {
+			snd_printd(KERN_INFO
+				   LOGNAME ": Stopping write for %p\n", file);
+			chip->mode &= ~FMODE_WRITE;
+		}
+		clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
+	}
+}
+EXPORT_SYMBOL(snd_msnd_dsp_halt);
+
+
+int snd_msnd_DARQ(struct snd_msnd *chip, int bank)
+{
+	int /*size, n,*/ timeout = 3;
+	u16 wTmp;
+	/* void *DAQD; */
+
+	/* Increment the tail and check for queue wrap */
+	wTmp = readw(chip->DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size);
+	if (wTmp > readw(chip->DARQ + JQS_wSize))
+		wTmp = 0;
+	while (wTmp == readw(chip->DARQ + JQS_wHead) && timeout--)
+		udelay(1);
+
+	if (chip->capturePeriods == 2) {
+		void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF +
+			     bank * DAQDS__size + DAQDS_wStart;
+		unsigned short offset = 0x3000 + chip->capturePeriodBytes;
+
+		if (readw(pDAQ) != PCTODSP_BASED(0x3000))
+			offset = 0x3000;
+		writew(PCTODSP_BASED(offset), pDAQ);
+	}
+
+	writew(wTmp, chip->DARQ + JQS_wTail);
+
+#if 0
+	/* Get our digital audio queue struct */
+	DAQD = bank * DAQDS__size + chip->mappedbase + DARQ_DATA_BUFF;
+
+	/* Get length of data */
+	size = readw(DAQD + DAQDS_wSize);
+
+	/* Read data from the head (unprotected bank 1 access okay
+	   since this is only called inside an interrupt) */
+	outb(HPBLKSEL_1, chip->io + HP_BLKS);
+	n = msnd_fifo_write(&chip->DARF,
+			    (char *)(chip->base + bank * DAR_BUFF_SIZE),
+			    size, 0);
+	if (n <= 0) {
+		outb(HPBLKSEL_0, chip->io + HP_BLKS);
+		return n;
+	}
+	outb(HPBLKSEL_0, chip->io + HP_BLKS);
+#endif
+
+	return 1;
+}
+EXPORT_SYMBOL(snd_msnd_DARQ);
+
+int snd_msnd_DAPQ(struct snd_msnd *chip, int start)
+{
+	u16	DAPQ_tail;
+	int	protect = start, nbanks = 0;
+	void	*DAQD;
+	static int play_banks_submitted;
+	/* unsigned long flags;
+	spin_lock_irqsave(&chip->lock, flags); not necessary */
+
+	DAPQ_tail = readw(chip->DAPQ + JQS_wTail);
+	while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) {
+		int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size);
+
+		if (start) {
+			start = 0;
+			play_banks_submitted = 0;
+		}
+
+		/* Get our digital audio queue struct */
+		DAQD = bank_num * DAQDS__size + chip->mappedbase +
+			DAPQ_DATA_BUFF;
+
+		/* Write size of this bank */
+		writew(chip->play_period_bytes, DAQD + DAQDS_wSize);
+		if (play_banks_submitted < 3)
+			++play_banks_submitted;
+		else if (chip->playPeriods == 2) {
+			unsigned short offset = chip->play_period_bytes;
+
+			if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0))
+				offset = 0;
+
+			writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart);
+		}
+		++nbanks;
+
+		/* Then advance the tail */
+		/*
+		if (protect)
+			snd_printd(KERN_INFO "B %X %lX\n",
+				   bank_num, xtime.tv_usec);
+		*/
+
+		DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size);
+		writew(DAPQ_tail, chip->DAPQ + JQS_wTail);
+		/* Tell the DSP to play the bank */
+		snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START);
+		if (protect)
+			if (2 == bank_num)
+				break;
+	}
+	/*
+	if (protect)
+		snd_printd(KERN_INFO "%lX\n", xtime.tv_usec);
+	*/
+	/* spin_unlock_irqrestore(&chip->lock, flags); not necessary */
+	return nbanks;
+}
+EXPORT_SYMBOL(snd_msnd_DAPQ);
+
+static void snd_msnd_play_reset_queue(struct snd_msnd *chip,
+				      unsigned int pcm_periods,
+				      unsigned int pcm_count)
+{
+	int	n;
+	void	*pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
+
+	chip->last_playbank = -1;
+	chip->playLimit = pcm_count * (pcm_periods - 1);
+	chip->playPeriods = pcm_periods;
+	writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead);
+	writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail);
+
+	chip->play_period_bytes = pcm_count;
+
+	for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
+		writew(PCTODSP_BASED((u32)(pcm_count * n)),
+			pDAQ + DAQDS_wStart);
+		writew(0, pDAQ + DAQDS_wSize);
+		writew(1, pDAQ + DAQDS_wFormat);
+		writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
+		writew(chip->play_channels, pDAQ + DAQDS_wChannels);
+		writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
+		writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
+		writew(n, pDAQ + DAQDS_wFlags);
+	}
+}
+
+static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
+					 unsigned int pcm_periods,
+					 unsigned int pcm_count)
+{
+	int		n;
+	void		*pDAQ;
+	/* unsigned long	flags; */
+
+	/* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */
+
+	chip->last_recbank = 2;
+	chip->captureLimit = pcm_count * (pcm_periods - 1);
+	chip->capturePeriods = pcm_periods;
+	writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead);
+	writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size),
+		chip->DARQ + JQS_wTail);
+
+#if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/
+	spin_lock_irqsave(&chip->lock, flags);
+	outb(HPBLKSEL_1, chip->io + HP_BLKS);
+	memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3);
+	outb(HPBLKSEL_0, chip->io + HP_BLKS);
+	spin_unlock_irqrestore(&chip->lock, flags);
+#endif
+
+	chip->capturePeriodBytes = pcm_count;
+	snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count);
+
+	pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
+
+	for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
+		u32 tmp = pcm_count * n;
+
+		writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart);
+		writew(pcm_count, pDAQ + DAQDS_wSize);
+		writew(1, pDAQ + DAQDS_wFormat);
+		writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
+		writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
+		writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
+		writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
+		writew(n, pDAQ + DAQDS_wFlags);
+	}
+}
+
+static struct snd_pcm_hardware snd_msnd_playback = {
+	.info =			SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_INTERLEAVED |
+				SNDRV_PCM_INFO_MMAP_VALID,
+	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_8000_48000,
+	.rate_min =		8000,
+	.rate_max =		48000,
+	.channels_min =		1,
+	.channels_max =		2,
+	.buffer_bytes_max =	0x3000,
+	.period_bytes_min =	0x40,
+	.period_bytes_max =	0x1800,
+	.periods_min =		2,
+	.periods_max =		3,
+	.fifo_size =		0,
+};
+
+static struct snd_pcm_hardware snd_msnd_capture = {
+	.info =			SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_INTERLEAVED |
+				SNDRV_PCM_INFO_MMAP_VALID,
+	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_8000_48000,
+	.rate_min =		8000,
+	.rate_max =		48000,
+	.channels_min =		1,
+	.channels_max =		2,
+	.buffer_bytes_max =	0x3000,
+	.period_bytes_min =	0x40,
+	.period_bytes_max =	0x1800,
+	.periods_min =		2,
+	.periods_max =		3,
+	.fifo_size =		0,
+};
+
+
+static int snd_msnd_playback_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+
+	set_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
+	clear_bit(F_WRITING, &chip->flags);
+	snd_msnd_enable_irq(chip);
+
+	runtime->dma_area = chip->mappedbase;
+	runtime->dma_bytes = 0x3000;
+
+	chip->playback_substream = substream;
+	runtime->hw = snd_msnd_playback;
+	return 0;
+}
+
+static int snd_msnd_playback_close(struct snd_pcm_substream *substream)
+{
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+
+	snd_msnd_disable_irq(chip);
+	clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
+	return 0;
+}
+
+
+static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	int	i;
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+	void	*pDAQ =	chip->mappedbase + DAPQ_DATA_BUFF;
+
+	chip->play_sample_size = snd_pcm_format_width(params_format(params));
+	chip->play_channels = params_channels(params);
+	chip->play_sample_rate = params_rate(params);
+
+	for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
+		writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
+		writew(chip->play_channels, pDAQ + DAQDS_wChannels);
+		writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
+	}
+	/* dont do this here:
+	 * snd_msnd_calibrate_adc(chip->play_sample_rate);
+	 */
+
+	return 0;
+}
+
+static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+	unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
+	unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
+	unsigned int pcm_periods = pcm_size / pcm_count;
+
+	snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count);
+	chip->playDMAPos = 0;
+	return 0;
+}
+
+static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream,
+				     int cmd)
+{
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+	int	result = 0;
+
+	if (cmd == SNDRV_PCM_TRIGGER_START) {
+		snd_printdd("snd_msnd_playback_trigger(START)\n");
+		chip->banksPlayed = 0;
+		set_bit(F_WRITING, &chip->flags);
+		snd_msnd_DAPQ(chip, 1);
+	} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+		snd_printdd("snd_msnd_playback_trigger(STop)\n");
+		/* interrupt diagnostic, comment this out later */
+		clear_bit(F_WRITING, &chip->flags);
+		snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
+	} else {
+		snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n");
+		result = -EINVAL;
+	}
+
+	snd_printdd("snd_msnd_playback_trigger() ENDE\n");
+	return result;
+}
+
+static snd_pcm_uframes_t
+snd_msnd_playback_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+
+	return bytes_to_frames(substream->runtime, chip->playDMAPos);
+}
+
+
+static struct snd_pcm_ops snd_msnd_playback_ops = {
+	.open =		snd_msnd_playback_open,
+	.close =	snd_msnd_playback_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_msnd_playback_hw_params,
+	.prepare =	snd_msnd_playback_prepare,
+	.trigger =	snd_msnd_playback_trigger,
+	.pointer =	snd_msnd_playback_pointer,
+};
+
+static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+
+	set_bit(F_AUDIO_READ_INUSE, &chip->flags);
+	snd_msnd_enable_irq(chip);
+	runtime->dma_area = chip->mappedbase + 0x3000;
+	runtime->dma_bytes = 0x3000;
+	memset(runtime->dma_area, 0, runtime->dma_bytes);
+	chip->capture_substream = substream;
+	runtime->hw = snd_msnd_capture;
+	return 0;
+}
+
+static int snd_msnd_capture_close(struct snd_pcm_substream *substream)
+{
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+
+	snd_msnd_disable_irq(chip);
+	clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
+	return 0;
+}
+
+static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+	unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
+	unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
+	unsigned int pcm_periods = pcm_size / pcm_count;
+
+	snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count);
+	chip->captureDMAPos = 0;
+	return 0;
+}
+
+static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream,
+				    int cmd)
+{
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+
+	if (cmd == SNDRV_PCM_TRIGGER_START) {
+		chip->last_recbank = -1;
+		set_bit(F_READING, &chip->flags);
+		if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0)
+			return 0;
+
+		clear_bit(F_READING, &chip->flags);
+	} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+		clear_bit(F_READING, &chip->flags);
+		snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+
+static snd_pcm_uframes_t
+snd_msnd_capture_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+
+	return bytes_to_frames(runtime, chip->captureDMAPos);
+}
+
+
+static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	int		i;
+	struct snd_msnd *chip = snd_pcm_substream_chip(substream);
+	void		*pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
+
+	chip->capture_sample_size = snd_pcm_format_width(params_format(params));
+	chip->capture_channels = params_channels(params);
+	chip->capture_sample_rate = params_rate(params);
+
+	for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
+		writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
+		writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
+		writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
+	}
+	return 0;
+}
+
+
+static struct snd_pcm_ops snd_msnd_capture_ops = {
+	.open =		snd_msnd_capture_open,
+	.close =	snd_msnd_capture_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_msnd_capture_hw_params,
+	.prepare =	snd_msnd_capture_prepare,
+	.trigger =	snd_msnd_capture_trigger,
+	.pointer =	snd_msnd_capture_pointer,
+};
+
+
+int snd_msnd_pcm(struct snd_card *card, int device,
+			struct snd_pcm **rpcm)
+{
+	struct snd_msnd *chip = card->private_data;
+	struct snd_pcm	*pcm;
+	int err;
+
+	err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm);
+	if (err < 0)
+		return err;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops);
+
+	pcm->private_data = chip;
+	strcpy(pcm->name, "Hurricane");
+
+
+	if (rpcm)
+		*rpcm = pcm;
+	return 0;
+}
+EXPORT_SYMBOL(snd_msnd_pcm);
+
+MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h
new file mode 100644
index 0000000..3773e24
--- /dev/null
+++ b/sound/isa/msnd/msnd.h
@@ -0,0 +1,308 @@
+/*********************************************************************
+ *
+ * msnd.h
+ *
+ * Turtle Beach MultiSound Sound Card Driver for Linux
+ *
+ * Some parts of this header file were derived from the Turtle Beach
+ * MultiSound Driver Development Kit.
+ *
+ * Copyright (C) 1998 Andrew Veliath
+ * Copyright (C) 1993 Turtle Beach Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************/
+#ifndef __MSND_H
+#define __MSND_H
+
+#define DEFSAMPLERATE		44100
+#define DEFSAMPLESIZE		SNDRV_PCM_FORMAT_S16
+#define DEFCHANNELS		1
+
+#define SRAM_BANK_SIZE		0x8000
+#define SRAM_CNTL_START		0x7F00
+#define SMA_STRUCT_START	0x7F40
+
+#define DSP_BASE_ADDR		0x4000
+#define DSP_BANK_BASE		0x4000
+
+#define AGND			0x01
+#define SIGNAL			0x02
+
+#define EXT_DSP_BIT_DCAL	0x0001
+#define EXT_DSP_BIT_MIDI_CON	0x0002
+
+#define BUFFSIZE		0x8000
+#define HOSTQ_SIZE		0x40
+
+#define DAP_BUFF_SIZE		0x2400
+
+#define DAPQ_STRUCT_SIZE	0x10
+#define DARQ_STRUCT_SIZE	0x10
+#define DAPQ_BUFF_SIZE		(3 * 0x10)
+#define DARQ_BUFF_SIZE		(3 * 0x10)
+#define MODQ_BUFF_SIZE		0x400
+
+#define DAPQ_DATA_BUFF		0x6C00
+#define DARQ_DATA_BUFF		0x6C30
+#define MODQ_DATA_BUFF		0x6C60
+#define MIDQ_DATA_BUFF		0x7060
+
+#define DAPQ_OFFSET		SRAM_CNTL_START
+#define DARQ_OFFSET		(SRAM_CNTL_START + 0x08)
+#define MODQ_OFFSET		(SRAM_CNTL_START + 0x10)
+#define MIDQ_OFFSET		(SRAM_CNTL_START + 0x18)
+#define DSPQ_OFFSET		(SRAM_CNTL_START + 0x20)
+
+#define	HP_ICR			0x00
+#define	HP_CVR			0x01
+#define	HP_ISR			0x02
+#define	HP_IVR			0x03
+#define HP_NU			0x04
+#define HP_INFO			0x04
+#define	HP_TXH			0x05
+#define	HP_RXH			0x05
+#define	HP_TXM			0x06
+#define	HP_RXM			0x06
+#define	HP_TXL			0x07
+#define	HP_RXL			0x07
+
+#define HP_ICR_DEF		0x00
+#define HP_CVR_DEF		0x12
+#define HP_ISR_DEF		0x06
+#define HP_IVR_DEF		0x0f
+#define HP_NU_DEF		0x00
+
+#define	HP_IRQM			0x09
+
+#define	HPR_BLRC		0x08
+#define	HPR_SPR1		0x09
+#define	HPR_SPR2		0x0A
+#define	HPR_TCL0		0x0B
+#define	HPR_TCL1		0x0C
+#define	HPR_TCL2		0x0D
+#define	HPR_TCL3		0x0E
+#define	HPR_TCL4		0x0F
+
+#define	HPICR_INIT		0x80
+#define HPICR_HM1		0x40
+#define HPICR_HM0		0x20
+#define HPICR_HF1		0x10
+#define HPICR_HF0		0x08
+#define	HPICR_TREQ		0x02
+#define	HPICR_RREQ		0x01
+
+#define HPCVR_HC		0x80
+
+#define	HPISR_HREQ		0x80
+#define HPISR_DMA		0x40
+#define HPISR_HF3		0x10
+#define HPISR_HF2		0x08
+#define	HPISR_TRDY		0x04
+#define	HPISR_TXDE		0x02
+#define	HPISR_RXDF		0x01
+
+#define	HPIO_290		0
+#define	HPIO_260		1
+#define	HPIO_250		2
+#define	HPIO_240		3
+#define	HPIO_230		4
+#define	HPIO_220		5
+#define	HPIO_210		6
+#define	HPIO_3E0		7
+
+#define	HPMEM_NONE		0
+#define	HPMEM_B000		1
+#define	HPMEM_C800		2
+#define	HPMEM_D000		3
+#define	HPMEM_D400		4
+#define	HPMEM_D800		5
+#define	HPMEM_E000		6
+#define	HPMEM_E800		7
+
+#define	HPIRQ_NONE		0
+#define HPIRQ_5			1
+#define HPIRQ_7			2
+#define HPIRQ_9			3
+#define HPIRQ_10		4
+#define HPIRQ_11		5
+#define HPIRQ_12		6
+#define HPIRQ_15		7
+
+#define	HIMT_PLAY_DONE		0x00
+#define	HIMT_RECORD_DONE	0x01
+#define	HIMT_MIDI_EOS		0x02
+#define	HIMT_MIDI_OUT		0x03
+
+#define	HIMT_MIDI_IN_UCHAR	0x0E
+#define	HIMT_DSP		0x0F
+
+#define	HDEX_BASE	       	0x92
+#define	HDEX_PLAY_START		(0 + HDEX_BASE)
+#define	HDEX_PLAY_STOP		(1 + HDEX_BASE)
+#define	HDEX_PLAY_PAUSE		(2 + HDEX_BASE)
+#define	HDEX_PLAY_RESUME	(3 + HDEX_BASE)
+#define	HDEX_RECORD_START	(4 + HDEX_BASE)
+#define	HDEX_RECORD_STOP	(5 + HDEX_BASE)
+#define	HDEX_MIDI_IN_START 	(6 + HDEX_BASE)
+#define	HDEX_MIDI_IN_STOP	(7 + HDEX_BASE)
+#define	HDEX_MIDI_OUT_START	(8 + HDEX_BASE)
+#define	HDEX_MIDI_OUT_STOP	(9 + HDEX_BASE)
+#define	HDEX_AUX_REQ		(10 + HDEX_BASE)
+
+#define	HDEXAR_CLEAR_PEAKS	1
+#define	HDEXAR_IN_SET_POTS	2
+#define	HDEXAR_AUX_SET_POTS	3
+#define	HDEXAR_CAL_A_TO_D	4
+#define	HDEXAR_RD_EXT_DSP_BITS	5
+
+/* Pinnacle only HDEXAR defs */
+#define	HDEXAR_SET_ANA_IN	0
+#define	HDEXAR_SET_SYNTH_IN	4
+#define	HDEXAR_READ_DAT_IN	5
+#define	HDEXAR_MIC_SET_POTS	6
+#define	HDEXAR_SET_DAT_IN	7
+
+#define HDEXAR_SET_SYNTH_48	8
+#define HDEXAR_SET_SYNTH_44	9
+
+#define HIWORD(l)		((u16)((((u32)(l)) >> 16) & 0xFFFF))
+#define LOWORD(l)		((u16)(u32)(l))
+#define HIBYTE(w)		((u8)(((u16)(w) >> 8) & 0xFF))
+#define LOBYTE(w)		((u8)(w))
+#define MAKELONG(low, hi)	((long)(((u16)(low))|(((u32)((u16)(hi)))<<16)))
+#define MAKEWORD(low, hi)	((u16)(((u8)(low))|(((u16)((u8)(hi)))<<8)))
+
+#define PCTODSP_OFFSET(w)	(u16)((w)/2)
+#define PCTODSP_BASED(w)	(u16)(((w)/2) + DSP_BASE_ADDR)
+#define DSPTOPC_BASED(w)	(((w) - DSP_BASE_ADDR) * 2)
+
+#ifdef SLOWIO
+#  undef outb
+#  undef inb
+#  define outb			outb_p
+#  define inb			inb_p
+#endif
+
+/* JobQueueStruct */
+#define JQS_wStart		0x00
+#define JQS_wSize		0x02
+#define JQS_wHead		0x04
+#define JQS_wTail		0x06
+#define JQS__size		0x08
+
+/* DAQueueDataStruct */
+#define DAQDS_wStart		0x00
+#define DAQDS_wSize		0x02
+#define DAQDS_wFormat		0x04
+#define DAQDS_wSampleSize	0x06
+#define DAQDS_wChannels		0x08
+#define DAQDS_wSampleRate	0x0A
+#define DAQDS_wIntMsg		0x0C
+#define DAQDS_wFlags		0x0E
+#define DAQDS__size		0x10
+
+#include <sound/pcm.h>
+
+struct snd_msnd {
+	void __iomem		*mappedbase;
+	int			play_period_bytes;
+	int			playLimit;
+	int			playPeriods;
+	int 			playDMAPos;
+	int			banksPlayed;
+	int 			captureDMAPos;
+	int			capturePeriodBytes;
+	int			captureLimit;
+	int			capturePeriods;
+	struct snd_card		*card;
+	void			*msndmidi_mpu;
+	struct snd_rawmidi	*rmidi;
+
+	/* Hardware resources */
+	long io;
+	int memid, irqid;
+	int irq, irq_ref;
+	unsigned long base;
+
+	/* Motorola 56k DSP SMA */
+	void __iomem	*SMA;
+	void __iomem	*DAPQ;
+	void __iomem	*DARQ;
+	void __iomem	*MODQ;
+	void __iomem	*MIDQ;
+	void __iomem	*DSPQ;
+	int dspq_data_buff, dspq_buff_size;
+
+	/* State variables */
+	enum { msndClassic, msndPinnacle } type;
+	mode_t mode;
+	unsigned long flags;
+#define F_RESETTING			0
+#define F_HAVEDIGITAL			1
+#define F_AUDIO_WRITE_INUSE		2
+#define F_WRITING			3
+#define F_WRITEBLOCK			4
+#define F_WRITEFLUSH			5
+#define F_AUDIO_READ_INUSE		6
+#define F_READING			7
+#define F_READBLOCK			8
+#define F_EXT_MIDI_INUSE		9
+#define F_HDR_MIDI_INUSE		10
+#define F_DISABLE_WRITE_NDELAY		11
+	spinlock_t lock;
+	spinlock_t mixer_lock;
+	int nresets;
+	unsigned recsrc;
+#define LEVEL_ENTRIES 32
+	int left_levels[LEVEL_ENTRIES];
+	int right_levels[LEVEL_ENTRIES];
+	int calibrate_signal;
+	int play_sample_size, play_sample_rate, play_channels;
+	int play_ndelay;
+	int capture_sample_size, capture_sample_rate, capture_channels;
+	int capture_ndelay;
+	u8 bCurrentMidiPatch;
+
+	int last_playbank, last_recbank;
+	struct snd_pcm_substream *playback_substream;
+	struct snd_pcm_substream *capture_substream;
+
+};
+
+void snd_msnd_init_queue(void *base, int start, int size);
+
+int snd_msnd_send_dsp_cmd(struct snd_msnd *chip, u8 cmd);
+int snd_msnd_send_word(struct snd_msnd *chip,
+			   unsigned char high,
+			   unsigned char mid,
+			   unsigned char low);
+int snd_msnd_upload_host(struct snd_msnd *chip,
+			     const u8 *bin, int len);
+int snd_msnd_enable_irq(struct snd_msnd *chip);
+int snd_msnd_disable_irq(struct snd_msnd *chip);
+void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file);
+int snd_msnd_DAPQ(struct snd_msnd *chip, int start);
+int snd_msnd_DARQ(struct snd_msnd *chip, int start);
+int snd_msnd_pcm(struct snd_card *card, int device, struct snd_pcm **rpcm);
+
+int snd_msndmidi_new(struct snd_card *card, int device);
+void snd_msndmidi_input_read(void *mpu);
+
+void snd_msndmix_setup(struct snd_msnd *chip);
+int __devinit snd_msndmix_new(struct snd_card *card);
+int snd_msndmix_force_recsrc(struct snd_msnd *chip, int recsrc);
+#endif /* __MSND_H */
diff --git a/sound/isa/msnd/msnd_classic.c b/sound/isa/msnd/msnd_classic.c
new file mode 100644
index 0000000..3b23a09
--- /dev/null
+++ b/sound/isa/msnd/msnd_classic.c
@@ -0,0 +1,3 @@
+/* The work is in msnd_pinnacle.c, just define MSND_CLASSIC before it. */
+#define MSND_CLASSIC
+#include "msnd_pinnacle.c"
diff --git a/sound/isa/msnd/msnd_classic.h b/sound/isa/msnd/msnd_classic.h
new file mode 100644
index 0000000..f18d5fa
--- /dev/null
+++ b/sound/isa/msnd/msnd_classic.h
@@ -0,0 +1,129 @@
+/*********************************************************************
+ *
+ * msnd_classic.h
+ *
+ * Turtle Beach MultiSound Sound Card Driver for Linux
+ *
+ * Some parts of this header file were derived from the Turtle Beach
+ * MultiSound Driver Development Kit.
+ *
+ * Copyright (C) 1998 Andrew Veliath
+ * Copyright (C) 1993 Turtle Beach Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************/
+#ifndef __MSND_CLASSIC_H
+#define __MSND_CLASSIC_H
+
+#define DSP_NUMIO				0x10
+
+#define	HP_MEMM					0x08
+
+#define	HP_BITM					0x0E
+#define	HP_WAIT					0x0D
+#define	HP_DSPR					0x0A
+#define	HP_PROR					0x0B
+#define	HP_BLKS					0x0C
+
+#define	HPPRORESET_OFF				0
+#define HPPRORESET_ON				1
+
+#define HPDSPRESET_OFF				0
+#define HPDSPRESET_ON				1
+
+#define HPBLKSEL_0				0
+#define HPBLKSEL_1				1
+
+#define HPWAITSTATE_0				0
+#define HPWAITSTATE_1				1
+
+#define HPBITMODE_16				0
+#define HPBITMODE_8				1
+
+#define	HIDSP_INT_PLAY_UNDER			0x00
+#define	HIDSP_INT_RECORD_OVER			0x01
+#define	HIDSP_INPUT_CLIPPING			0x02
+#define	HIDSP_MIDI_IN_OVER			0x10
+#define	HIDSP_MIDI_OVERRUN_ERR  0x13
+
+#define TIME_PRO_RESET_DONE			0x028A
+#define TIME_PRO_SYSEX				0x0040
+#define TIME_PRO_RESET				0x0032
+
+#define DAR_BUFF_SIZE				0x2000
+
+#define MIDQ_BUFF_SIZE				0x200
+#define DSPQ_BUFF_SIZE				0x40
+
+#define DSPQ_DATA_BUFF				0x7260
+
+#define MOP_SYNTH				0x10
+#define MOP_EXTOUT				0x32
+#define MOP_EXTTHRU				0x02
+#define MOP_OUTMASK				0x01
+
+#define MIP_EXTIN				0x01
+#define MIP_SYNTH				0x00
+#define MIP_INMASK				0x32
+
+/* Classic SMA Common Data */
+#define SMA_wCurrPlayBytes			0x0000
+#define SMA_wCurrRecordBytes			0x0002
+#define SMA_wCurrPlayVolLeft			0x0004
+#define SMA_wCurrPlayVolRight			0x0006
+#define SMA_wCurrInVolLeft			0x0008
+#define SMA_wCurrInVolRight			0x000a
+#define SMA_wUser_3				0x000c
+#define SMA_wUser_4				0x000e
+#define SMA_dwUser_5				0x0010
+#define SMA_dwUser_6				0x0014
+#define SMA_wUser_7				0x0018
+#define SMA_wReserved_A				0x001a
+#define SMA_wReserved_B				0x001c
+#define SMA_wReserved_C				0x001e
+#define SMA_wReserved_D				0x0020
+#define SMA_wReserved_E				0x0022
+#define SMA_wReserved_F				0x0024
+#define SMA_wReserved_G				0x0026
+#define SMA_wReserved_H				0x0028
+#define SMA_wCurrDSPStatusFlags			0x002a
+#define SMA_wCurrHostStatusFlags		0x002c
+#define SMA_wCurrInputTagBits			0x002e
+#define SMA_wCurrLeftPeak			0x0030
+#define SMA_wCurrRightPeak			0x0032
+#define SMA_wExtDSPbits				0x0034
+#define SMA_bExtHostbits			0x0036
+#define SMA_bBoardLevel				0x0037
+#define SMA_bInPotPosRight			0x0038
+#define SMA_bInPotPosLeft			0x0039
+#define SMA_bAuxPotPosRight			0x003a
+#define SMA_bAuxPotPosLeft			0x003b
+#define SMA_wCurrMastVolLeft			0x003c
+#define SMA_wCurrMastVolRight			0x003e
+#define SMA_bUser_12				0x0040
+#define SMA_bUser_13				0x0041
+#define SMA_wUser_14				0x0042
+#define SMA_wUser_15				0x0044
+#define SMA_wCalFreqAtoD			0x0046
+#define SMA_wUser_16				0x0048
+#define SMA_wUser_17				0x004a
+#define SMA__size				0x004c
+
+#define INITCODEFILE		"turtlebeach/msndinit.bin"
+#define PERMCODEFILE		"turtlebeach/msndperm.bin"
+#define LONGNAME		"MultiSound (Classic/Monterey/Tahiti)"
+
+#endif /* __MSND_CLASSIC_H */
diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c
new file mode 100644
index 0000000..cb9aa4c
--- /dev/null
+++ b/sound/isa/msnd/msnd_midi.c
@@ -0,0 +1,180 @@
+/*
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ *  Copyright (c) 2009 by Krzysztof Helt
+ *  Routines for control of MPU-401 in UART mode
+ *
+ *  MPU-401 supports UART mode which is not capable generate transmit
+ *  interrupts thus output is done via polling. Also, if irq < 0, then
+ *  input is done also via polling. Do not expect good performance.
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <sound/core.h>
+#include <sound/rawmidi.h>
+
+#include "msnd.h"
+
+#define MSNDMIDI_MODE_BIT_INPUT		0
+#define MSNDMIDI_MODE_BIT_OUTPUT		1
+#define MSNDMIDI_MODE_BIT_INPUT_TRIGGER	2
+#define MSNDMIDI_MODE_BIT_OUTPUT_TRIGGER	3
+
+struct snd_msndmidi {
+	struct snd_msnd *dev;
+
+	unsigned long mode;		/* MSNDMIDI_MODE_XXXX */
+
+	struct snd_rawmidi_substream *substream_input;
+
+	spinlock_t input_lock;
+};
+
+/*
+ * input/output open/close - protected by open_mutex in rawmidi.c
+ */
+static int snd_msndmidi_input_open(struct snd_rawmidi_substream *substream)
+{
+	struct snd_msndmidi *mpu;
+
+	snd_printdd("snd_msndmidi_input_open()\n");
+
+	mpu = substream->rmidi->private_data;
+
+	mpu->substream_input = substream;
+
+	snd_msnd_enable_irq(mpu->dev);
+
+	snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_START);
+	set_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode);
+	return 0;
+}
+
+static int snd_msndmidi_input_close(struct snd_rawmidi_substream *substream)
+{
+	struct snd_msndmidi *mpu;
+
+	mpu = substream->rmidi->private_data;
+	snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_STOP);
+	clear_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode);
+	mpu->substream_input = NULL;
+	snd_msnd_disable_irq(mpu->dev);
+	return 0;
+}
+
+static void snd_msndmidi_input_drop(struct snd_msndmidi *mpu)
+{
+	u16 tail;
+
+	tail = readw(mpu->dev->MIDQ + JQS_wTail);
+	writew(tail, mpu->dev->MIDQ + JQS_wHead);
+}
+
+/*
+ * trigger input
+ */
+static void snd_msndmidi_input_trigger(struct snd_rawmidi_substream *substream,
+					int up)
+{
+	unsigned long flags;
+	struct snd_msndmidi *mpu;
+
+	snd_printdd("snd_msndmidi_input_trigger(, %i)\n", up);
+
+	mpu = substream->rmidi->private_data;
+	spin_lock_irqsave(&mpu->input_lock, flags);
+	if (up) {
+		if (!test_and_set_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER,
+				      &mpu->mode))
+			snd_msndmidi_input_drop(mpu);
+	} else {
+		clear_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
+	}
+	spin_unlock_irqrestore(&mpu->input_lock, flags);
+	if (up)
+		snd_msndmidi_input_read(mpu);
+}
+
+void snd_msndmidi_input_read(void *mpuv)
+{
+	unsigned long flags;
+	struct snd_msndmidi *mpu = mpuv;
+	void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF;
+
+	spin_lock_irqsave(&mpu->input_lock, flags);
+	while (readw(mpu->dev->MIDQ + JQS_wTail) !=
+	       readw(mpu->dev->MIDQ + JQS_wHead)) {
+		u16 wTmp, val;
+		val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead));
+
+			if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER,
+				     &mpu->mode))
+				snd_rawmidi_receive(mpu->substream_input,
+						    (unsigned char *)&val, 1);
+
+		wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1;
+		if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize))
+			writew(0,  mpu->dev->MIDQ + JQS_wHead);
+		else
+			writew(wTmp,  mpu->dev->MIDQ + JQS_wHead);
+	}
+	spin_unlock_irqrestore(&mpu->input_lock, flags);
+}
+EXPORT_SYMBOL(snd_msndmidi_input_read);
+
+static struct snd_rawmidi_ops snd_msndmidi_input = {
+	.open =		snd_msndmidi_input_open,
+	.close =	snd_msndmidi_input_close,
+	.trigger =	snd_msndmidi_input_trigger,
+};
+
+static void snd_msndmidi_free(struct snd_rawmidi *rmidi)
+{
+	struct snd_msndmidi *mpu = rmidi->private_data;
+	kfree(mpu);
+}
+
+int snd_msndmidi_new(struct snd_card *card, int device)
+{
+	struct snd_msnd *chip = card->private_data;
+	struct snd_msndmidi *mpu;
+	struct snd_rawmidi *rmidi;
+	int err;
+
+	err = snd_rawmidi_new(card, "MSND-MIDI", device, 1, 1, &rmidi);
+	if (err < 0)
+		return err;
+	mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
+	if (mpu == NULL) {
+		snd_device_free(card, rmidi);
+		return -ENOMEM;
+	}
+	mpu->dev = chip;
+	chip->msndmidi_mpu = mpu;
+	rmidi->private_data = mpu;
+	rmidi->private_free = snd_msndmidi_free;
+	spin_lock_init(&mpu->input_lock);
+	strcpy(rmidi->name, "MSND MIDI");
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+			    &snd_msndmidi_input);
+	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
+	return 0;
+}
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
new file mode 100644
index 0000000..60b6abd
--- /dev/null
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -0,0 +1,1238 @@
+/*********************************************************************
+ *
+ * Linux multisound pinnacle/fiji driver for ALSA.
+ *
+ * 2002/06/30 Karsten Wiese:
+ *	for now this is only used to build a pinnacle / fiji driver.
+ *	the OSS parent of this code is designed to also support
+ *	the multisound classic via the file msnd_classic.c.
+ *	to make it easier for some brave heart to implemt classic
+ *	support in alsa, i left all the MSND_CLASSIC tokens in this file.
+ *	but for now this untested & undone.
+ *
+ *
+ * ripped from linux kernel 2.4.18 by Karsten Wiese.
+ *
+ * the following is a copy of the 2.4.18 OSS FREE file-heading comment:
+ *
+ * Turtle Beach MultiSound Sound Card Driver for Linux
+ * msnd_pinnacle.c / msnd_classic.c
+ *
+ * -- If MSND_CLASSIC is defined:
+ *
+ *     -> driver for Turtle Beach Classic/Monterey/Tahiti
+ *
+ * -- Else
+ *
+ *     -> driver for Turtle Beach Pinnacle/Fiji
+ *
+ * 12-3-2000  Modified IO port validation  Steve Sycamore
+ *
+ * Copyright (C) 1998 Andrew Veliath
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/firmware.h>
+#include <linux/isa.h>
+#include <linux/isapnp.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/asound.h>
+#include <sound/pcm.h>
+#include <sound/mpu401.h>
+
+#ifdef MSND_CLASSIC
+# ifndef __alpha__
+#  define SLOWIO
+# endif
+#endif
+#include "msnd.h"
+#ifdef MSND_CLASSIC
+#  include "msnd_classic.h"
+#  define LOGNAME			"msnd_classic"
+#else
+#  include "msnd_pinnacle.h"
+#  define LOGNAME			"snd_msnd_pinnacle"
+#endif
+
+static void __devinit set_default_audio_parameters(struct snd_msnd *chip)
+{
+	chip->play_sample_size = DEFSAMPLESIZE;
+	chip->play_sample_rate = DEFSAMPLERATE;
+	chip->play_channels = DEFCHANNELS;
+	chip->capture_sample_size = DEFSAMPLESIZE;
+	chip->capture_sample_rate = DEFSAMPLERATE;
+	chip->capture_channels = DEFCHANNELS;
+}
+
+static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage)
+{
+	switch (HIBYTE(wMessage)) {
+	case HIMT_PLAY_DONE: {
+		if (chip->banksPlayed < 3)
+			snd_printdd("%08X: HIMT_PLAY_DONE: %i\n",
+				(unsigned)jiffies, LOBYTE(wMessage));
+
+		if (chip->last_playbank == LOBYTE(wMessage)) {
+			snd_printdd("chip.last_playbank == LOBYTE(wMessage)\n");
+			break;
+		}
+		chip->banksPlayed++;
+
+		if (test_bit(F_WRITING, &chip->flags))
+			snd_msnd_DAPQ(chip, 0);
+
+		chip->last_playbank = LOBYTE(wMessage);
+		chip->playDMAPos += chip->play_period_bytes;
+		if (chip->playDMAPos > chip->playLimit)
+			chip->playDMAPos = 0;
+		snd_pcm_period_elapsed(chip->playback_substream);
+
+		break;
+	}
+	case HIMT_RECORD_DONE:
+		if (chip->last_recbank == LOBYTE(wMessage))
+			break;
+		chip->last_recbank = LOBYTE(wMessage);
+		chip->captureDMAPos += chip->capturePeriodBytes;
+		if (chip->captureDMAPos > (chip->captureLimit))
+			chip->captureDMAPos = 0;
+
+		if (test_bit(F_READING, &chip->flags))
+			snd_msnd_DARQ(chip, chip->last_recbank);
+
+		snd_pcm_period_elapsed(chip->capture_substream);
+		break;
+
+	case HIMT_DSP:
+		switch (LOBYTE(wMessage)) {
+#ifndef MSND_CLASSIC
+		case HIDSP_PLAY_UNDER:
+#endif
+		case HIDSP_INT_PLAY_UNDER:
+			snd_printd(KERN_WARNING LOGNAME ": Play underflow %i\n",
+				chip->banksPlayed);
+			if (chip->banksPlayed > 2)
+				clear_bit(F_WRITING, &chip->flags);
+			break;
+
+		case HIDSP_INT_RECORD_OVER:
+			snd_printd(KERN_WARNING LOGNAME ": Record overflow\n");
+			clear_bit(F_READING, &chip->flags);
+			break;
+
+		default:
+			snd_printd(KERN_WARNING LOGNAME
+				   ": DSP message %d 0x%02x\n",
+				   LOBYTE(wMessage), LOBYTE(wMessage));
+			break;
+		}
+		break;
+
+	case HIMT_MIDI_IN_UCHAR:
+		if (chip->msndmidi_mpu)
+			snd_msndmidi_input_read(chip->msndmidi_mpu);
+		break;
+
+	default:
+		snd_printd(KERN_WARNING LOGNAME ": HIMT message %d 0x%02x\n",
+			   HIBYTE(wMessage), HIBYTE(wMessage));
+		break;
+	}
+}
+
+static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id)
+{
+	struct snd_msnd *chip = dev_id;
+	void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF;
+
+	/* Send ack to DSP */
+	/* inb(chip->io + HP_RXL); */
+
+	/* Evaluate queued DSP messages */
+	while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) {
+		u16 wTmp;
+
+		snd_msnd_eval_dsp_msg(chip,
+			readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead)));
+
+		wTmp = readw(chip->DSPQ + JQS_wHead) + 1;
+		if (wTmp > readw(chip->DSPQ + JQS_wSize))
+			writew(0, chip->DSPQ + JQS_wHead);
+		else
+			writew(wTmp, chip->DSPQ + JQS_wHead);
+	}
+	/* Send ack to DSP */
+	inb(chip->io + HP_RXL);
+	return IRQ_HANDLED;
+}
+
+
+static int snd_msnd_reset_dsp(long io, unsigned char *info)
+{
+	int timeout = 100;
+
+	outb(HPDSPRESET_ON, io + HP_DSPR);
+	msleep(1);
+#ifndef MSND_CLASSIC
+	if (info)
+		*info = inb(io + HP_INFO);
+#endif
+	outb(HPDSPRESET_OFF, io + HP_DSPR);
+	msleep(1);
+	while (timeout-- > 0) {
+		if (inb(io + HP_CVR) == HP_CVR_DEF)
+			return 0;
+		msleep(1);
+	}
+	snd_printk(KERN_ERR LOGNAME ": Cannot reset DSP\n");
+
+	return -EIO;
+}
+
+static int __devinit snd_msnd_probe(struct snd_card *card)
+{
+	struct snd_msnd *chip = card->private_data;
+	unsigned char info;
+#ifndef MSND_CLASSIC
+	char *xv, *rev = NULL;
+	char *pin = "TB Pinnacle", *fiji = "TB Fiji";
+	char *pinfiji = "TB Pinnacle/Fiji";
+#endif
+
+	if (!request_region(chip->io, DSP_NUMIO, "probing")) {
+		snd_printk(KERN_ERR LOGNAME ": I/O port conflict\n");
+		return -ENODEV;
+	}
+
+	if (snd_msnd_reset_dsp(chip->io, &info) < 0) {
+		release_region(chip->io, DSP_NUMIO);
+		return -ENODEV;
+	}
+
+#ifdef MSND_CLASSIC
+	strcpy(card->shortname, "Classic/Tahiti/Monterey");
+	strcpy(card->longname, "Turtle Beach Multisound");
+	printk(KERN_INFO LOGNAME ": %s, "
+	       "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n",
+	       card->shortname,
+	       chip->io, chip->io + DSP_NUMIO - 1,
+	       chip->irq,
+	       chip->base, chip->base + 0x7fff);
+#else
+	switch (info >> 4) {
+	case 0xf:
+		xv = "<= 1.15";
+		break;
+	case 0x1:
+		xv = "1.18/1.2";
+		break;
+	case 0x2:
+		xv = "1.3";
+		break;
+	case 0x3:
+		xv = "1.4";
+		break;
+	default:
+		xv = "unknown";
+		break;
+	}
+
+	switch (info & 0x7) {
+	case 0x0:
+		rev = "I";
+		strcpy(card->shortname, pin);
+		break;
+	case 0x1:
+		rev = "F";
+		strcpy(card->shortname, pin);
+		break;
+	case 0x2:
+		rev = "G";
+		strcpy(card->shortname, pin);
+		break;
+	case 0x3:
+		rev = "H";
+		strcpy(card->shortname, pin);
+		break;
+	case 0x4:
+		rev = "E";
+		strcpy(card->shortname, fiji);
+		break;
+	case 0x5:
+		rev = "C";
+		strcpy(card->shortname, fiji);
+		break;
+	case 0x6:
+		rev = "D";
+		strcpy(card->shortname, fiji);
+		break;
+	case 0x7:
+		rev = "A-B (Fiji) or A-E (Pinnacle)";
+		strcpy(card->shortname, pinfiji);
+		break;
+	}
+	strcpy(card->longname, "Turtle Beach Multisound Pinnacle");
+	printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, "
+	       "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n",
+	       card->shortname,
+	       rev, xv,
+	       chip->io, chip->io + DSP_NUMIO - 1,
+	       chip->irq,
+	       chip->base, chip->base + 0x7fff);
+#endif
+
+	release_region(chip->io, DSP_NUMIO);
+	return 0;
+}
+
+static int snd_msnd_init_sma(struct snd_msnd *chip)
+{
+	static int initted;
+	u16 mastVolLeft, mastVolRight;
+	unsigned long flags;
+
+#ifdef MSND_CLASSIC
+	outb(chip->memid, chip->io + HP_MEMM);
+#endif
+	outb(HPBLKSEL_0, chip->io + HP_BLKS);
+	/* Motorola 56k shared memory base */
+	chip->SMA = chip->mappedbase + SMA_STRUCT_START;
+
+	if (initted) {
+		mastVolLeft = readw(chip->SMA + SMA_wCurrMastVolLeft);
+		mastVolRight = readw(chip->SMA + SMA_wCurrMastVolRight);
+	} else
+		mastVolLeft = mastVolRight = 0;
+	memset_io(chip->mappedbase, 0, 0x8000);
+
+	/* Critical section: bank 1 access */
+	spin_lock_irqsave(&chip->lock, flags);
+	outb(HPBLKSEL_1, chip->io + HP_BLKS);
+	memset_io(chip->mappedbase, 0, 0x8000);
+	outb(HPBLKSEL_0, chip->io + HP_BLKS);
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+	/* Digital audio play queue */
+	chip->DAPQ = chip->mappedbase + DAPQ_OFFSET;
+	snd_msnd_init_queue(chip->DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE);
+
+	/* Digital audio record queue */
+	chip->DARQ = chip->mappedbase + DARQ_OFFSET;
+	snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE);
+
+	/* MIDI out queue */
+	chip->MODQ = chip->mappedbase + MODQ_OFFSET;
+	snd_msnd_init_queue(chip->MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE);
+
+	/* MIDI in queue */
+	chip->MIDQ = chip->mappedbase + MIDQ_OFFSET;
+	snd_msnd_init_queue(chip->MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE);
+
+	/* DSP -> host message queue */
+	chip->DSPQ = chip->mappedbase + DSPQ_OFFSET;
+	snd_msnd_init_queue(chip->DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE);
+
+	/* Setup some DSP values */
+#ifndef MSND_CLASSIC
+	writew(1, chip->SMA + SMA_wCurrPlayFormat);
+	writew(chip->play_sample_size, chip->SMA + SMA_wCurrPlaySampleSize);
+	writew(chip->play_channels, chip->SMA + SMA_wCurrPlayChannels);
+	writew(chip->play_sample_rate, chip->SMA + SMA_wCurrPlaySampleRate);
+#endif
+	writew(chip->play_sample_rate, chip->SMA + SMA_wCalFreqAtoD);
+	writew(mastVolLeft, chip->SMA + SMA_wCurrMastVolLeft);
+	writew(mastVolRight, chip->SMA + SMA_wCurrMastVolRight);
+#ifndef MSND_CLASSIC
+	writel(0x00010000, chip->SMA + SMA_dwCurrPlayPitch);
+	writel(0x00000001, chip->SMA + SMA_dwCurrPlayRate);
+#endif
+	writew(0x303, chip->SMA + SMA_wCurrInputTagBits);
+
+	initted = 1;
+
+	return 0;
+}
+
+
+static int upload_dsp_code(struct snd_card *card)
+{
+	struct snd_msnd *chip = card->private_data;
+	const struct firmware *init_fw = NULL, *perm_fw = NULL;
+	int err;
+
+	outb(HPBLKSEL_0, chip->io + HP_BLKS);
+
+	err = request_firmware(&init_fw, INITCODEFILE, card->dev);
+	if (err < 0) {
+		printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE);
+		goto cleanup1;
+	}
+	err = request_firmware(&perm_fw, PERMCODEFILE, card->dev);
+	if (err < 0) {
+		printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE);
+		goto cleanup;
+	}
+
+	memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size);
+	if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) {
+		printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n");
+		err = -ENODEV;
+		goto cleanup;
+	}
+	printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n");
+	err = 0;
+
+cleanup:
+	release_firmware(perm_fw);
+cleanup1:
+	release_firmware(init_fw);
+	return err;
+}
+
+#ifdef MSND_CLASSIC
+static void reset_proteus(struct snd_msnd *chip)
+{
+	outb(HPPRORESET_ON, chip->io + HP_PROR);
+	msleep(TIME_PRO_RESET);
+	outb(HPPRORESET_OFF, chip->io + HP_PROR);
+	msleep(TIME_PRO_RESET_DONE);
+}
+#endif
+
+static int snd_msnd_initialize(struct snd_card *card)
+{
+	struct snd_msnd *chip = card->private_data;
+	int err, timeout;
+
+#ifdef MSND_CLASSIC
+	outb(HPWAITSTATE_0, chip->io + HP_WAIT);
+	outb(HPBITMODE_16, chip->io + HP_BITM);
+
+	reset_proteus(chip);
+#endif
+	err = snd_msnd_init_sma(chip);
+	if (err < 0) {
+		printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n");
+		return err;
+	}
+
+	err = snd_msnd_reset_dsp(chip->io, NULL);
+	if (err < 0)
+		return err;
+
+	err = upload_dsp_code(card);
+	if (err < 0) {
+		printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n");
+		return err;
+	}
+
+	timeout = 200;
+
+	while (readw(chip->mappedbase)) {
+		msleep(1);
+		if (!timeout--) {
+			snd_printd(KERN_ERR LOGNAME ": DSP reset timeout\n");
+			return -EIO;
+		}
+	}
+
+	snd_msndmix_setup(chip);
+	return 0;
+}
+
+static int snd_msnd_dsp_full_reset(struct snd_card *card)
+{
+	struct snd_msnd *chip = card->private_data;
+	int rv;
+
+	if (test_bit(F_RESETTING, &chip->flags) || ++chip->nresets > 10)
+		return 0;
+
+	set_bit(F_RESETTING, &chip->flags);
+	snd_msnd_dsp_halt(chip, NULL);	/* Unconditionally halt */
+
+	rv = snd_msnd_initialize(card);
+	if (rv)
+		printk(KERN_WARNING LOGNAME ": DSP reset failed\n");
+	snd_msndmix_force_recsrc(chip, 0);
+	clear_bit(F_RESETTING, &chip->flags);
+	return rv;
+}
+
+static int snd_msnd_dev_free(struct snd_device *device)
+{
+	snd_printdd("snd_msnd_chip_free()\n");
+	return 0;
+}
+
+static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
+{
+	if (snd_msnd_send_dsp_cmd(chip, cmd) == 0)
+		return 0;
+	snd_msnd_dsp_full_reset(chip->card);
+	return snd_msnd_send_dsp_cmd(chip, cmd);
+}
+
+static int __devinit snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
+{
+	snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate);
+	writew(srate, chip->SMA + SMA_wCalFreqAtoD);
+	if (chip->calibrate_signal == 0)
+		writew(readw(chip->SMA + SMA_wCurrHostStatusFlags)
+		       | 0x0001, chip->SMA + SMA_wCurrHostStatusFlags);
+	else
+		writew(readw(chip->SMA + SMA_wCurrHostStatusFlags)
+		       & ~0x0001, chip->SMA + SMA_wCurrHostStatusFlags);
+	if (snd_msnd_send_word(chip, 0, 0, HDEXAR_CAL_A_TO_D) == 0 &&
+	    snd_msnd_send_dsp_cmd_chk(chip, HDEX_AUX_REQ) == 0) {
+		schedule_timeout_interruptible(msecs_to_jiffies(333));
+		return 0;
+	}
+	printk(KERN_WARNING LOGNAME ": ADC calibration failed\n");
+	return -EIO;
+}
+
+/*
+ * ALSA callback function, called when attempting to open the MIDI device.
+ */
+static int snd_msnd_mpu401_open(struct snd_mpu401 *mpu)
+{
+	snd_msnd_enable_irq(mpu->private_data);
+	snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_START);
+	return 0;
+}
+
+static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu)
+{
+	snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_STOP);
+	snd_msnd_disable_irq(mpu->private_data);
+}
+
+static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+
+static int __devinit snd_msnd_attach(struct snd_card *card)
+{
+	struct snd_msnd *chip = card->private_data;
+	int err;
+	static struct snd_device_ops ops = {
+		.dev_free =      snd_msnd_dev_free,
+		};
+
+	err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname,
+			  chip);
+	if (err < 0) {
+		printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
+		return err;
+	}
+	request_region(chip->io, DSP_NUMIO, card->shortname);
+
+	if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) {
+		printk(KERN_ERR LOGNAME
+			": unable to grab memory region 0x%lx-0x%lx\n",
+			chip->base, chip->base + BUFFSIZE - 1);
+		release_region(chip->io, DSP_NUMIO);
+		free_irq(chip->irq, chip);
+		return -EBUSY;
+	}
+	chip->mappedbase = ioremap_nocache(chip->base, 0x8000);
+	if (!chip->mappedbase) {
+		printk(KERN_ERR LOGNAME
+			": unable to map memory region 0x%lx-0x%lx\n",
+			chip->base, chip->base + BUFFSIZE - 1);
+		err = -EIO;
+		goto err_release_region;
+	}
+
+	err = snd_msnd_dsp_full_reset(card);
+	if (err < 0)
+		goto err_release_region;
+
+	/* Register device */
+	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+	if (err < 0)
+		goto err_release_region;
+
+	err = snd_msnd_pcm(card, 0, NULL);
+	if (err < 0) {
+		printk(KERN_ERR LOGNAME ": error creating new PCM device\n");
+		goto err_release_region;
+	}
+
+	err = snd_msndmix_new(card);
+	if (err < 0) {
+		printk(KERN_ERR LOGNAME ": error creating new Mixer device\n");
+		goto err_release_region;
+	}
+
+
+	if (mpu_io[0] != SNDRV_AUTO_PORT) {
+		struct snd_mpu401 *mpu;
+
+		err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
+					  mpu_io[0],
+					  MPU401_MODE_INPUT |
+					  MPU401_MODE_OUTPUT,
+					  mpu_irq[0], IRQF_DISABLED,
+					  &chip->rmidi);
+		if (err < 0) {
+			printk(KERN_ERR LOGNAME
+				": error creating new Midi device\n");
+			goto err_release_region;
+		}
+		mpu = chip->rmidi->private_data;
+
+		mpu->open_input = snd_msnd_mpu401_open;
+		mpu->close_input = snd_msnd_mpu401_close;
+		mpu->private_data = chip;
+	}
+
+	disable_irq(chip->irq);
+	snd_msnd_calibrate_adc(chip, chip->play_sample_rate);
+	snd_msndmix_force_recsrc(chip, 0);
+
+	err = snd_card_register(card);
+	if (err < 0)
+		goto err_release_region;
+
+	return 0;
+
+err_release_region:
+	if (chip->mappedbase)
+		iounmap(chip->mappedbase);
+	release_mem_region(chip->base, BUFFSIZE);
+	release_region(chip->io, DSP_NUMIO);
+	free_irq(chip->irq, chip);
+	return err;
+}
+
+
+static void __devexit snd_msnd_unload(struct snd_card *card)
+{
+	struct snd_msnd *chip = card->private_data;
+
+	iounmap(chip->mappedbase);
+	release_mem_region(chip->base, BUFFSIZE);
+	release_region(chip->io, DSP_NUMIO);
+	free_irq(chip->irq, chip);
+	snd_card_free(card);
+}
+
+#ifndef MSND_CLASSIC
+
+/* Pinnacle/Fiji Logical Device Configuration */
+
+static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value)
+{
+	outb(reg, cfg);
+	outb(value, cfg + 1);
+	if (value != inb(cfg + 1)) {
+		printk(KERN_ERR LOGNAME ": snd_msnd_write_cfg: I/O error\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
+{
+	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+		return -EIO;
+	if (snd_msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io)))
+		return -EIO;
+	if (snd_msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io)))
+		return -EIO;
+	return 0;
+}
+
+static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
+{
+	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+		return -EIO;
+	if (snd_msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io)))
+		return -EIO;
+	if (snd_msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io)))
+		return -EIO;
+	return 0;
+}
+
+static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
+{
+	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+		return -EIO;
+	if (snd_msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq)))
+		return -EIO;
+	if (snd_msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE))
+		return -EIO;
+	return 0;
+}
+
+static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem)
+{
+	u16 wmem;
+
+	mem >>= 8;
+	wmem = (u16)(mem & 0xfff);
+	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+		return -EIO;
+	if (snd_msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem)))
+		return -EIO;
+	if (snd_msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem)))
+		return -EIO;
+	if (wmem && snd_msnd_write_cfg(cfg, IREG_MEMCONTROL,
+				       MEMTYPE_HIADDR | MEMTYPE_16BIT))
+		return -EIO;
+	return 0;
+}
+
+static int __devinit snd_msnd_activate_logical(int cfg, int num)
+{
+	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+		return -EIO;
+	if (snd_msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE))
+		return -EIO;
+	return 0;
+}
+
+static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
+						u16 io1, u16 irq, int mem)
+{
+	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+		return -EIO;
+	if (snd_msnd_write_cfg_io0(cfg, num, io0))
+		return -EIO;
+	if (snd_msnd_write_cfg_io1(cfg, num, io1))
+		return -EIO;
+	if (snd_msnd_write_cfg_irq(cfg, num, irq))
+		return -EIO;
+	if (snd_msnd_write_cfg_mem(cfg, num, mem))
+		return -EIO;
+	if (snd_msnd_activate_logical(cfg, num))
+		return -EIO;
+	return 0;
+}
+
+static int __devinit snd_msnd_pinnacle_cfg_reset(int cfg)
+{
+	int i;
+
+	/* Reset devices if told to */
+	printk(KERN_INFO LOGNAME ": Resetting all devices\n");
+	for (i = 0; i < 4; ++i)
+		if (snd_msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0))
+			return -EIO;
+
+	return 0;
+}
+#endif
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+
+module_param_array(index, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(index, "Index value for msnd_pinnacle soundcard.");
+module_param_array(id, charp, NULL, S_IRUGO);
+MODULE_PARM_DESC(id, "ID string for msnd_pinnacle soundcard.");
+
+static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+
+static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+
+#ifndef MSND_CLASSIC
+/* Extra Peripheral Configuration (Default: Disable) */
+static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static int ide_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+
+static long joystick_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+/* If we have the digital daugherboard... */
+static int digital[SNDRV_CARDS];
+
+/* Extra Peripheral Configuration */
+static int reset[SNDRV_CARDS];
+#endif
+
+static int write_ndelay[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 };
+
+static int calibrate_signal;
+
+#ifdef CONFIG_PNP
+static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+module_param_array(isapnp, bool, NULL, 0444);
+MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
+#define has_isapnp(x) isapnp[x]
+#else
+#define has_isapnp(x) 0
+#endif
+
+MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
+MODULE_DESCRIPTION("Turtle Beach " LONGNAME " Linux Driver");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(INITCODEFILE);
+MODULE_FIRMWARE(PERMCODEFILE);
+
+module_param_array(io, long, NULL, S_IRUGO);
+MODULE_PARM_DESC(io, "IO port #");
+module_param_array(irq, int, NULL, S_IRUGO);
+module_param_array(mem, long, NULL, S_IRUGO);
+module_param_array(write_ndelay, int, NULL, S_IRUGO);
+module_param(calibrate_signal, int, S_IRUGO);
+#ifndef MSND_CLASSIC
+module_param_array(digital, int, NULL, S_IRUGO);
+module_param_array(cfg, long, NULL, S_IRUGO);
+module_param_array(reset, int, 0, S_IRUGO);
+module_param_array(mpu_io, long, NULL, S_IRUGO);
+module_param_array(mpu_irq, int, NULL, S_IRUGO);
+module_param_array(ide_io0, long, NULL, S_IRUGO);
+module_param_array(ide_io1, long, NULL, S_IRUGO);
+module_param_array(ide_irq, int, NULL, S_IRUGO);
+module_param_array(joystick_io, long, NULL, S_IRUGO);
+#endif
+
+
+static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i)
+{
+	if (io[i] == SNDRV_AUTO_PORT)
+		return 0;
+
+	if (irq[i] == SNDRV_AUTO_PORT || mem[i] == SNDRV_AUTO_PORT) {
+		printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n");
+		return 0;
+	}
+
+#ifdef MSND_CLASSIC
+	if (!(io[i] == 0x290 ||
+	      io[i] == 0x260 ||
+	      io[i] == 0x250 ||
+	      io[i] == 0x240 ||
+	      io[i] == 0x230 ||
+	      io[i] == 0x220 ||
+	      io[i] == 0x210 ||
+	      io[i] == 0x3e0)) {
+		printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set "
+			" to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, "
+			"or 0x3E0\n");
+		return 0;
+	}
+#else
+	if (io[i] < 0x100 || io[i] > 0x3e0 || (io[i] % 0x10) != 0) {
+		printk(KERN_ERR LOGNAME
+			": \"io\" - DSP I/O base must within the range 0x100 "
+			"to 0x3E0 and must be evenly divisible by 0x10\n");
+		return 0;
+	}
+#endif /* MSND_CLASSIC */
+
+	if (!(irq[i] == 5 ||
+	      irq[i] == 7 ||
+	      irq[i] == 9 ||
+	      irq[i] == 10 ||
+	      irq[i] == 11 ||
+	      irq[i] == 12)) {
+		printk(KERN_ERR LOGNAME
+			": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n");
+		return 0;
+	}
+
+	if (!(mem[i] == 0xb0000 ||
+	      mem[i] == 0xc8000 ||
+	      mem[i] == 0xd0000 ||
+	      mem[i] == 0xd8000 ||
+	      mem[i] == 0xe0000 ||
+	      mem[i] == 0xe8000)) {
+		printk(KERN_ERR LOGNAME ": \"mem\" - must be set to "
+		       "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or "
+		       "0xe8000\n");
+		return 0;
+	}
+
+#ifndef MSND_CLASSIC
+	if (cfg[i] == SNDRV_AUTO_PORT) {
+		printk(KERN_INFO LOGNAME ": Assuming PnP mode\n");
+	} else if (cfg[i] != 0x250 && cfg[i] != 0x260 && cfg[i] != 0x270) {
+		printk(KERN_INFO LOGNAME
+			": Config port must be 0x250, 0x260 or 0x270 "
+			"(or unspecified for PnP mode)\n");
+		return 0;
+	}
+#endif /* MSND_CLASSIC */
+
+	return 1;
+}
+
+static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
+{
+	int err;
+	struct snd_card *card;
+	struct snd_msnd *chip;
+
+	if (has_isapnp(idx) || cfg[idx] == SNDRV_AUTO_PORT) {
+		printk(KERN_INFO LOGNAME ": Assuming PnP mode\n");
+		return -ENODEV;
+	}
+
+	err = snd_card_create(index[idx], id[idx], THIS_MODULE,
+			      sizeof(struct snd_msnd), &card);
+	if (err < 0)
+		return err;
+
+	snd_card_set_dev(card, pdev);
+	chip = card->private_data;
+	chip->card = card;
+
+#ifdef MSND_CLASSIC
+	switch (irq[idx]) {
+	case 5:
+		chip->irqid = HPIRQ_5; break;
+	case 7:
+		chip->irqid = HPIRQ_7; break;
+	case 9:
+		chip->irqid = HPIRQ_9; break;
+	case 10:
+		chip->irqid = HPIRQ_10; break;
+	case 11:
+		chip->irqid = HPIRQ_11; break;
+	case 12:
+		chip->irqid = HPIRQ_12; break;
+	}
+
+	switch (mem[idx]) {
+	case 0xb0000:
+		chip->memid = HPMEM_B000; break;
+	case 0xc8000:
+		chip->memid = HPMEM_C800; break;
+	case 0xd0000:
+		chip->memid = HPMEM_D000; break;
+	case 0xd8000:
+		chip->memid = HPMEM_D800; break;
+	case 0xe0000:
+		chip->memid = HPMEM_E000; break;
+	case 0xe8000:
+		chip->memid = HPMEM_E800; break;
+	}
+#else
+	printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n",
+			cfg[idx]);
+
+	if (!request_region(cfg[idx], 2, "Pinnacle/Fiji Config")) {
+		printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n",
+			   cfg[idx]);
+		snd_card_free(card);
+		return -EIO;
+	}
+	if (reset[idx])
+		if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) {
+			err = -EIO;
+			goto cfg_error;
+		}
+
+	/* DSP */
+	err = snd_msnd_write_cfg_logical(cfg[idx], 0,
+					 io[idx], 0,
+					 irq[idx], mem[idx]);
+
+	if (err)
+		goto cfg_error;
+
+	/* The following are Pinnacle specific */
+
+	/* MPU */
+	if (mpu_io[idx] != SNDRV_AUTO_PORT
+	    && mpu_irq[idx] != SNDRV_AUTO_IRQ) {
+		printk(KERN_INFO LOGNAME
+		       ": Configuring MPU to I/O 0x%lx IRQ %d\n",
+		       mpu_io[idx], mpu_irq[idx]);
+		err = snd_msnd_write_cfg_logical(cfg[idx], 1,
+						 mpu_io[idx], 0,
+						 mpu_irq[idx], 0);
+
+		if (err)
+			goto cfg_error;
+	}
+
+	/* IDE */
+	if (ide_io0[idx] != SNDRV_AUTO_PORT
+	    && ide_io1[idx] != SNDRV_AUTO_PORT
+	    && ide_irq[idx] != SNDRV_AUTO_IRQ) {
+		printk(KERN_INFO LOGNAME
+		       ": Configuring IDE to I/O 0x%lx, 0x%lx IRQ %d\n",
+		       ide_io0[idx], ide_io1[idx], ide_irq[idx]);
+		err = snd_msnd_write_cfg_logical(cfg[idx], 2,
+						 ide_io0[idx], ide_io1[idx],
+						 ide_irq[idx], 0);
+
+		if (err)
+			goto cfg_error;
+	}
+
+	/* Joystick */
+	if (joystick_io[idx] != SNDRV_AUTO_PORT) {
+		printk(KERN_INFO LOGNAME
+		       ": Configuring joystick to I/O 0x%lx\n",
+		       joystick_io[idx]);
+		err = snd_msnd_write_cfg_logical(cfg[idx], 3,
+						 joystick_io[idx], 0,
+						 0, 0);
+
+		if (err)
+			goto cfg_error;
+	}
+	release_region(cfg[idx], 2);
+
+#endif /* MSND_CLASSIC */
+
+	set_default_audio_parameters(chip);
+#ifdef MSND_CLASSIC
+	chip->type = msndClassic;
+#else
+	chip->type = msndPinnacle;
+#endif
+	chip->io = io[idx];
+	chip->irq = irq[idx];
+	chip->base = mem[idx];
+
+	chip->calibrate_signal = calibrate_signal ? 1 : 0;
+	chip->recsrc = 0;
+	chip->dspq_data_buff = DSPQ_DATA_BUFF;
+	chip->dspq_buff_size = DSPQ_BUFF_SIZE;
+	if (write_ndelay[idx])
+		clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
+	else
+		set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
+#ifndef MSND_CLASSIC
+	if (digital[idx])
+		set_bit(F_HAVEDIGITAL, &chip->flags);
+#endif
+	spin_lock_init(&chip->lock);
+	err = snd_msnd_probe(card);
+	if (err < 0) {
+		printk(KERN_ERR LOGNAME ": Probe failed\n");
+		snd_card_free(card);
+		return err;
+	}
+
+	err = snd_msnd_attach(card);
+	if (err < 0) {
+		printk(KERN_ERR LOGNAME ": Attach failed\n");
+		snd_card_free(card);
+		return err;
+	}
+	dev_set_drvdata(pdev, card);
+
+	return 0;
+
+#ifndef MSND_CLASSIC
+cfg_error:
+	release_region(cfg[idx], 2);
+	snd_card_free(card);
+	return err;
+#endif
+}
+
+static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
+{
+	snd_msnd_unload(dev_get_drvdata(pdev));
+	dev_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+#define DEV_NAME "msnd-pinnacle"
+
+static struct isa_driver snd_msnd_driver = {
+	.match		= snd_msnd_isa_match,
+	.probe		= snd_msnd_isa_probe,
+	.remove		= __devexit_p(snd_msnd_isa_remove),
+	/* FIXME: suspend, resume */
+	.driver		= {
+		.name	= DEV_NAME
+	},
+};
+
+#ifdef CONFIG_PNP
+static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard,
+					 const struct pnp_card_device_id *pid)
+{
+	static int idx;
+	struct pnp_dev *pnp_dev;
+	struct pnp_dev *mpu_dev;
+	struct snd_card *card;
+	struct snd_msnd *chip;
+	int ret;
+
+	for ( ; idx < SNDRV_CARDS; idx++) {
+		if (has_isapnp(idx))
+			break;
+	}
+	if (idx >= SNDRV_CARDS)
+		return -ENODEV;
+
+	/*
+	 * Check that we still have room for another sound card ...
+	 */
+	pnp_dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
+	if (!pnp_dev)
+		return -ENODEV;
+
+	mpu_dev = pnp_request_card_device(pcard, pid->devs[1].id, NULL);
+	if (!mpu_dev)
+		return -ENODEV;
+
+	if (!pnp_is_active(pnp_dev) && pnp_activate_dev(pnp_dev) < 0) {
+		printk(KERN_INFO "msnd_pinnacle: device is inactive\n");
+		return -EBUSY;
+	}
+
+	if (!pnp_is_active(mpu_dev) && pnp_activate_dev(mpu_dev) < 0) {
+		printk(KERN_INFO "msnd_pinnacle: MPU device is inactive\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * Create a new ALSA sound card entry, in anticipation
+	 * of detecting our hardware ...
+	 */
+	ret = snd_card_create(index[idx], id[idx], THIS_MODULE,
+			      sizeof(struct snd_msnd), &card);
+	if (ret < 0)
+		return ret;
+
+	chip = card->private_data;
+	chip->card = card;
+	snd_card_set_dev(card, &pcard->card->dev);
+
+	/*
+	 * Read the correct parameters off the ISA PnP bus ...
+	 */
+	io[idx] = pnp_port_start(pnp_dev, 0);
+	irq[idx] = pnp_irq(pnp_dev, 0);
+	mem[idx] = pnp_mem_start(pnp_dev, 0);
+	mpu_io[idx] = pnp_port_start(mpu_dev, 0);
+	mpu_irq[idx] = pnp_irq(mpu_dev, 0);
+
+	set_default_audio_parameters(chip);
+#ifdef MSND_CLASSIC
+	chip->type = msndClassic;
+#else
+	chip->type = msndPinnacle;
+#endif
+	chip->io = io[idx];
+	chip->irq = irq[idx];
+	chip->base = mem[idx];
+
+	chip->calibrate_signal = calibrate_signal ? 1 : 0;
+	chip->recsrc = 0;
+	chip->dspq_data_buff = DSPQ_DATA_BUFF;
+	chip->dspq_buff_size = DSPQ_BUFF_SIZE;
+	if (write_ndelay[idx])
+		clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
+	else
+		set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
+#ifndef MSND_CLASSIC
+	if (digital[idx])
+		set_bit(F_HAVEDIGITAL, &chip->flags);
+#endif
+	spin_lock_init(&chip->lock);
+	ret = snd_msnd_probe(card);
+	if (ret < 0) {
+		printk(KERN_ERR LOGNAME ": Probe failed\n");
+		goto _release_card;
+	}
+
+	ret = snd_msnd_attach(card);
+	if (ret < 0) {
+		printk(KERN_ERR LOGNAME ": Attach failed\n");
+		goto _release_card;
+	}
+
+	pnp_set_card_drvdata(pcard, card);
+	++idx;
+	return 0;
+
+_release_card:
+	snd_card_free(card);
+	return ret;
+}
+
+static void __devexit snd_msnd_pnp_remove(struct pnp_card_link *pcard)
+{
+	snd_msnd_unload(pnp_get_card_drvdata(pcard));
+	pnp_set_card_drvdata(pcard, NULL);
+}
+
+static int isa_registered;
+static int pnp_registered;
+
+static struct pnp_card_device_id msnd_pnpids[] = {
+	/* Pinnacle PnP */
+	{ .id = "BVJ0440", .devs = { { "TBS0000" }, { "TBS0001" } } },
+	{ .id = "" }	/* end */
+};
+
+MODULE_DEVICE_TABLE(pnp_card, msnd_pnpids);
+
+static struct pnp_card_driver msnd_pnpc_driver = {
+	.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
+	.name = "msnd_pinnacle",
+	.id_table = msnd_pnpids,
+	.probe = snd_msnd_pnp_detect,
+	.remove = __devexit_p(snd_msnd_pnp_remove),
+};
+#endif /* CONFIG_PNP */
+
+static int __init snd_msnd_init(void)
+{
+	int err;
+
+	err = isa_register_driver(&snd_msnd_driver, SNDRV_CARDS);
+#ifdef CONFIG_PNP
+	if (!err)
+		isa_registered = 1;
+
+	err = pnp_register_card_driver(&msnd_pnpc_driver);
+	if (!err)
+		pnp_registered = 1;
+
+	if (isa_registered)
+		err = 0;
+#endif
+	return err;
+}
+
+static void __exit snd_msnd_exit(void)
+{
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		pnp_unregister_card_driver(&msnd_pnpc_driver);
+	if (isa_registered)
+#endif
+		isa_unregister_driver(&snd_msnd_driver);
+}
+
+module_init(snd_msnd_init);
+module_exit(snd_msnd_exit);
+
diff --git a/sound/isa/msnd/msnd_pinnacle.h b/sound/isa/msnd/msnd_pinnacle.h
new file mode 100644
index 0000000..48318d1
--- /dev/null
+++ b/sound/isa/msnd/msnd_pinnacle.h
@@ -0,0 +1,181 @@
+/*********************************************************************
+ *
+ * msnd_pinnacle.h
+ *
+ * Turtle Beach MultiSound Sound Card Driver for Linux
+ *
+ * Some parts of this header file were derived from the Turtle Beach
+ * MultiSound Driver Development Kit.
+ *
+ * Copyright (C) 1998 Andrew Veliath
+ * Copyright (C) 1993 Turtle Beach Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************/
+#ifndef __MSND_PINNACLE_H
+#define __MSND_PINNACLE_H
+
+#define DSP_NUMIO				0x08
+
+#define IREG_LOGDEVICE				0x07
+#define IREG_ACTIVATE				0x30
+#define LD_ACTIVATE				0x01
+#define LD_DISACTIVATE				0x00
+#define IREG_EECONTROL				0x3F
+#define IREG_MEMBASEHI				0x40
+#define IREG_MEMBASELO				0x41
+#define IREG_MEMCONTROL				0x42
+#define IREG_MEMRANGEHI				0x43
+#define IREG_MEMRANGELO				0x44
+#define MEMTYPE_8BIT				0x00
+#define MEMTYPE_16BIT				0x02
+#define MEMTYPE_RANGE				0x00
+#define MEMTYPE_HIADDR				0x01
+#define IREG_IO0_BASEHI				0x60
+#define IREG_IO0_BASELO				0x61
+#define IREG_IO1_BASEHI				0x62
+#define IREG_IO1_BASELO				0x63
+#define IREG_IRQ_NUMBER				0x70
+#define IREG_IRQ_TYPE				0x71
+#define IRQTYPE_HIGH				0x02
+#define IRQTYPE_LOW				0x00
+#define IRQTYPE_LEVEL				0x01
+#define IRQTYPE_EDGE				0x00
+
+#define	HP_DSPR					0x04
+#define	HP_BLKS					0x04
+
+#define HPDSPRESET_OFF				2
+#define HPDSPRESET_ON				0
+
+#define HPBLKSEL_0				2
+#define HPBLKSEL_1				3
+
+#define	HIMT_DAT_OFF				0x03
+
+#define	HIDSP_PLAY_UNDER			0x00
+#define	HIDSP_INT_PLAY_UNDER			0x01
+#define	HIDSP_SSI_TX_UNDER  			0x02
+#define HIDSP_RECQ_OVERFLOW			0x08
+#define HIDSP_INT_RECORD_OVER			0x09
+#define HIDSP_SSI_RX_OVERFLOW			0x0a
+
+#define	HIDSP_MIDI_IN_OVER			0x10
+
+#define	HIDSP_MIDI_FRAME_ERR			0x11
+#define	HIDSP_MIDI_PARITY_ERR			0x12
+#define	HIDSP_MIDI_OVERRUN_ERR			0x13
+
+#define HIDSP_INPUT_CLIPPING			0x20
+#define	HIDSP_MIX_CLIPPING			0x30
+#define HIDSP_DAT_IN_OFF			0x21
+
+#define TIME_PRO_RESET_DONE			0x028A
+#define TIME_PRO_SYSEX				0x001E
+#define TIME_PRO_RESET				0x0032
+
+#define DAR_BUFF_SIZE				0x1000
+
+#define MIDQ_BUFF_SIZE				0x800
+#define DSPQ_BUFF_SIZE				0x5A0
+
+#define DSPQ_DATA_BUFF				0x7860
+
+#define MOP_WAVEHDR				0
+#define MOP_EXTOUT				1
+#define MOP_HWINIT				0xfe
+#define MOP_NONE				0xff
+#define MOP_MAX					1
+
+#define MIP_EXTIN				0
+#define MIP_WAVEHDR				1
+#define MIP_HWINIT				0xfe
+#define MIP_MAX					1
+
+/* Pinnacle/Fiji SMA Common Data */
+#define SMA_wCurrPlayBytes			0x0000
+#define SMA_wCurrRecordBytes			0x0002
+#define SMA_wCurrPlayVolLeft			0x0004
+#define SMA_wCurrPlayVolRight			0x0006
+#define SMA_wCurrInVolLeft			0x0008
+#define SMA_wCurrInVolRight			0x000a
+#define SMA_wCurrMHdrVolLeft			0x000c
+#define SMA_wCurrMHdrVolRight			0x000e
+#define SMA_dwCurrPlayPitch			0x0010
+#define SMA_dwCurrPlayRate			0x0014
+#define SMA_wCurrMIDIIOPatch			0x0018
+#define SMA_wCurrPlayFormat			0x001a
+#define SMA_wCurrPlaySampleSize			0x001c
+#define SMA_wCurrPlayChannels			0x001e
+#define SMA_wCurrPlaySampleRate			0x0020
+#define SMA_wCurrRecordFormat			0x0022
+#define SMA_wCurrRecordSampleSize		0x0024
+#define SMA_wCurrRecordChannels			0x0026
+#define SMA_wCurrRecordSampleRate		0x0028
+#define SMA_wCurrDSPStatusFlags			0x002a
+#define SMA_wCurrHostStatusFlags		0x002c
+#define SMA_wCurrInputTagBits			0x002e
+#define SMA_wCurrLeftPeak			0x0030
+#define SMA_wCurrRightPeak			0x0032
+#define SMA_bMicPotPosLeft			0x0034
+#define SMA_bMicPotPosRight			0x0035
+#define SMA_bMicPotMaxLeft			0x0036
+#define SMA_bMicPotMaxRight			0x0037
+#define SMA_bInPotPosLeft			0x0038
+#define SMA_bInPotPosRight			0x0039
+#define SMA_bAuxPotPosLeft			0x003a
+#define SMA_bAuxPotPosRight			0x003b
+#define SMA_bInPotMaxLeft			0x003c
+#define SMA_bInPotMaxRight			0x003d
+#define SMA_bAuxPotMaxLeft			0x003e
+#define SMA_bAuxPotMaxRight			0x003f
+#define SMA_bInPotMaxMethod			0x0040
+#define SMA_bAuxPotMaxMethod			0x0041
+#define SMA_wCurrMastVolLeft			0x0042
+#define SMA_wCurrMastVolRight			0x0044
+#define SMA_wCalFreqAtoD			0x0046
+#define SMA_wCurrAuxVolLeft			0x0048
+#define SMA_wCurrAuxVolRight			0x004a
+#define SMA_wCurrPlay1VolLeft			0x004c
+#define SMA_wCurrPlay1VolRight			0x004e
+#define SMA_wCurrPlay2VolLeft			0x0050
+#define SMA_wCurrPlay2VolRight			0x0052
+#define SMA_wCurrPlay3VolLeft			0x0054
+#define SMA_wCurrPlay3VolRight			0x0056
+#define SMA_wCurrPlay4VolLeft			0x0058
+#define SMA_wCurrPlay4VolRight			0x005a
+#define SMA_wCurrPlay1PeakLeft			0x005c
+#define SMA_wCurrPlay1PeakRight			0x005e
+#define SMA_wCurrPlay2PeakLeft			0x0060
+#define SMA_wCurrPlay2PeakRight			0x0062
+#define SMA_wCurrPlay3PeakLeft			0x0064
+#define SMA_wCurrPlay3PeakRight			0x0066
+#define SMA_wCurrPlay4PeakLeft			0x0068
+#define SMA_wCurrPlay4PeakRight			0x006a
+#define SMA_wCurrPlayPeakLeft			0x006c
+#define SMA_wCurrPlayPeakRight			0x006e
+#define SMA_wCurrDATSR				0x0070
+#define SMA_wCurrDATRXCHNL			0x0072
+#define SMA_wCurrDATTXCHNL			0x0074
+#define SMA_wCurrDATRXRate			0x0076
+#define SMA_dwDSPPlayCount			0x0078
+#define SMA__size				0x007c
+
+#define INITCODEFILE		"turtlebeach/pndspini.bin"
+#define PERMCODEFILE		"turtlebeach/pndsperm.bin"
+#define LONGNAME		"MultiSound (Pinnacle/Fiji)"
+
+#endif /* __MSND_PINNACLE_H */
diff --git a/sound/isa/msnd/msnd_pinnacle_mixer.c b/sound/isa/msnd/msnd_pinnacle_mixer.c
new file mode 100644
index 0000000..494058a
--- /dev/null
+++ b/sound/isa/msnd/msnd_pinnacle_mixer.c
@@ -0,0 +1,343 @@
+/***************************************************************************
+			  msnd_pinnacle_mixer.c  -  description
+			     -------------------
+    begin		: Fre Jun 7 2002
+    copyright 		: (C) 2002 by karsten wiese
+    email		: annabellesgarden@yahoo.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/io.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include "msnd.h"
+#include "msnd_pinnacle.h"
+
+
+#define MSND_MIXER_VOLUME	0
+#define MSND_MIXER_PCM		1
+#define MSND_MIXER_AUX		2	/* Input source 1  (aux1) */
+#define MSND_MIXER_IMIX		3	/*  Recording monitor  */
+#define MSND_MIXER_SYNTH	4
+#define MSND_MIXER_SPEAKER	5
+#define MSND_MIXER_LINE		6
+#define MSND_MIXER_MIC		7
+#define MSND_MIXER_RECLEV	11	/* Recording level */
+#define MSND_MIXER_IGAIN	12	/* Input gain */
+#define MSND_MIXER_OGAIN	13	/* Output gain */
+#define MSND_MIXER_DIGITAL	17	/* Digital (input) 1 */
+
+/*	Device mask bits	*/
+
+#define MSND_MASK_VOLUME	(1 << MSND_MIXER_VOLUME)
+#define MSND_MASK_SYNTH		(1 << MSND_MIXER_SYNTH)
+#define MSND_MASK_PCM		(1 << MSND_MIXER_PCM)
+#define MSND_MASK_SPEAKER	(1 << MSND_MIXER_SPEAKER)
+#define MSND_MASK_LINE		(1 << MSND_MIXER_LINE)
+#define MSND_MASK_MIC		(1 << MSND_MIXER_MIC)
+#define MSND_MASK_IMIX		(1 << MSND_MIXER_IMIX)
+#define MSND_MASK_RECLEV	(1 << MSND_MIXER_RECLEV)
+#define MSND_MASK_IGAIN		(1 << MSND_MIXER_IGAIN)
+#define MSND_MASK_OGAIN		(1 << MSND_MIXER_OGAIN)
+#define MSND_MASK_AUX		(1 << MSND_MIXER_AUX)
+#define MSND_MASK_DIGITAL	(1 << MSND_MIXER_DIGITAL)
+
+static int snd_msndmix_info_mux(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[3] = {
+		"Analog", "MASS", "SPDIF",
+	};
+	struct snd_msnd *chip = snd_kcontrol_chip(kcontrol);
+	unsigned items = test_bit(F_HAVEDIGITAL, &chip->flags) ? 3 : 2;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = items;
+	if (uinfo->value.enumerated.item >= items)
+		uinfo->value.enumerated.item = items - 1;
+	strcpy(uinfo->value.enumerated.name,
+		texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_msndmix_get_mux(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_msnd *chip = snd_kcontrol_chip(kcontrol);
+	/* MSND_MASK_IMIX is the default */
+	ucontrol->value.enumerated.item[0] = 0;
+
+	if (chip->recsrc & MSND_MASK_SYNTH) {
+		ucontrol->value.enumerated.item[0] = 1;
+	} else if ((chip->recsrc & MSND_MASK_DIGITAL) &&
+		 test_bit(F_HAVEDIGITAL, &chip->flags)) {
+		ucontrol->value.enumerated.item[0] = 2;
+	}
+
+
+	return 0;
+}
+
+static int snd_msndmix_set_mux(struct snd_msnd *chip, int val)
+{
+	unsigned newrecsrc;
+	int change;
+	unsigned char msndbyte;
+
+	switch (val) {
+	case 0:
+		newrecsrc = MSND_MASK_IMIX;
+		msndbyte = HDEXAR_SET_ANA_IN;
+		break;
+	case 1:
+		newrecsrc = MSND_MASK_SYNTH;
+		msndbyte = HDEXAR_SET_SYNTH_IN;
+		break;
+	case 2:
+		newrecsrc = MSND_MASK_DIGITAL;
+		msndbyte = HDEXAR_SET_DAT_IN;
+		break;
+	default:
+		return -EINVAL;
+	}
+	change  = newrecsrc != chip->recsrc;
+	if (change) {
+		change = 0;
+		if (!snd_msnd_send_word(chip, 0, 0, msndbyte))
+			if (!snd_msnd_send_dsp_cmd(chip, HDEX_AUX_REQ)) {
+				chip->recsrc = newrecsrc;
+				change = 1;
+			}
+	}
+	return change;
+}
+
+static int snd_msndmix_put_mux(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol);
+	return snd_msndmix_set_mux(msnd, ucontrol->value.enumerated.item[0]);
+}
+
+
+static int snd_msndmix_volume_info(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_msndmix_volume_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol);
+	int addr = kcontrol->private_value;
+	unsigned long flags;
+
+	spin_lock_irqsave(&msnd->mixer_lock, flags);
+	ucontrol->value.integer.value[0] = msnd->left_levels[addr] * 100;
+	ucontrol->value.integer.value[0] /= 0xFFFF;
+	ucontrol->value.integer.value[1] = msnd->right_levels[addr] * 100;
+	ucontrol->value.integer.value[1] /= 0xFFFF;
+	spin_unlock_irqrestore(&msnd->mixer_lock, flags);
+	return 0;
+}
+
+#define update_volm(a, b)						\
+	do {								\
+		writew((dev->left_levels[a] >> 1) *			\
+		       readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff,	\
+		       dev->SMA + SMA_##b##Left);			\
+		writew((dev->right_levels[a] >> 1)  *			\
+		       readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \
+		       dev->SMA + SMA_##b##Right);			\
+	} while (0);
+
+#define update_potm(d, s, ar)						\
+	do {								\
+		writeb((dev->left_levels[d] >> 8) *			\
+		       readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff, \
+		       dev->SMA + SMA_##s##Left);			\
+		writeb((dev->right_levels[d] >> 8) *			\
+		       readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \
+		       dev->SMA + SMA_##s##Right);			\
+		if (snd_msnd_send_word(dev, 0, 0, ar) == 0)		\
+			snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ);	\
+	} while (0);
+
+#define update_pot(d, s, ar)						\
+	do {								\
+		writeb(dev->left_levels[d] >> 8,			\
+		       dev->SMA + SMA_##s##Left);			\
+		writeb(dev->right_levels[d] >> 8,			\
+		       dev->SMA + SMA_##s##Right);			\
+		if (snd_msnd_send_word(dev, 0, 0, ar) == 0)		\
+			snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ);	\
+	} while (0);
+
+
+static int snd_msndmix_set(struct snd_msnd *dev, int d, int left, int right)
+{
+	int bLeft, bRight;
+	int wLeft, wRight;
+	int updatemaster = 0;
+
+	if (d >= LEVEL_ENTRIES)
+		return -EINVAL;
+
+	bLeft = left * 0xff / 100;
+	wLeft = left * 0xffff / 100;
+
+	bRight = right * 0xff / 100;
+	wRight = right * 0xffff / 100;
+
+	dev->left_levels[d] = wLeft;
+	dev->right_levels[d] = wRight;
+
+	switch (d) {
+		/* master volume unscaled controls */
+	case MSND_MIXER_LINE:			/* line pot control */
+		/* scaled by IMIX in digital mix */
+		writeb(bLeft, dev->SMA + SMA_bInPotPosLeft);
+		writeb(bRight, dev->SMA + SMA_bInPotPosRight);
+		if (snd_msnd_send_word(dev, 0, 0, HDEXAR_IN_SET_POTS) == 0)
+			snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ);
+		break;
+	case MSND_MIXER_MIC:			/* mic pot control */
+		if (dev->type == msndClassic)
+			return -EINVAL;
+		/* scaled by IMIX in digital mix */
+		writeb(bLeft, dev->SMA + SMA_bMicPotPosLeft);
+		writeb(bRight, dev->SMA + SMA_bMicPotPosRight);
+		if (snd_msnd_send_word(dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0)
+			snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ);
+		break;
+	case MSND_MIXER_VOLUME:		/* master volume */
+		writew(wLeft, dev->SMA + SMA_wCurrMastVolLeft);
+		writew(wRight, dev->SMA + SMA_wCurrMastVolRight);
+		/* fall through */
+
+	case MSND_MIXER_AUX:			/* aux pot control */
+		/* scaled by master volume */
+		/* fall through */
+
+		/* digital controls */
+	case MSND_MIXER_SYNTH:			/* synth vol (dsp mix) */
+	case MSND_MIXER_PCM:			/* pcm vol (dsp mix) */
+	case MSND_MIXER_IMIX:			/* input monitor (dsp mix) */
+		/* scaled by master volume */
+		updatemaster = 1;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (updatemaster) {
+		/* update master volume scaled controls */
+		update_volm(MSND_MIXER_PCM, wCurrPlayVol);
+		update_volm(MSND_MIXER_IMIX, wCurrInVol);
+		if (dev->type == msndPinnacle)
+			update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol);
+		update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS);
+	}
+
+	return 0;
+}
+
+static int snd_msndmix_volume_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol);
+	int change, addr = kcontrol->private_value;
+	int left, right;
+	unsigned long flags;
+
+	left = ucontrol->value.integer.value[0] % 101;
+	right = ucontrol->value.integer.value[1] % 101;
+	spin_lock_irqsave(&msnd->mixer_lock, flags);
+	change = msnd->left_levels[addr] != left
+		|| msnd->right_levels[addr] != right;
+	snd_msndmix_set(msnd, addr, left, right);
+	spin_unlock_irqrestore(&msnd->mixer_lock, flags);
+	return change;
+}
+
+
+#define DUMMY_VOLUME(xname, xindex, addr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+  .info = snd_msndmix_volume_info, \
+  .get = snd_msndmix_volume_get, .put = snd_msndmix_volume_put, \
+  .private_value = addr }
+
+
+static struct snd_kcontrol_new snd_msnd_controls[] = {
+DUMMY_VOLUME("Master Volume", 0, MSND_MIXER_VOLUME),
+DUMMY_VOLUME("PCM Volume", 0, MSND_MIXER_PCM),
+DUMMY_VOLUME("Aux Volume", 0, MSND_MIXER_AUX),
+DUMMY_VOLUME("Line Volume", 0, MSND_MIXER_LINE),
+DUMMY_VOLUME("Mic Volume", 0, MSND_MIXER_MIC),
+DUMMY_VOLUME("Monitor",	0, MSND_MIXER_IMIX),
+{
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Capture Source",
+	.info = snd_msndmix_info_mux,
+	.get = snd_msndmix_get_mux,
+	.put = snd_msndmix_put_mux,
+}
+};
+
+
+int __devinit snd_msndmix_new(struct snd_card *card)
+{
+	struct snd_msnd *chip = card->private_data;
+	unsigned int idx;
+	int err;
+
+	if (snd_BUG_ON(!chip))
+		return -EINVAL;
+	spin_lock_init(&chip->mixer_lock);
+	strcpy(card->mixername, "MSND Pinnacle Mixer");
+
+	for (idx = 0; idx < ARRAY_SIZE(snd_msnd_controls); idx++)
+		err = snd_ctl_add(card,
+				  snd_ctl_new1(snd_msnd_controls + idx, chip));
+		if (err < 0)
+			return err;
+
+	return 0;
+}
+EXPORT_SYMBOL(snd_msndmix_new);
+
+void snd_msndmix_setup(struct snd_msnd *dev)
+{
+	update_pot(MSND_MIXER_LINE, bInPotPos, HDEXAR_IN_SET_POTS);
+	update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS);
+	update_volm(MSND_MIXER_PCM, wCurrPlayVol);
+	update_volm(MSND_MIXER_IMIX, wCurrInVol);
+	if (dev->type == msndPinnacle) {
+		update_pot(MSND_MIXER_MIC, bMicPotPos, HDEXAR_MIC_SET_POTS);
+		update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol);
+	}
+}
+EXPORT_SYMBOL(snd_msndmix_setup);
+
+int snd_msndmix_force_recsrc(struct snd_msnd *dev, int recsrc)
+{
+	dev->recsrc = -1;
+	return snd_msndmix_set_mux(dev, recsrc);
+}
+EXPORT_SYMBOL(snd_msndmix_force_recsrc);
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 58c972b..ef95279d 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -179,12 +179,13 @@
 	unsigned char result;
 #if 0
 	outb(0x1d, port);	/* password */
-	printk("read [0x%lx] = 0x%x\n", port, inb(port));
+	printk(KERN_DEBUG "read [0x%lx] = 0x%x\n", port, inb(port));
 #endif
 	outb(reg, chip->port);	/* register */
 	result = inb(chip->port + 1);
 #if 0
-	printk("read [0x%lx] = 0x%x [0x%x]\n", port, result, inb(port));
+	printk(KERN_DEBUG "read [0x%lx] = 0x%x [0x%x]\n",
+	       port, result, inb(port));
 #endif
 	return result;
 }
@@ -233,7 +234,10 @@
 		snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port);
 		return -EBUSY;
 	}
-	// snd_printk("REG 0A = 0x%x\n", snd_opl3sa2_read(chip, 0x0a));
+	/*
+	snd_printk(KERN_DEBUG "REG 0A = 0x%x\n",
+		   snd_opl3sa2_read(chip, 0x0a));
+	*/
 	chip->version = 0;
 	tmp = snd_opl3sa2_read(chip, OPL3SA2_MISC);
 	if (tmp == 0xff) {
@@ -550,21 +554,27 @@
 #ifdef CONFIG_PM
 static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state)
 {
-	struct snd_opl3sa2 *chip = card->private_data;
+	if (card) {
+		struct snd_opl3sa2 *chip = card->private_data;
 
-	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-	chip->wss->suspend(chip->wss);
-	/* power down */
-	snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3);
+		snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+		chip->wss->suspend(chip->wss);
+		/* power down */
+		snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3);
+	}
 
 	return 0;
 }
 
 static int snd_opl3sa2_resume(struct snd_card *card)
 {
-	struct snd_opl3sa2 *chip = card->private_data;
+	struct snd_opl3sa2 *chip;
 	int i;
 
+	if (!card)
+		return 0;
+
+	chip = card->private_data;
 	/* power up */
 	snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D0);
 
@@ -613,25 +623,28 @@
 {
 	struct snd_opl3sa2 *chip = card->private_data;
 	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
+		free_irq(chip->irq, card);
 	release_and_free_resource(chip->res_port);
 }
 
-static struct snd_card *snd_opl3sa2_card_new(int dev)
+static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp)
 {
 	struct snd_card *card;
 	struct snd_opl3sa2 *chip;
+	int err;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_opl3sa2));
-	if (card == NULL)
-		return NULL;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_opl3sa2), &card);
+	if (err < 0)
+		return err;
 	strcpy(card->driver, "OPL3SA2");
-	strcpy(card->shortname, "Yamaha OPL3-SA2");
+	strcpy(card->shortname, "Yamaha OPL3-SA");
 	chip = card->private_data;
 	spin_lock_init(&chip->reg_lock);
 	chip->irq = -1;
 	card->private_free = snd_opl3sa2_free;
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
@@ -723,9 +736,9 @@
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
 
-	card = snd_opl3sa2_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_opl3sa2_card_new(dev, &card);
+	if (err < 0)
+		return err;
 	if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) {
 		snd_card_free(card);
 		return err;
@@ -789,9 +802,9 @@
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
 
-	card = snd_opl3sa2_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_opl3sa2_card_new(dev, &card);
+	if (err < 0)
+		return err;
 	if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) {
 		snd_card_free(card);
 		return err;
@@ -870,9 +883,9 @@
 	struct snd_card *card;
 	int err;
 
-	card = snd_opl3sa2_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_opl3sa2_card_new(dev, &card);
+	if (err < 0)
+		return err;
 	snd_card_set_dev(card, pdev);
 	if ((err = snd_opl3sa2_probe(card, dev)) < 0) {
 		snd_card_free(card);
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index 440755c..02e30d7 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -1228,9 +1228,10 @@
 	struct snd_pcm *pcm;
 	struct snd_rawmidi *rmidi;
 
-	if (!(card = snd_card_new(index, id, THIS_MODULE,
-				  sizeof(struct snd_miro))))
-		return -ENOMEM;
+	error = snd_card_create(index, id, THIS_MODULE,
+				sizeof(struct snd_miro), &card);
+	if (error < 0)
+		return error;
 
 	card->private_free = snd_card_miro_free;
 	miro = card->private_data;
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 19706b0..5cd5553 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -252,7 +252,7 @@
 #endif	/* OPTi93X */
 
 	default:
-		snd_printk("chip %d not supported\n", hardware);
+		snd_printk(KERN_ERR "chip %d not supported\n", hardware);
 		return -ENODEV;
 	}
 	return 0;
@@ -294,7 +294,7 @@
 #endif	/* OPTi93X */
 
 	default:
-		snd_printk("chip %d not supported\n", chip->hardware);
+		snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
 	}
 
 	spin_unlock_irqrestore(&chip->lock, flags);
@@ -336,7 +336,7 @@
 #endif	/* OPTi93X */
 
 	default:
-		snd_printk("chip %d not supported\n", chip->hardware);
+		snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
 	}
 
 	spin_unlock_irqrestore(&chip->lock, flags);
@@ -412,7 +412,7 @@
 #endif	/* OPTi93X */
 
 	default:
-		snd_printk("chip %d not supported\n", chip->hardware);
+		snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
 		return -EINVAL;
 	}
 
@@ -430,7 +430,8 @@
 		wss_base_bits = 0x02;
 		break;
 	default:
-		snd_printk("WSS port 0x%lx not valid\n", chip->wss_base);
+		snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n",
+			   chip->wss_base);
 		goto __skip_base;
 	}
 	snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
@@ -455,7 +456,7 @@
 		irq_bits = 0x04;
 		break;
 	default:
-		snd_printk("WSS irq # %d not valid\n", chip->irq);
+		snd_printk(KERN_WARNING "WSS irq # %d not valid\n", chip->irq);
 		goto __skip_resources;
 	}
 
@@ -470,13 +471,14 @@
 		dma_bits = 0x03;
 		break;
 	default:
-		snd_printk("WSS dma1 # %d not valid\n", chip->dma1);
+		snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n",
+			   chip->dma1);
 		goto __skip_resources;
 	}
 
 #if defined(CS4231) || defined(OPTi93X)
 	if (chip->dma1 == chip->dma2) {
-		snd_printk("don't want to share dmas\n");
+		snd_printk(KERN_ERR "don't want to share dmas\n");
 		return -EBUSY;
 	}
 
@@ -485,7 +487,8 @@
 	case 1:
 		break;
 	default:
-		snd_printk("WSS dma2 # %d not valid\n", chip->dma2);
+		snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n",
+			   chip->dma2);
 		goto __skip_resources;
 	}
 	dma_bits |= 0x04;
@@ -516,7 +519,8 @@
 			mpu_port_bits = 0x00;
 			break;
 		default:
-			snd_printk("MPU-401 port 0x%lx not valid\n",
+			snd_printk(KERN_WARNING
+				   "MPU-401 port 0x%lx not valid\n",
 				chip->mpu_port);
 			goto __skip_mpu;
 		}
@@ -535,7 +539,7 @@
 			mpu_irq_bits = 0x01;
 			break;
 		default:
-			snd_printk("MPU-401 irq # %d not valid\n",
+			snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n",
 				chip->mpu_irq);
 			goto __skip_mpu;
 		}
@@ -726,7 +730,7 @@
 	if (chip->wss_base == SNDRV_AUTO_PORT) {
 		chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4);
 		if (chip->wss_base < 0) {
-			snd_printk("unable to find a free WSS port\n");
+			snd_printk(KERN_ERR "unable to find a free WSS port\n");
 			return -EBUSY;
 		}
 	}
@@ -815,14 +819,8 @@
 				   chip->fm_port, chip->fm_port + 4 - 1);
 		}
 		if (opl3) {
-#ifdef CS4231
-			const int t1dev = 1;
-#else
-			const int t1dev = 0;
-#endif
-			if ((error = snd_opl3_timer_new(opl3, t1dev, t1dev+1)) < 0)
-				return error;
-			if ((error = snd_opl3_hwdep_new(opl3, 0, 1, &synth)) < 0)
+			error = snd_opl3_hwdep_new(opl3, 0, 1, &synth);
+			if (error < 0)
 				return error;
 		}
 	}
@@ -830,15 +828,18 @@
 	return snd_card_register(card);
 }
 
-static struct snd_card *snd_opti9xx_card_new(void)
+static int snd_opti9xx_card_new(struct snd_card **cardp)
 {
 	struct snd_card *card;
+	int err;
 
-	card = snd_card_new(index, id, THIS_MODULE, sizeof(struct snd_opti9xx));
-	if (! card)
-		return NULL;
+	err = snd_card_create(index, id, THIS_MODULE,
+			      sizeof(struct snd_opti9xx), &card);
+	if (err < 0)
+		return err;
 	card->private_free = snd_card_opti9xx_free;
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 static int __devinit snd_opti9xx_isa_match(struct device *devptr,
@@ -897,15 +898,15 @@
 #if defined(CS4231) || defined(OPTi93X)
 	if (dma2 == SNDRV_AUTO_DMA) {
 		if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) {
-			snd_printk("unable to find a free DMA2\n");
+			snd_printk(KERN_ERR "unable to find a free DMA2\n");
 			return -EBUSY;
 		}
 	}
 #endif
 
-	card = snd_opti9xx_card_new();
-	if (! card)
-		return -ENOMEM;
+	error = snd_opti9xx_card_new(&card);
+	if (error < 0)
+		return error;
 
 	if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) {
 		snd_card_free(card);
@@ -950,9 +951,9 @@
 		return -EBUSY;
 	if (! isapnp)
 		return -ENODEV;
-	card = snd_opti9xx_card_new();
-	if (! card)
-		return -ENOMEM;
+	error = snd_opti9xx_card_new(&card);
+	if (error < 0)
+		return error;
 	chip = card->private_data;
 
 	hw = snd_card_opti9xx_pnp(chip, pcard, pid);
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c
index c8c8e21..cafc3a7 100644
--- a/sound/isa/sb/es968.c
+++ b/sound/isa/sb/es968.c
@@ -108,9 +108,10 @@
 	struct snd_card *card;
 	struct snd_card_es968 *acard;
 
-	if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-				 sizeof(struct snd_card_es968))) == NULL)
-		return -ENOMEM;
+	error = snd_card_create(index[dev], id[dev], THIS_MODULE,
+				sizeof(struct snd_card_es968), &card);
+	if (error < 0)
+		return error;
 	acard = card->private_data;
 	if ((error = snd_card_es968_pnp(dev, acard, pcard, pid))) {
 		snd_card_free(card);
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 2c201f7..519c363 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -324,14 +324,18 @@
 #define is_isapnp_selected(dev)		0
 #endif
 
-static struct snd_card *snd_sb16_card_new(int dev)
+static int snd_sb16_card_new(int dev, struct snd_card **cardp)
 {
-	struct snd_card *card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-					sizeof(struct snd_card_sb16));
-	if (card == NULL)
-		return NULL;
+	struct snd_card *card;
+	int err;
+
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_card_sb16), &card);
+	if (err < 0)
+		return err;
 	card->private_free = snd_sb16_free;
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 static int __devinit snd_sb16_probe(struct snd_card *card, int dev)
@@ -489,9 +493,9 @@
 	struct snd_card *card;
 	int err;
 
-	card = snd_sb16_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_sb16_card_new(dev, &card);
+	if (err < 0)
+		return err;
 
 	acard = card->private_data;
 	/* non-PnP FM port address is hardwired with base port address */
@@ -610,9 +614,9 @@
 	for ( ; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev] || !isapnp[dev])
 			continue;
-		card = snd_sb16_card_new(dev);
-		if (! card)
-			return -ENOMEM;
+		res = snd_sb16_card_new(dev, &card);
+		if (res < 0)
+			return res;
 		snd_card_set_dev(card, &pcard->card->dev);
 		if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 ||
 		    (res = snd_sb16_probe(card, dev)) < 0) {
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index ea06877..3cd57ee 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -103,10 +103,10 @@
 	struct snd_opl3 *opl3;
 	int err;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_sb8));
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_sb8), &card);
+	if (err < 0)
+		return err;
 	acard = card->private_data;
 	card->private_free = snd_sb8_free;
 
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 406a431..475220b 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -182,7 +182,7 @@
 
 static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[5] = {
+	static const char *texts[5] = {
 		"CD", "Mic", "Line", "Synth", "Master"
 	};
 
@@ -269,12 +269,73 @@
 }
 
 /*
+ * ALS4000 mono recording control switch
+ */
+
+static int snd_als4k_mono_capture_route_info(struct snd_kcontrol *kcontrol,
+					     struct snd_ctl_elem_info *uinfo)
+{
+	static const char *texts[3] = {
+		"L chan only", "R chan only", "L ch/2 + R ch/2"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item > 2)
+		uinfo->value.enumerated.item = 2;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_als4k_mono_capture_route_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
+	unsigned long flags;
+	unsigned char oval;
+
+	spin_lock_irqsave(&sb->mixer_lock, flags);
+	oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL);
+	spin_unlock_irqrestore(&sb->mixer_lock, flags);
+	oval >>= 6;
+	if (oval > 2)
+		oval = 2;
+
+	ucontrol->value.enumerated.item[0] = oval;
+	return 0;
+}
+
+static int snd_als4k_mono_capture_route_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
+	unsigned long flags;
+	int change;
+	unsigned char nval, oval;
+
+	if (ucontrol->value.enumerated.item[0] > 2)
+		return -EINVAL;
+	spin_lock_irqsave(&sb->mixer_lock, flags);
+	oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL);
+
+	nval = (oval & ~(3 << 6))
+	     | (ucontrol->value.enumerated.item[0] << 6);
+	change = nval != oval;
+	if (change)
+		snd_sbmixer_write(sb, SB_ALS4000_MONO_IO_CTRL, nval);
+	spin_unlock_irqrestore(&sb->mixer_lock, flags);
+	return change;
+}
+
+/*
  * SBPRO input multiplexer
  */
 
 static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[3] = {
+	static const char *texts[3] = {
 		"Mic", "CD", "Line"
 	};
 
@@ -442,6 +503,12 @@
 			.get = snd_dt019x_input_sw_get,
 			.put = snd_dt019x_input_sw_put,
 		},
+		[SB_MIX_MONO_CAPTURE_ALS4K] = {
+			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+			.info = snd_als4k_mono_capture_route_info,
+			.get = snd_als4k_mono_capture_route_get,
+			.put = snd_als4k_mono_capture_route_put,
+		},
 	};
 	struct snd_kcontrol *ctl;
 	int err;
@@ -636,6 +703,8 @@
 	};
 
 static struct sbmix_elem *snd_dt019x_controls[] = {
+	/* ALS4000 below has some parts which we might be lacking,
+	 * e.g. snd_als4000_ctl_mono_playback_switch - check it! */
 	&snd_dt019x_ctl_master_play_vol,
 	&snd_dt019x_ctl_pcm_play_vol,
 	&snd_dt019x_ctl_synth_play_vol,
@@ -666,18 +735,21 @@
 /*
  * ALS4000 specific mixer elements
  */
-/* FIXME: SB_ALS4000_MONO_IO_CTRL needs output select ctrl! */
 static struct sbmix_elem snd_als4000_ctl_master_mono_playback_switch =
 	SB_SINGLE("Master Mono Playback Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1);
-static struct sbmix_elem snd_als4000_ctl_master_mono_capture_route =
-	SB_SINGLE("Master Mono Capture Route", SB_ALS4000_MONO_IO_CTRL, 6, 0x03);
-/* FIXME: mono playback switch also available on DT019X? */
+static struct sbmix_elem snd_als4k_ctl_master_mono_capture_route = {
+		.name = "Master Mono Capture Route",
+		.type = SB_MIX_MONO_CAPTURE_ALS4K
+	};
 static struct sbmix_elem snd_als4000_ctl_mono_playback_switch =
 	SB_SINGLE("Mono Playback Switch", SB_DT019X_OUTPUT_SW2, 0, 1);
 static struct sbmix_elem snd_als4000_ctl_mic_20db_boost =
 	SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03);
-static struct sbmix_elem snd_als4000_ctl_mixer_loopback =
-	SB_SINGLE("Analog Loopback", SB_ALS4000_MIC_IN_GAIN, 7, 0x01);
+static struct sbmix_elem snd_als4000_ctl_mixer_analog_loopback =
+	SB_SINGLE("Analog Loopback Switch", SB_ALS4000_MIC_IN_GAIN, 7, 0x01);
+static struct sbmix_elem snd_als4000_ctl_mixer_digital_loopback =
+	SB_SINGLE("Digital Loopback Switch",
+		  SB_ALS4000_CR3_CONFIGURATION, 7, 0x01);
 /* FIXME: functionality of 3D controls might be swapped, I didn't find
  * a description of how to identify what is supposed to be what */
 static struct sbmix_elem snd_als4000_3d_control_switch =
@@ -694,6 +766,9 @@
 	SB_SINGLE("3D Control - Wide", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f);
 static struct sbmix_elem snd_als4000_3d_control_poweroff_switch =
 	SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01);
+static struct sbmix_elem snd_als4000_ctl_3db_freq_control_switch =
+	SB_SINGLE("Master Playback 8kHz / 20kHz LPF Switch",
+		  SB_ALS4000_FMDAC, 5, 0x01);
 #ifdef NOT_AVAILABLE
 static struct sbmix_elem snd_als4000_ctl_fmdac =
 	SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01);
@@ -702,35 +777,37 @@
 #endif
 
 static struct sbmix_elem *snd_als4000_controls[] = {
-	&snd_sb16_ctl_master_play_vol,
-	&snd_dt019x_ctl_pcm_play_switch,
-	&snd_sb16_ctl_pcm_play_vol,
-	&snd_sb16_ctl_synth_capture_route,
-	&snd_dt019x_ctl_synth_play_switch,
-	&snd_sb16_ctl_synth_play_vol,
-	&snd_sb16_ctl_cd_capture_route,
-	&snd_sb16_ctl_cd_play_switch,
-	&snd_sb16_ctl_cd_play_vol,
-	&snd_sb16_ctl_line_capture_route,
-	&snd_sb16_ctl_line_play_switch,
-	&snd_sb16_ctl_line_play_vol,
-	&snd_sb16_ctl_mic_capture_route,
-	&snd_als4000_ctl_mic_20db_boost,
-	&snd_sb16_ctl_auto_mic_gain,
-	&snd_sb16_ctl_mic_play_switch,
-	&snd_sb16_ctl_mic_play_vol,
-	&snd_sb16_ctl_pc_speaker_vol,
-	&snd_sb16_ctl_capture_vol,
-	&snd_sb16_ctl_play_vol,
-	&snd_als4000_ctl_master_mono_playback_switch,
-	&snd_als4000_ctl_master_mono_capture_route,
-	&snd_als4000_ctl_mono_playback_switch,
-	&snd_als4000_ctl_mixer_loopback,
-	&snd_als4000_3d_control_switch,
-	&snd_als4000_3d_control_ratio,
-	&snd_als4000_3d_control_freq,
-	&snd_als4000_3d_control_delay,
-	&snd_als4000_3d_control_poweroff_switch,
+						/* ALS4000a.PDF regs page */
+	&snd_sb16_ctl_master_play_vol,		/* MX30/31 12 */
+	&snd_dt019x_ctl_pcm_play_switch,	/* MX4C    16 */
+	&snd_sb16_ctl_pcm_play_vol,		/* MX32/33 12 */
+	&snd_sb16_ctl_synth_capture_route,	/* MX3D/3E 14 */
+	&snd_dt019x_ctl_synth_play_switch,	/* MX4C    16 */
+	&snd_sb16_ctl_synth_play_vol,		/* MX34/35 12/13 */
+	&snd_sb16_ctl_cd_capture_route,		/* MX3D/3E 14 */
+	&snd_sb16_ctl_cd_play_switch,		/* MX3C    14 */
+	&snd_sb16_ctl_cd_play_vol,		/* MX36/37 13 */
+	&snd_sb16_ctl_line_capture_route,	/* MX3D/3E 14 */
+	&snd_sb16_ctl_line_play_switch,		/* MX3C    14 */
+	&snd_sb16_ctl_line_play_vol,		/* MX38/39 13 */
+	&snd_sb16_ctl_mic_capture_route,	/* MX3D/3E 14 */
+	&snd_als4000_ctl_mic_20db_boost,	/* MX4D    16 */
+	&snd_sb16_ctl_mic_play_switch,		/* MX3C    14 */
+	&snd_sb16_ctl_mic_play_vol,		/* MX3A    13 */
+	&snd_sb16_ctl_pc_speaker_vol,		/* MX3B    14 */
+	&snd_sb16_ctl_capture_vol,		/* MX3F/40 15 */
+	&snd_sb16_ctl_play_vol,			/* MX41/42 15 */
+	&snd_als4000_ctl_master_mono_playback_switch, /* MX4C 16 */
+	&snd_als4k_ctl_master_mono_capture_route, /* MX4B  16 */
+	&snd_als4000_ctl_mono_playback_switch,	/* MX4C    16 */
+	&snd_als4000_ctl_mixer_analog_loopback, /* MX4D    16 */
+	&snd_als4000_ctl_mixer_digital_loopback, /* CR3    21 */
+	&snd_als4000_3d_control_switch,		 /* MX50   17 */
+	&snd_als4000_3d_control_ratio,		 /* MX50   17 */
+	&snd_als4000_3d_control_freq,		 /* MX50   17 */
+	&snd_als4000_3d_control_delay,		 /* MX51   18 */
+	&snd_als4000_3d_control_poweroff_switch,	/* MX51    18 */
+	&snd_als4000_ctl_3db_freq_control_switch,	/* MX4F    17 */
 #ifdef NOT_AVAILABLE
 	&snd_als4000_ctl_fmdac,
 	&snd_als4000_ctl_qsound,
@@ -905,13 +982,14 @@
 };
 
 static unsigned char als4000_saved_regs[] = {
+	/* please verify in dsheet whether regs to be added
+	   are actually real H/W or just dummy */
 	SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
 	SB_DSP4_OUTPUT_SW,
 	SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
 	SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
 	SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
 	SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
-	SB_DSP4_MIC_AGC,
 	SB_DSP4_MIC_DEV,
 	SB_DSP4_SPEAKER_DEV,
 	SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1,
@@ -919,8 +997,10 @@
 	SB_DT019X_OUTPUT_SW2,
 	SB_ALS4000_MONO_IO_CTRL,
 	SB_ALS4000_MIC_IN_GAIN,
+	SB_ALS4000_FMDAC,
 	SB_ALS4000_3D_SND_FX,
 	SB_ALS4000_3D_TIME_DELAY,
+	SB_ALS4000_CR3_CONFIGURATION,
 };
 
 static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index ca35924..7820106 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -489,9 +489,9 @@
 	char __iomem *vmss_port;
 
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (!card)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	if (xirq == SNDRV_AUTO_IRQ) {
 		xirq = snd_legacy_find_free_irq(possible_irqs);
@@ -576,10 +576,6 @@
 		snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n",
 			   0x388, 0x388 + 2);
 	} else {
-		err = snd_opl3_timer_new(opl3, 0, 1);
-		if (err < 0)
-			goto err_unmap2;
-
 		err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
 		if (err < 0)
 			goto err_unmap2;
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index 2c7503b..6fe27b9 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -243,9 +243,9 @@
 	struct snd_card *card;
 	struct snd_wss *chip;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	xirq = irq[dev];
 	if (xirq == SNDRV_AUTO_IRQ) {
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 48a16d8..6618712 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -89,9 +89,6 @@
 #endif
 
 
-#define MPU401_IO(i)     ((i) + 0)
-#define MIDI_DATA_IO(i)  ((i) + 0)
-#define MIDI_CTRL_IO(i)  ((i) + 1)
 #define HOST_CTRL_IO(i)  ((i) + 2)
 #define HOST_DATA_IO(i)  ((i) + 3)
 #define ODIE_ADDR_IO(i)  ((i) + 4)
@@ -129,9 +126,6 @@
 #define DMA_8BIT  0x80
 
 
-#define AD1845_FREQ_SEL_MSB    0x16
-#define AD1845_FREQ_SEL_LSB    0x17
-
 enum card_type {
 	SSCAPE,
 	SSCAPE_PNP,
@@ -141,8 +135,6 @@
 struct soundscape {
 	spinlock_t lock;
 	unsigned io_base;
-	unsigned wss_base;
-	int codec_type;
 	int ic_type;
 	enum card_type type;
 	struct resource *io_res;
@@ -330,7 +322,7 @@
  */
 static inline int verify_mpu401(const struct snd_mpu401 * mpu)
 {
-	return ((inb(MIDI_CTRL_IO(mpu->port)) & 0xc0) == 0x80);
+	return ((inb(MPU401C(mpu)) & 0xc0) == 0x80);
 }
 
 /*
@@ -338,7 +330,7 @@
  */
 static inline void initialise_mpu401(const struct snd_mpu401 * mpu)
 {
-	outb(0, MIDI_DATA_IO(mpu->port));
+	outb(0, MPU401D(mpu));
 }
 
 /*
@@ -396,20 +388,20 @@
  */
 static int obp_startup_ack(struct soundscape *s, unsigned timeout)
 {
-	while (timeout != 0) {
+	unsigned long end_time = jiffies + msecs_to_jiffies(timeout);
+
+	do {
 		unsigned long flags;
 		unsigned char x;
 
-		schedule_timeout_uninterruptible(1);
-
 		spin_lock_irqsave(&s->lock, flags);
 		x = inb(HOST_DATA_IO(s->io_base));
 		spin_unlock_irqrestore(&s->lock, flags);
 		if ((x & 0xfe) == 0xfe)
 			return 1;
 
-		--timeout;
-	} /* while */
+		msleep(10);
+	} while (time_before(jiffies, end_time));
 
 	return 0;
 }
@@ -423,20 +415,20 @@
  */
 static int host_startup_ack(struct soundscape *s, unsigned timeout)
 {
-	while (timeout != 0) {
+	unsigned long end_time = jiffies + msecs_to_jiffies(timeout);
+
+	do {
 		unsigned long flags;
 		unsigned char x;
 
-		schedule_timeout_uninterruptible(1);
-
 		spin_lock_irqsave(&s->lock, flags);
 		x = inb(HOST_DATA_IO(s->io_base));
 		spin_unlock_irqrestore(&s->lock, flags);
 		if (x == 0xfe)
 			return 1;
 
-		--timeout;
-	} /* while */
+		msleep(10);
+	} while (time_before(jiffies, end_time));
 
 	return 0;
 }
@@ -532,10 +524,10 @@
 	 * give it 5 seconds (max) ...
 	 */
 	ret = 0;
-	if (!obp_startup_ack(s, 5)) {
+	if (!obp_startup_ack(s, 5000)) {
 		snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n");
 		ret = -EAGAIN;
-	} else if (!host_startup_ack(s, 5)) {
+	} else if (!host_startup_ack(s, 5000)) {
 		snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n");
 		ret = -EAGAIN;
 	}
@@ -732,13 +724,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&s->lock, flags);
-	set_host_mode_unsafe(s->io_base);
-
-	if (host_write_ctrl_unsafe(s->io_base, CMD_GET_MIDI_VOL, 100)) {
-		uctl->value.integer.value[0] = host_read_ctrl_unsafe(s->io_base, 100);
-	}
-
-	set_midi_mode_unsafe(s->io_base);
+	uctl->value.integer.value[0] = s->midi_vol;
 	spin_unlock_irqrestore(&s->lock, flags);
 	return 0;
 }
@@ -773,6 +759,7 @@
 	change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100)
 	          && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100)
 	          && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100));
+	s->midi_vol = (unsigned char) uctl->value.integer.value[0] & 127;
       __skip_change:
 
 	/*
@@ -815,12 +802,11 @@
  * Perform certain arcane port-checks to see whether there
  * is a SoundScape board lurking behind the given ports.
  */
-static int __devinit detect_sscape(struct soundscape *s)
+static int __devinit detect_sscape(struct soundscape *s, long wss_io)
 {
 	unsigned long flags;
 	unsigned d;
 	int retval = 0;
-	int codec = s->wss_base;
 
 	spin_lock_irqsave(&s->lock, flags);
 
@@ -836,13 +822,11 @@
 	if ((d & 0x80) != 0)
 		goto _done;
 
-	if (d == 0) {
-		s->codec_type = 1;
+	if (d == 0)
 		s->ic_type = IC_ODIE;
-	} else if ((d & 0x60) != 0) {
-		s->codec_type = 2;
+	else if ((d & 0x60) != 0)
 		s->ic_type = IC_OPUS;
-	} else
+	else
 		goto _done;
 
 	outb(0xfa, ODIE_ADDR_IO(s->io_base));
@@ -862,10 +846,10 @@
 	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
 
 	if (s->type == SSCAPE_VIVO)
-		codec += 4;
+		wss_io += 4;
 	/* wait for WSS codec */
 	for (d = 0; d < 500; d++) {
-		if ((inb(codec) & 0x80) == 0)
+		if ((inb(wss_io) & 0x80) == 0)
 			break;
 		spin_unlock_irqrestore(&s->lock, flags);
 		msleep(1);
@@ -955,82 +939,6 @@
 
 
 /*
- * Override for the CS4231 playback format function.
- * The AD1845 has much simpler format and rate selection.
- */
-static void ad1845_playback_format(struct snd_wss *chip,
-				   struct snd_pcm_hw_params *params,
-				   unsigned char format)
-{
-	unsigned long flags;
-	unsigned rate = params_rate(params);
-
-	/*
-	 * The AD1845 can't handle sample frequencies
-	 * outside of 4 kHZ to 50 kHZ
-	 */
-	if (rate > 50000)
-		rate = 50000;
-	else if (rate < 4000)
-		rate = 4000;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
-
-	/*
-	 * Program the AD1845 correctly for the playback stream.
-	 * Note that we do NOT need to toggle the MCE bit because
-	 * the PLAYBACK_ENABLE bit of the Interface Configuration
-	 * register is set.
-	 * 
-	 * NOTE: We seem to need to write to the MSB before the LSB
-	 *       to get the correct sample frequency.
-	 */
-	snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0));
-	snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
-	snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
-
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
-/*
- * Override for the CS4231 capture format function. 
- * The AD1845 has much simpler format and rate selection.
- */
-static void ad1845_capture_format(struct snd_wss *chip,
-				  struct snd_pcm_hw_params *params,
-				  unsigned char format)
-{
-	unsigned long flags;
-	unsigned rate = params_rate(params);
-
-	/*
-	 * The AD1845 can't handle sample frequencies 
-	 * outside of 4 kHZ to 50 kHZ
-	 */
-	if (rate > 50000)
-		rate = 50000;
-	else if (rate < 4000)
-		rate = 4000;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
-
-	/*
-	 * Program the AD1845 correctly for the playback stream.
-	 * Note that we do NOT need to toggle the MCE bit because
-	 * the CAPTURE_ENABLE bit of the Interface Configuration
-	 * register is set.
-	 *
-	 * NOTE: We seem to need to write to the MSB before the LSB
-	 *       to get the correct sample frequency.
-	 */
-	snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0));
-	snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
-	snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
-
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
-/*
  * Create an AD1845 PCM subdevice on the SoundScape. The AD1845
  * is very much like a CS4231, with a few extra bits. We will
  * try to support at least some of the extra bits by overriding
@@ -1055,11 +963,6 @@
 		unsigned long flags;
 		struct snd_pcm *pcm;
 
-#define AD1845_FREQ_SEL_ENABLE  0x08
-
-#define AD1845_PWR_DOWN_CTRL   0x1b
-#define AD1845_CRYS_CLOCK_SEL  0x1d
-
 /*
  * It turns out that the PLAYBACK_ENABLE bit is set
  * by the lowlevel driver ...
@@ -1074,7 +977,6 @@
  */
 
 		if (sscape->type != SSCAPE_VIVO) {
-			int val;
 			/*
 			 * The input clock frequency on the SoundScape must
 			 * be 14.31818 MHz, because we must set this register
@@ -1082,22 +984,10 @@
 			 */
 			snd_wss_mce_up(chip);
 			spin_lock_irqsave(&chip->reg_lock, flags);
-			snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20);
+			snd_wss_out(chip, AD1845_CLOCK, 0x20);
 			spin_unlock_irqrestore(&chip->reg_lock, flags);
 			snd_wss_mce_down(chip);
 
-			/*
-			 * More custom configuration:
-			 * a) select "mode 2" and provide a current drive of 8mA
-			 * b) enable frequency selection (for capture/playback)
-			 */
-			spin_lock_irqsave(&chip->reg_lock, flags);
-			snd_wss_out(chip, CS4231_MISC_INFO,
-				    CS4231_MODE2 | 0x10);
-			val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL);
-			snd_wss_out(chip, AD1845_PWR_DOWN_CTRL,
-				    val | AD1845_FREQ_SEL_ENABLE);
-			spin_unlock_irqrestore(&chip->reg_lock, flags);
 		}
 
 		err = snd_wss_pcm(chip, 0, &pcm);
@@ -1113,11 +1003,13 @@
 					    "for AD1845 chip\n");
 			goto _error;
 		}
-		err = snd_wss_timer(chip, 0, NULL);
-		if (err < 0) {
-			snd_printk(KERN_ERR "sscape: No timer device "
-					    "for AD1845 chip\n");
-			goto _error;
+		if (chip->hardware != WSS_HW_AD1848) {
+			err = snd_wss_timer(chip, 0, NULL);
+			if (err < 0) {
+				snd_printk(KERN_ERR "sscape: No timer device "
+						    "for AD1845 chip\n");
+				goto _error;
+			}
 		}
 
 		if (sscape->type != SSCAPE_VIVO) {
@@ -1128,8 +1020,6 @@
 						    "MIDI mixer control\n");
 				goto _error;
 			}
-			chip->set_playback_format = ad1845_playback_format;
-			chip->set_capture_format = ad1845_capture_format;
 		}
 
 		strcpy(card->driver, "SoundScape");
@@ -1157,7 +1047,6 @@
 	unsigned dma_cfg;
 	unsigned irq_cfg;
 	unsigned mpu_irq_cfg;
-	unsigned xport;
 	struct resource *io_res;
 	struct resource *wss_res;
 	unsigned long flags;
@@ -1177,15 +1066,15 @@
 		printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
 		return -ENXIO;
 	}
-	xport = port[dev];
 
 	/*
 	 * Grab IO ports that we will need to probe so that we
 	 * can detect and control this hardware ...
 	 */
-	io_res = request_region(xport, 8, "SoundScape");
+	io_res = request_region(port[dev], 8, "SoundScape");
 	if (!io_res) {
-		snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport);
+		snd_printk(KERN_ERR
+			   "sscape: can't grab port 0x%lx\n", port[dev]);
 		return -EBUSY;
 	}
 	wss_res = NULL;
@@ -1212,10 +1101,9 @@
 	spin_lock_init(&sscape->fwlock);
 	sscape->io_res = io_res;
 	sscape->wss_res = wss_res;
-	sscape->io_base = xport;
-	sscape->wss_base = wss_port[dev];
+	sscape->io_base = port[dev];
 
-	if (!detect_sscape(sscape)) {
+	if (!detect_sscape(sscape, wss_port[dev])) {
 		printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base);
 		err = -ENODEV;
 		goto _release_dma;
@@ -1288,12 +1176,11 @@
 	}
 #define MIDI_DEVNUM  0
 	if (sscape->type != SSCAPE_VIVO) {
-		err = create_mpu401(card, MIDI_DEVNUM,
-				    MPU401_IO(xport), mpu_irq[dev]);
+		err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]);
 		if (err < 0) {
 			printk(KERN_ERR "sscape: Failed to create "
-					"MPU-401 device at 0x%x\n",
-					MPU401_IO(xport));
+					"MPU-401 device at 0x%lx\n",
+					port[dev]);
 			goto _release_dma;
 		}
 
@@ -1357,10 +1244,10 @@
 	struct soundscape *sscape;
 	int ret;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct soundscape));
-	if (!card)
-		return -ENOMEM;
+	ret = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct soundscape), &card);
+	if (ret < 0)
+		return ret;
 
 	sscape = get_card_soundscape(card);
 	sscape->type = SSCAPE;
@@ -1462,10 +1349,10 @@
 	 * Create a new ALSA sound card entry, in anticipation
 	 * of detecting our hardware ...
 	 */
-	card = snd_card_new(index[idx], id[idx], THIS_MODULE,
-			    sizeof(struct soundscape));
-	if (!card)
-		return -ENOMEM;
+	ret = snd_card_create(index[idx], id[idx], THIS_MODULE,
+			      sizeof(struct soundscape), &card);
+	if (ret < 0)
+		return ret;
 
 	sscape = get_card_soundscape(card);
 
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 4c095bc..a34ae7b 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -338,15 +338,16 @@
 	}
 }
 
-static struct snd_card *snd_wavefront_card_new(int dev)
+static int snd_wavefront_card_new(int dev, struct snd_card **cardp)
 {
 	struct snd_card *card;
 	snd_wavefront_card_t *acard;
+	int err;
 
-	card = snd_card_new (index[dev], id[dev], THIS_MODULE,
-			     sizeof(snd_wavefront_card_t));
-	if (card == NULL)
-		return NULL;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(snd_wavefront_card_t), &card);
+	if (err < 0)
+		return err;
 
 	acard = card->private_data;
 	acard->wavefront.irq = -1;
@@ -357,7 +358,8 @@
 	acard->wavefront.card = card;
 	card->private_free = snd_wavefront_free;
 
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 static int __devinit
@@ -551,11 +553,11 @@
 		return 0;
 #endif
 	if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
-		snd_printk("specify CS4232 port\n");
+		snd_printk(KERN_ERR "specify CS4232 port\n");
 		return 0;
 	}
 	if (ics2115_port[dev] == SNDRV_AUTO_PORT) {
-		snd_printk("specify ICS2115 port\n");
+		snd_printk(KERN_ERR "specify ICS2115 port\n");
 		return 0;
 	}
 	return 1;
@@ -567,9 +569,9 @@
 	struct snd_card *card;
 	int err;
 
-	card = snd_wavefront_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	err = snd_wavefront_card_new(dev, &card);
+	if (err < 0)
+		return err;
 	snd_card_set_dev(card, pdev);
 	if ((err = snd_wavefront_probe(card, dev)) < 0) {
 		snd_card_free(card);
@@ -616,9 +618,9 @@
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
 
-	card = snd_wavefront_card_new(dev);
-	if (! card)
-		return -ENOMEM;
+	res = snd_wavefront_card_new(dev, &card);
+	if (res < 0)
+		return res;
 
 	if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) {
 		if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index 4c41082..beb312c 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -633,7 +633,7 @@
 		wbuf[1] = i >> 7;
 
 		if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
-			snd_printk("cannot identify sample "
+			snd_printk(KERN_WARNING "cannot identify sample "
 				   "type of slot %d\n", i);
 			dev->sample_status[i] = WF_ST_EMPTY;
 			continue;
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 3d6c5f2..5d2ba1b 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -181,25 +181,6 @@
 		udelay(100);
 }
 
-static void snd_wss_outm(struct snd_wss *chip, unsigned char reg,
-			    unsigned char mask, unsigned char value)
-{
-	unsigned char tmp = (chip->image[reg] & mask) | value;
-
-	snd_wss_wait(chip);
-#ifdef CONFIG_SND_DEBUG
-	if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
-		snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
-#endif
-	chip->image[reg] = tmp;
-	if (!chip->calibrate_mute) {
-		wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
-		wmb();
-		wss_outb(chip, CS4231P(REG), tmp);
-		mb();
-	}
-}
-
 static void snd_wss_dout(struct snd_wss *chip, unsigned char reg,
 			 unsigned char value)
 {
@@ -219,7 +200,8 @@
 	snd_wss_wait(chip);
 #ifdef CONFIG_SND_DEBUG
 	if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
-		snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+		snd_printk(KERN_DEBUG "out: auto calibration time out "
+			   "- reg = 0x%x, value = 0x%x\n", reg, value);
 #endif
 	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
 	wss_outb(chip, CS4231P(REG), value);
@@ -235,7 +217,8 @@
 	snd_wss_wait(chip);
 #ifdef CONFIG_SND_DEBUG
 	if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
-		snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
+		snd_printk(KERN_DEBUG "in: auto calibration time out "
+			   "- reg = 0x%x\n", reg);
 #endif
 	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
 	mb();
@@ -252,7 +235,7 @@
 	wss_outb(chip, CS4231P(REG), val);
 	chip->eimage[CS4236_REG(reg)] = val;
 #if 0
-	printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val);
+	printk(KERN_DEBUG "ext out : reg = 0x%x, val = 0x%x\n", reg, val);
 #endif
 }
 EXPORT_SYMBOL(snd_cs4236_ext_out);
@@ -268,7 +251,8 @@
 	{
 		unsigned char res;
 		res = wss_inb(chip, CS4231P(REG));
-		printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res);
+		printk(KERN_DEBUG "ext in : reg = 0x%x, val = 0x%x\n",
+		       reg, res);
 		return res;
 	}
 #endif
@@ -394,13 +378,16 @@
 	snd_wss_wait(chip);
 #ifdef CONFIG_SND_DEBUG
 	if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
-		snd_printk("mce_up - auto calibration time out (0)\n");
+		snd_printk(KERN_DEBUG
+			   "mce_up - auto calibration time out (0)\n");
 #endif
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	chip->mce_bit |= CS4231_MCE;
 	timeout = wss_inb(chip, CS4231P(REGSEL));
 	if (timeout == 0x80)
-		snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
+		snd_printk(KERN_DEBUG "mce_up [0x%lx]: "
+			   "serious init problem - codec still busy\n",
+			   chip->port);
 	if (!(timeout & CS4231_MCE))
 		wss_outb(chip, CS4231P(REGSEL),
 			 chip->mce_bit | (timeout & 0x1f));
@@ -419,7 +406,9 @@
 
 #ifdef CONFIG_SND_DEBUG
 	if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
-		snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
+		snd_printk(KERN_DEBUG "mce_down [0x%lx] - "
+			   "auto calibration time out (0)\n",
+			   (long)CS4231P(REGSEL));
 #endif
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	chip->mce_bit &= ~CS4231_MCE;
@@ -427,7 +416,9 @@
 	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	if (timeout == 0x80)
-		snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
+		snd_printk(KERN_DEBUG "mce_down [0x%lx]: "
+			   "serious init problem - codec still busy\n",
+			   chip->port);
 	if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask))
 		return;
 
@@ -565,7 +556,7 @@
 	if (channels > 1)
 		rformat |= CS4231_STEREO;
 #if 0
-	snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
+	snd_printk(KERN_DEBUG "get_format: 0x%x (mode=0x%x)\n", format, mode);
 #endif
 	return rformat;
 }
@@ -587,7 +578,15 @@
 			     chip->image[CS4231_RIGHT_INPUT]);
 		snd_wss_dout(chip, CS4231_LOOPBACK,
 			     chip->image[CS4231_LOOPBACK]);
+	} else {
+		snd_wss_dout(chip, CS4231_LEFT_INPUT,
+			     0);
+		snd_wss_dout(chip, CS4231_RIGHT_INPUT,
+			     0);
+		snd_wss_dout(chip, CS4231_LOOPBACK,
+			     0xfd);
 	}
+
 	snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT,
 		     mute | chip->image[CS4231_AUX1_LEFT_INPUT]);
 	snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT,
@@ -630,7 +629,6 @@
 	int full_calib = 1;
 
 	mutex_lock(&chip->mce_mutex);
-	snd_wss_calibrate_mute(chip, 1);
 	if (chip->hardware == WSS_HW_CS4231A ||
 	    (chip->hardware & WSS_HW_CS4232_MASK)) {
 		spin_lock_irqsave(&chip->reg_lock, flags);
@@ -646,6 +644,24 @@
 			full_calib = 0;
 		}
 		spin_unlock_irqrestore(&chip->reg_lock, flags);
+	} else if (chip->hardware == WSS_HW_AD1845) {
+		unsigned rate = params_rate(params);
+
+		/*
+		 * Program the AD1845 correctly for the playback stream.
+		 * Note that we do NOT need to toggle the MCE bit because
+		 * the PLAYBACK_ENABLE bit of the Interface Configuration
+		 * register is set.
+		 *
+		 * NOTE: We seem to need to write to the MSB before the LSB
+		 *       to get the correct sample frequency.
+		 */
+		spin_lock_irqsave(&chip->reg_lock, flags);
+		snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0));
+		snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
+		snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
+		full_calib = 0;
+		spin_unlock_irqrestore(&chip->reg_lock, flags);
 	}
 	if (full_calib) {
 		snd_wss_mce_up(chip);
@@ -663,7 +679,6 @@
 			udelay(100);	/* this seems to help */
 		snd_wss_mce_down(chip);
 	}
-	snd_wss_calibrate_mute(chip, 0);
 	mutex_unlock(&chip->mce_mutex);
 }
 
@@ -675,7 +690,6 @@
 	int full_calib = 1;
 
 	mutex_lock(&chip->mce_mutex);
-	snd_wss_calibrate_mute(chip, 1);
 	if (chip->hardware == WSS_HW_CS4231A ||
 	    (chip->hardware & WSS_HW_CS4232_MASK)) {
 		spin_lock_irqsave(&chip->reg_lock, flags);
@@ -690,6 +704,24 @@
 			full_calib = 0;
 		}
 		spin_unlock_irqrestore(&chip->reg_lock, flags);
+	} else if (chip->hardware == WSS_HW_AD1845) {
+		unsigned rate = params_rate(params);
+
+		/*
+		 * Program the AD1845 correctly for the capture stream.
+		 * Note that we do NOT need to toggle the MCE bit because
+		 * the PLAYBACK_ENABLE bit of the Interface Configuration
+		 * register is set.
+		 *
+		 * NOTE: We seem to need to write to the MSB before the LSB
+		 *       to get the correct sample frequency.
+		 */
+		spin_lock_irqsave(&chip->reg_lock, flags);
+		snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0));
+		snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
+		snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
+		full_calib = 0;
+		spin_unlock_irqrestore(&chip->reg_lock, flags);
 	}
 	if (full_calib) {
 		snd_wss_mce_up(chip);
@@ -714,7 +746,6 @@
 		spin_unlock_irqrestore(&chip->reg_lock, flags);
 		snd_wss_mce_down(chip);
 	}
-	snd_wss_calibrate_mute(chip, 0);
 	mutex_unlock(&chip->mce_mutex);
 }
 
@@ -771,10 +802,11 @@
 {
 	unsigned long flags;
 
+	snd_wss_calibrate_mute(chip, 1);
 	snd_wss_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (1)\n");
+	snd_printk(KERN_DEBUG "init: (1)\n");
 #endif
 	snd_wss_mce_up(chip);
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -789,18 +821,20 @@
 	snd_wss_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (2)\n");
+	snd_printk(KERN_DEBUG "init: (2)\n");
 #endif
 
 	snd_wss_mce_up(chip);
 	spin_lock_irqsave(&chip->reg_lock, flags);
+	chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB;
+	snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
 	snd_wss_out(chip,
 		    CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	snd_wss_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (3) - afei = 0x%x\n",
+	snd_printk(KERN_DEBUG "init: (3) - afei = 0x%x\n",
 		   chip->image[CS4231_ALT_FEATURE_1]);
 #endif
 
@@ -817,7 +851,7 @@
 	snd_wss_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (4)\n");
+	snd_printk(KERN_DEBUG "init: (4)\n");
 #endif
 
 	snd_wss_mce_up(chip);
@@ -827,9 +861,10 @@
 			    chip->image[CS4231_REC_FORMAT]);
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	snd_wss_mce_down(chip);
+	snd_wss_calibrate_mute(chip, 0);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (5)\n");
+	snd_printk(KERN_DEBUG "init: (5)\n");
 #endif
 }
 
@@ -885,8 +920,6 @@
 		mutex_unlock(&chip->open_mutex);
 		return;
 	}
-	snd_wss_calibrate_mute(chip, 1);
-
 	/* disable IRQ */
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	if (!(chip->hardware & WSS_HW_AD1848_MASK))
@@ -919,8 +952,6 @@
 	wss_outb(chip, CS4231P(STATUS), 0);	/* clear IRQ */
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 
-	snd_wss_calibrate_mute(chip, 0);
-
 	chip->mode = 0;
 	mutex_unlock(&chip->open_mutex);
 }
@@ -1113,7 +1144,7 @@
 	if (chip->hardware & WSS_HW_AD1848_MASK)
 		wss_outb(chip, CS4231P(STATUS), 0);
 	else
-		snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0);
+		snd_wss_out(chip, CS4231_IRQ_STATUS, status);
 	spin_unlock(&chip->reg_lock);
 	return IRQ_HANDLED;
 }
@@ -1278,7 +1309,8 @@
 		} else if (rev == 0x03) {
 			chip->hardware = WSS_HW_CS4236B;
 		} else {
-			snd_printk("unknown CS chip with version 0x%x\n", rev);
+			snd_printk(KERN_ERR
+				   "unknown CS chip with version 0x%x\n", rev);
 			return -ENODEV;		/* unknown CS4231 chip? */
 		}
 	}
@@ -1314,6 +1346,10 @@
 		chip->image[CS4231_ALT_FEATURE_2] =
 			chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
 	}
+	/* enable fine grained frequency selection */
+	if (chip->hardware == WSS_HW_AD1845)
+		chip->image[AD1845_PWR_DOWN] = 8;
+
 	ptr = (unsigned char *) &chip->image;
 	regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
 	snd_wss_mce_down(chip);
@@ -1342,7 +1378,10 @@
 				case 6:
 					break;
 				default:
-					snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id);
+					snd_printk(KERN_WARNING
+						"unknown CS4235 chip "
+						"(enhanced version = 0x%x)\n",
+						id);
 				}
 			} else if ((id & 0x1f) == 0x0b) {	/* CS4236/B */
 				switch (id >> 5) {
@@ -1353,7 +1392,10 @@
 					chip->hardware = WSS_HW_CS4236B;
 					break;
 				default:
-					snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id);
+					snd_printk(KERN_WARNING
+						"unknown CS4236 chip "
+						"(enhanced version = 0x%x)\n",
+						id);
 				}
 			} else if ((id & 0x1f) == 0x08) {	/* CS4237B */
 				chip->hardware = WSS_HW_CS4237B;
@@ -1364,7 +1406,10 @@
 				case 7:
 					break;
 				default:
-					snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id);
+					snd_printk(KERN_WARNING
+						"unknown CS4237B chip "
+						"(enhanced version = 0x%x)\n",
+						id);
 				}
 			} else if ((id & 0x1f) == 0x09) {	/* CS4238B */
 				chip->hardware = WSS_HW_CS4238B;
@@ -1374,7 +1419,10 @@
 				case 7:
 					break;
 				default:
-					snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id);
+					snd_printk(KERN_WARNING
+						"unknown CS4238B chip "
+						"(enhanced version = 0x%x)\n",
+						id);
 				}
 			} else if ((id & 0x1f) == 0x1e) {	/* CS4239 */
 				chip->hardware = WSS_HW_CS4239;
@@ -1384,10 +1432,15 @@
 				case 6:
 					break;
 				default:
-					snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id);
+					snd_printk(KERN_WARNING
+						"unknown CS4239 chip "
+						"(enhanced version = 0x%x)\n",
+						id);
 				}
 			} else {
-				snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id);
+				snd_printk(KERN_WARNING
+					   "unknown CS4236/CS423xB chip "
+					   "(enhanced version = 0x%x)\n", id);
 			}
 		}
 	}
@@ -1618,7 +1671,8 @@
 	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	if (timeout == 0x80)
-		snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);
+		snd_printk(KERN_ERR "down [0x%lx]: serious init problem "
+			   "- codec still busy\n", chip->port);
 	if ((timeout & CS4231_MCE) == 0 ||
 	    !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
 		return;
@@ -1628,7 +1682,7 @@
 }
 #endif /* CONFIG_PM */
 
-static int snd_wss_free(struct snd_wss *chip)
+int snd_wss_free(struct snd_wss *chip)
 {
 	release_and_free_resource(chip->res_port);
 	release_and_free_resource(chip->res_cport);
@@ -1651,6 +1705,7 @@
 	kfree(chip);
 	return 0;
 }
+EXPORT_SYMBOL(snd_wss_free);
 
 static int snd_wss_dev_free(struct snd_device *device)
 {
@@ -1820,7 +1875,8 @@
 #if 0
 	if (chip->hardware & WSS_HW_CS4232_MASK) {
 		if (chip->res_cport == NULL)
-			snd_printk("CS4232 control port features are not accessible\n");
+			snd_printk(KERN_ERR "CS4232 control port features are "
+				   "not accessible\n");
 	}
 #endif
 
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index 1881cec..3e763d6 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -636,9 +636,10 @@
 	struct snd_card *card;
 	struct snd_au1000 *au1000;
 
-	card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(struct snd_au1000));
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(-1, "AC97", THIS_MODULE,
+			      sizeof(struct snd_au1000), &card);
+	if (err < 0)
+		return err;
 
 	card->private_free = snd_au1000_free;
 	au1000 = card->private_data;
@@ -678,7 +679,7 @@
 		return err;
 	}
 
-	printk( KERN_INFO "ALSA AC97: Driver Initialized\n" );
+	printk(KERN_INFO "ALSA AC97: Driver Initialized\n");
 	au1000_card = card;
 	return 0;
 }
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
index db495be..c52691c 100644
--- a/sound/mips/hal2.c
+++ b/sound/mips/hal2.c
@@ -878,9 +878,9 @@
 	struct snd_hal2 *chip;
 	int err;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	err = hal2_create(card, &chip);
 	if (err < 0) {
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
index 4c63504..66f3b48 100644
--- a/sound/mips/sgio2audio.c
+++ b/sound/mips/sgio2audio.c
@@ -936,9 +936,9 @@
 	struct snd_sgio2audio *chip;
 	int err;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	err = snd_sgio2audio_create(card, &chip);
 	if (err < 0) {
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 7cf9913..d12bd98 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -280,7 +280,7 @@
 	while (timeout > 0 && (ad_read(devc, 11) & 0x20))
 		timeout--;
 	if (ad_read(devc, 11) & 0x20)
-		if ( (devc->model != MD_1845) || (devc->model != MD_1845_SSCAPE))
+		if ((devc->model != MD_1845) && (devc->model != MD_1845_SSCAPE))
 			printk(KERN_WARNING "ad1848: Auto calibration timed out(3).\n");
 }
 
@@ -2107,7 +2107,7 @@
 	switch (cmd)
 	{
 		case AD1848_SET_XTAL:	/* Change clock frequency of AD1845 (only ) */
-			if (devc->model != MD_1845 || devc->model != MD_1845_SSCAPE)
+			if (devc->model != MD_1845 && devc->model != MD_1845_SSCAPE)
 				return -EINVAL;
 			spin_lock_irqsave(&devc->lock,flags);
 			ad_enter_MCE(devc);
diff --git a/sound/oss/dmabuf.c b/sound/oss/dmabuf.c
index 1e90d76..1bfcf7e 100644
--- a/sound/oss/dmabuf.c
+++ b/sound/oss/dmabuf.c
@@ -439,7 +439,7 @@
 			DMAbuf_launch_output(dev, dmap);
 		adev->dmap_out->flags |= DMA_SYNCING;
 		adev->dmap_out->underrun_count = 0;
-		while (!signal_pending(current) && n++ <= adev->dmap_out->nbufs && 
+		while (!signal_pending(current) && n++ < adev->dmap_out->nbufs &&
 		       adev->dmap_out->qlen && adev->dmap_out->underrun_count == 0) {
 			long t = dmabuf_timeout(dmap);
 			spin_unlock_irqrestore(&dmap->lock,flags);
diff --git a/sound/oss/pas2_card.c b/sound/oss/pas2_card.c
index 25f3a22..7f377ec 100644
--- a/sound/oss/pas2_card.c
+++ b/sound/oss/pas2_card.c
@@ -156,9 +156,7 @@
 						 * 0x80
 						 */ , 0xB88);
 
-	pas_write(0x80
-		  | joystick?0x40:0
-		  ,0xF388);
+	pas_write(0x80 | (joystick ? 0x40 : 0), 0xF388);
 
 	if (pas_irq < 0 || pas_irq > 15)
 	{
diff --git a/sound/oss/pss.c b/sound/oss/pss.c
index 16ed069..16517a5 100644
--- a/sound/oss/pss.c
+++ b/sound/oss/pss.c
@@ -457,10 +457,9 @@
 	}
 }
 
-static int set_volume_mono(unsigned __user *p, int *aleft)
+static int set_volume_mono(unsigned __user *p, unsigned int *aleft)
 {
-	int left;
-	unsigned volume;
+	unsigned int left, volume;
 	if (get_user(volume, p))
 		return -EFAULT;
 	
@@ -471,10 +470,11 @@
 	return 0;
 }
 
-static int set_volume_stereo(unsigned __user *p, int *aleft, int *aright)
+static int set_volume_stereo(unsigned __user *p,
+			     unsigned int *aleft,
+			     unsigned int *aright)
 {
-	int left, right;
-	unsigned volume;
+	unsigned int left, right, volume;
 	if (get_user(volume, p))
 		return -EFAULT;
 
diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c
index 5c215f7..c798746 100644
--- a/sound/oss/sequencer.c
+++ b/sound/oss/sequencer.c
@@ -212,7 +212,6 @@
 {
 	unsigned char event_rec[EV_SZ], ev_code;
 	int p = 0, c, ev_size;
-	int err;
 	int mode = translate_mode(file);
 
 	dev = dev >> 4;
@@ -285,7 +284,7 @@
 		{
 			if (!midi_opened[event_rec[2]])
 			{
-				int mode;
+				int err, mode;
 				int dev = event_rec[2];
 
 				if (dev >= max_mididev || midi_devs[dev]==NULL)
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index 41f870f..6055fd6 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -975,9 +975,9 @@
 	struct snd_card *card;
 	struct snd_harmony *h;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	err = snd_harmony_create(card, padev, &h);
 	if (err < 0)
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 82b9bdd..ca25e61 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -400,6 +400,26 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-indigodj
 
+config SND_INDIGOIOX
+	tristate "(Echoaudio) Indigo IOx"
+	select FW_LOADER
+	select SND_PCM
+	help
+	  Say 'Y' or 'M' to include support for Echoaudio Indigo IOx.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-indigoiox
+
+config SND_INDIGODJX
+	tristate "(Echoaudio) Indigo DJx"
+	select FW_LOADER
+	select SND_PCM
+	help
+	  Say 'Y' or 'M' to include support for Echoaudio Indigo DJx.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-indigodjx
+
 config SND_EMU10K1
 	tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)"
 	select FW_LOADER
@@ -744,7 +764,8 @@
 	select SND_OXYGEN_LIB
 	help
 	  Say Y here to include support for sound cards based on the
-	  Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X.
+	  Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, and
+	  Essence STX.
 	  Support for the HDAV1.3 (Deluxe) is very experimental.
 
 	  To compile this driver as a module, choose M here: the module
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index e2b843b..97ee127 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -143,6 +143,7 @@
 { 0x43525970, 0xfffffff8, "CS4202",		NULL,		NULL },
 { 0x43585421, 0xffffffff, "HSD11246",		NULL,		NULL },	// SmartMC II
 { 0x43585428, 0xfffffff8, "Cx20468",		patch_conexant,	NULL }, // SmartAMC fixme: the mask might be different
+{ 0x43585430, 0xffffffff, "Cx20468-31",		patch_conexant, NULL },
 { 0x43585431, 0xffffffff, "Cx20551",           patch_cx20551,  NULL },
 { 0x44543031, 0xfffffff0, "DT0398",		NULL,		NULL },
 { 0x454d4328, 0xffffffff, "EM28028",		NULL,		NULL },  // same as TR28028?
@@ -383,7 +384,7 @@
 
 EXPORT_SYMBOL(snd_ac97_update_bits);
 
-/* no lock version - see snd_ac97_updat_bits() */
+/* no lock version - see snd_ac97_update_bits() */
 int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
 				unsigned short mask, unsigned short value)
 {
@@ -1643,7 +1644,10 @@
 {
 	int err, idx;
 
-	//printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG));
+	/*
+	printk(KERN_DEBUG "AC97_GPIO_CFG = %x\n",
+	       snd_ac97_read(ac97,AC97_GPIO_CFG));
+	*/
 	snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH));
 	snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH));
 	snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff);
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
index 060ea59..73b17d5 100644
--- a/sound/pci/ac97/ac97_proc.c
+++ b/sound/pci/ac97/ac97_proc.c
@@ -125,6 +125,8 @@
         snd_iprintf(buffer, "PCI Subsys Device: 0x%04x\n\n",
                     ac97->subsystem_device);
 
+	snd_iprintf(buffer, "Flags: %x\n", ac97->flags);
+
 	if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) {
 		val = snd_ac97_read(ac97, AC97_INT_PAGING);
 		snd_ac97_update_bits(ac97, AC97_INT_PAGING,
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index a7f38e6..d1f242b 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -995,10 +995,10 @@
 	}
 
 	/* (2) */
-	card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0);
+	err = snd_card_create(index[devno], id[devno], THIS_MODULE, 0, &card);
 	/* XXX REVISIT: we can probably allocate chip in this call */
-	if (card == NULL)
-		return -ENOMEM;
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "AD1889");
 	strcpy(card->shortname, "Analog Devices AD1889");
diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c
index 0f819dd..fd135e3 100644
--- a/sound/pci/ak4531_codec.c
+++ b/sound/pci/ak4531_codec.c
@@ -51,7 +51,8 @@
 	int idx;
 	
 	for (idx = 0; idx < 0x19; idx++)
-		printk("ak4531 0x%x: 0x%x\n", idx, ak4531->regs[idx]);
+		printk(KERN_DEBUG "ak4531 0x%x: 0x%x\n",
+		       idx, ak4531->regs[idx]);
 }
 
 #endif
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 1a0fd65..4edf270 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -2142,7 +2142,7 @@
 {
 	int err;
 
-	snd_ali_printk("resouces allocation ...\n");
+	snd_ali_printk("resources allocation ...\n");
 	err = pci_request_regions(codec->pci, "ALI 5451");
 	if (err < 0)
 		return err;
@@ -2154,7 +2154,7 @@
 		return -EBUSY;
 	}
 	codec->irq = codec->pci->irq;
-	snd_ali_printk("resouces allocated.\n");
+	snd_ali_printk("resources allocated.\n");
 	return 0;
 }
 static int snd_ali_dev_free(struct snd_device *device)
@@ -2307,9 +2307,9 @@
 
 	snd_ali_printk("probe ...\n");
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (!card)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	err = snd_ali_create(card, pci, pcm_channels, spdif, &codec);
 	if (err < 0)
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 8df6824..009b4c8 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -91,7 +91,7 @@
 #define DEBUG_PLAY_REC	0
 
 #if DEBUG_CALLS
-#define snd_als300_dbgcalls(format, args...) printk(format, ##args)
+#define snd_als300_dbgcalls(format, args...) printk(KERN_DEBUG format, ##args)
 #define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
 #define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
 #else
@@ -812,10 +812,10 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
 
-	if (card == NULL)
-		return -ENOMEM;
+	if (err < 0)
+		return err;
 
 	chip_type = pci_id->driver_data;
 
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index ba57005..542a0c6 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -889,12 +889,13 @@
 	pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO);
 	pci_set_master(pci);
 	
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 
-			    sizeof(*acard) /* private_data: acard */);
-	if (card == NULL) {
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 
+			      sizeof(*acard) /* private_data: acard */,
+			      &card);
+	if (err < 0) {
 		pci_release_regions(pci);
 		pci_disable_device(pci);
-		return -ENOMEM;
+		return err;
 	}
 
 	acard = card->private_data;
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 226fe82..9ce8548 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1645,9 +1645,9 @@
 	struct atiixp *chip;
 	int err;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA");
 	strcpy(card->shortname, "ATI IXP");
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 0e6e5cc..c3136cc 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1288,9 +1288,9 @@
 	struct atiixp_modem *chip;
 	int err;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "ATIIXP-MODEM");
 	strcpy(card->shortname, "ATI IXP Modem");
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index a36d4d1..9ec1223 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -250,9 +250,9 @@
 		return -ENOENT;
 	}
 	// (2)
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	// (3)
 	if ((err = snd_vortex_create(card, pci, &chip)) < 0) {
diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c
index 649849e..f4aa8ff 100644
--- a/sound/pci/au88x0/au88x0_a3d.c
+++ b/sound/pci/au88x0/au88x0_a3d.c
@@ -462,9 +462,10 @@
 /* Reset Single A3D source. */
 static void a3dsrc_ZeroState(a3dsrc_t * a)
 {
-
-	//printk("vortex: ZeroState slice: %d, source %d\n", a->slice, a->source);
-
+	/*
+	printk(KERN_DEBUG "vortex: ZeroState slice: %d, source %d\n",
+	       a->slice, a->source);
+	*/
 	a3dsrc_SetAtmosState(a, 0, 0, 0, 0);
 	a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros);
 	a3dsrc_SetItdDline(a, A3dItdDlineZeros);
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index b070e57..3906f5a 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -1135,7 +1135,10 @@
 			snd_pcm_sgbuf_get_addr(dma->substream, 0));
 		break;
 	}
-	//printk("vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", dma->cfg0, dma->cfg1);
+	/*
+	printk(KERN_DEBUG "vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n",
+	       dma->cfg0, dma->cfg1);
+	*/
 	hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0);
 	hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG1 + (adbdma << 3), dma->cfg1);
 
@@ -1959,7 +1962,7 @@
 					  ADB_CODECOUT(0 + 4));
 		vortex_connection_mix_adb(vortex, en, 0x11, mixers[3],
 					  ADB_CODECOUT(1 + 4));
-		//printk("SDAC detected ");
+		/* printk(KERN_DEBUG "SDAC detected "); */
 	}
 #else
 	// Use plain direct output to codec.
@@ -2013,7 +2016,11 @@
 					resmap[restype] |= (1 << i);
 				else
 					vortex->dma_adb[i].resources[restype] |= (1 << i);
-				//printk("vortex: ResManager: type %d out %d\n", restype, i);
+				/*
+				printk(KERN_DEBUG
+				       "vortex: ResManager: type %d out %d\n",
+				       restype, i);
+				*/
 				return i;
 			}
 		}
@@ -2024,7 +2031,11 @@
 		for (i = 0; i < qty; i++) {
 			if (resmap[restype] & (1 << i)) {
 				resmap[restype] &= ~(1 << i);
-				//printk("vortex: ResManager: type %d in %d\n",restype, i);
+				/*
+				printk(KERN_DEBUG
+				       "vortex: ResManager: type %d in %d\n",
+				       restype, i);
+				*/
 				return i;
 			}
 		}
@@ -2789,7 +2800,7 @@
 {
 	int a, this_194;
 
-	if ((bits != 8) || (bits != 16))
+	if ((bits != 8) && (bits != 16))
 		return -1;
 
 	switch (encod) {
diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c
index 978b856..2805e34 100644
--- a/sound/pci/au88x0/au88x0_synth.c
+++ b/sound/pci/au88x0/au88x0_synth.c
@@ -213,38 +213,59 @@
 	switch (reg) {
 		/* Voice specific parameters */
 	case 0:		/* running */
-		//printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_RUN(wt), (int)val);
+		/*
+		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
+		       WT_RUN(wt), (int)val);
+		*/
 		hwwrite(vortex->mmio, WT_RUN(wt), val);
 		return 0xc;
 		break;
 	case 1:		/* param 0 */
-		//printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,0), (int)val);
+		/*
+		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
+		       WT_PARM(wt,0), (int)val);
+		*/
 		hwwrite(vortex->mmio, WT_PARM(wt, 0), val);
 		return 0xc;
 		break;
 	case 2:		/* param 1 */
-		//printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,1), (int)val);
+		/*
+		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
+		       WT_PARM(wt,1), (int)val);
+		*/
 		hwwrite(vortex->mmio, WT_PARM(wt, 1), val);
 		return 0xc;
 		break;
 	case 3:		/* param 2 */
-		//printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,2), (int)val);
+		/*
+		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
+		       WT_PARM(wt,2), (int)val);
+		*/
 		hwwrite(vortex->mmio, WT_PARM(wt, 2), val);
 		return 0xc;
 		break;
 	case 4:		/* param 3 */
-		//printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,3), (int)val);
+		/*
+		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
+		       WT_PARM(wt,3), (int)val);
+		*/
 		hwwrite(vortex->mmio, WT_PARM(wt, 3), val);
 		return 0xc;
 		break;
 	case 6:		/* mute */
-		//printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_MUTE(wt), (int)val);
+		/*
+		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
+		       WT_MUTE(wt), (int)val);
+		*/
 		hwwrite(vortex->mmio, WT_MUTE(wt), val);
 		return 0xc;
 		break;
 	case 0xb:
 		{		/* delay */
-			//printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_DELAY(wt,0), (int)val);
+			/*
+			printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
+			       WT_DELAY(wt,0), (int)val);
+			*/
 			hwwrite(vortex->mmio, WT_DELAY(wt, 3), val);
 			hwwrite(vortex->mmio, WT_DELAY(wt, 2), val);
 			hwwrite(vortex->mmio, WT_DELAY(wt, 1), val);
@@ -272,7 +293,9 @@
 		return 0;
 		break;
 	}
-	//printk("vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val);
+	/*
+	printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val);
+	*/
 	hwwrite(vortex->mmio, ecx, val);
 	return 1;
 }
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index c7c54e7..8eea29f 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -368,9 +368,9 @@
 	}
 
 	/* (2) Create card instance */
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	/* (3) Create main component */
 	err = snd_aw2_create(card, pci, &chip);
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 333007c..e9e9b58 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -211,25 +211,25 @@
 #endif
 
 #if DEBUG_MIXER
-#define snd_azf3328_dbgmixer(format, args...) printk(format, ##args)
+#define snd_azf3328_dbgmixer(format, args...) printk(KERN_DEBUG format, ##args)
 #else
 #define snd_azf3328_dbgmixer(format, args...)
 #endif
 
 #if DEBUG_PLAY_REC
-#define snd_azf3328_dbgplay(format, args...) printk(KERN_ERR format, ##args)
+#define snd_azf3328_dbgplay(format, args...) printk(KERN_DEBUG format, ##args)
 #else
 #define snd_azf3328_dbgplay(format, args...)
 #endif
 
 #if DEBUG_MISC
-#define snd_azf3328_dbgtimer(format, args...) printk(KERN_ERR format, ##args)
+#define snd_azf3328_dbgtimer(format, args...) printk(KERN_DEBUG format, ##args)
 #else
 #define snd_azf3328_dbgtimer(format, args...)
 #endif
 
 #if DEBUG_GAME
-#define snd_azf3328_dbggame(format, args...) printk(KERN_ERR format, ##args)
+#define snd_azf3328_dbggame(format, args...) printk(KERN_DEBUG format, ##args)
 #else
 #define snd_azf3328_dbggame(format, args...)
 #endif
@@ -2216,9 +2216,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "AZF3328");
 	strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 1aa1c04..a299340 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -888,9 +888,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (!card)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	err = snd_bt87x_create(card, pci, &chip);
 	if (err < 0)
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 0e62205..df75757 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -255,6 +255,14 @@
 	   .gpio_type = 2,
 	   .i2c_adc = 1,
 	   .spi_dac = 1 } ,
+	/* Giga-byte GA-G1975X mobo
+	 * Novell bnc#395807
+	 */
+	/* FIXME: the GPIO and I2C setting aren't tested well */
+	{ .serial = 0x1458a006,
+	  .name = "Giga-byte GA-G1975X",
+	  .gpio_type = 1,
+	  .i2c_adc = 1 },
 	 /* Shuttle XPC SD31P which has an onboard Creative Labs
 	  * Sound Blaster Live! 24-bit EAX
 	  * high-definition 7.1 audio processor".
@@ -404,7 +412,9 @@
 	}
 
 	tmp = reg << 25 | value << 16;
-	// snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
+	/*
+	snd_printk(KERN_DEBUG "I2C-write:reg=0x%x, value=0x%x\n", reg, value);
+	*/
 	/* Not sure what this I2C channel controls. */
 	/* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
 
@@ -422,7 +432,7 @@
 		/* Wait till the transaction ends */
 		while (1) {
 			status = snd_ca0106_ptr_read(emu, I2C_A, 0);
-                	//snd_printk("I2C:status=0x%x\n", status);
+			/*snd_printk(KERN_DEBUG "I2C:status=0x%x\n", status);*/
 			timeout++;
 			if ((status & I2C_A_ADC_START) == 0)
 				break;
@@ -521,7 +531,10 @@
         channel->number = channel_id;
 
 	channel->use = 1;
-        //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
+	/*
+	printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n",
+	       channel_id, chip, channel);
+	*/
         //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
 	channel->epcm = epcm;
 	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
@@ -614,7 +627,10 @@
         channel->number = channel_id;
 
 	channel->use = 1;
-        //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
+	/*
+        printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n",
+	       channel_id, chip, channel);
+	*/
         //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
         channel->epcm = epcm;
 	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
@@ -705,9 +721,20 @@
 	u32 reg71;
 	int i;
 	
-        //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
-        //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
-	//snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+#if 0 /* debug */
+	snd_printk(KERN_DEBUG
+		   "prepare:channel_number=%d, rate=%d, format=0x%x, "
+		   "channels=%d, buffer_size=%ld, period_size=%ld, "
+		   "periods=%u, frames_to_bytes=%d\n",
+		   channel, runtime->rate, runtime->format,
+		   runtime->channels, runtime->buffer_size,
+		   runtime->period_size, runtime->periods,
+		   frames_to_bytes(runtime, 1));
+	snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n",
+		   runtime->dma_addr, runtime->dma_area, table_base);
+	snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
+		   emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+#endif /* debug */
 	/* Rate can be set per channel. */
 	/* reg40 control host to fifo */
 	/* reg71 controls DAC rate. */
@@ -799,9 +826,20 @@
 	u32 reg71_set = 0;
 	u32 reg71;
 	
-        //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
-        //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
-	//snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+#if 0 /* debug */
+	snd_printk(KERN_DEBUG
+		   "prepare:channel_number=%d, rate=%d, format=0x%x, "
+		   "channels=%d, buffer_size=%ld, period_size=%ld, "
+		   "periods=%u, frames_to_bytes=%d\n",
+		   channel, runtime->rate, runtime->format,
+		   runtime->channels, runtime->buffer_size,
+		   runtime->period_size, runtime->periods,
+		   frames_to_bytes(runtime, 1));
+        snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n",
+		   runtime->dma_addr, runtime->dma_area, table_base);
+	snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
+		   emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+#endif /* debug */
 	/* reg71 controls ADC rate. */
 	switch (runtime->rate) {
 	case 44100:
@@ -846,7 +884,14 @@
 	}
 
 
-        //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size,  frames_to_bytes(runtime, 1));
+	/*
+	printk(KERN_DEBUG
+	       "prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, "
+	       "buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",
+	       channel, runtime->rate, runtime->format, runtime->channels,
+	       runtime->buffer_size, runtime->period_size,
+	       frames_to_bytes(runtime, 1));
+	*/
 	snd_ca0106_ptr_write(emu, 0x13, channel, 0);
 	snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
 	snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
@@ -888,13 +933,13 @@
 		runtime = s->runtime;
 		epcm = runtime->private_data;
 		channel = epcm->channel_id;
-		/* snd_printk("channel=%d\n",channel); */
+		/* snd_printk(KERN_DEBUG "channel=%d\n", channel); */
 		epcm->running = running;
 		basic |= (0x1 << channel);
 		extended |= (0x10 << channel);
                 snd_pcm_trigger_done(s, substream);
         }
-	/* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */
+	/* snd_printk(KERN_DEBUG "basic=0x%x, extended=0x%x\n",basic, extended); */
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -972,8 +1017,13 @@
 	ptr=ptr2;
         if (ptr >= runtime->buffer_size)
 		ptr -= runtime->buffer_size;
-	//printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
-
+	/*
+	printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
+	       "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n",
+	       ptr1, ptr2, ptr, (int)runtime->buffer_size,
+	       (int)runtime->period_size, (int)runtime->frame_bits,
+	       (int)runtime->rate);
+	*/
 	return ptr;
 }
 
@@ -995,8 +1045,13 @@
 	ptr=ptr2;
         if (ptr >= runtime->buffer_size)
 		ptr -= runtime->buffer_size;
-	//printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
-
+	/*
+	printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
+	       "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n",
+	       ptr1, ptr2, ptr, (int)runtime->buffer_size,
+	       (int)runtime->period_size, (int)runtime->frame_bits,
+	       (int)runtime->rate);
+	*/
 	return ptr;
 }
 
@@ -1181,8 +1236,12 @@
 		return IRQ_NONE;
 
         stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0);
-	//snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76);
-	//snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0));
+	/*
+	snd_printk(KERN_DEBUG "interrupt status = 0x%08x, stat76=0x%08x\n",
+		   status, stat76);
+	snd_printk(KERN_DEBUG "ptr=0x%08x\n",
+		   snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0));
+	*/
         mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
 	for(i = 0; i < 4; i++) {
 		pchannel = &(chip->playback_channels[i]);
@@ -1470,7 +1529,7 @@
 		int size, n;
 
 		size = ARRAY_SIZE(i2c_adc_init);
-		/* snd_printk("I2C:array size=0x%x\n", size); */
+		/* snd_printk(KERN_DEBUG "I2C:array size=0x%x\n", size); */
 		for (n = 0; n < size; n++)
 			snd_ca0106_i2c_write(chip, i2c_adc_init[n][0],
 					     i2c_adc_init[n][1]);
@@ -1707,9 +1766,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	err = snd_ca0106_create(dev, card, pci, &chip);
 	if (err < 0)
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 1a74ca6..c7899c3 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -3272,9 +3272,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	
 	switch (pci->device) {
 	case PCI_DEVICE_ID_CMEDIA_CM8738:
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 192e784..f6286f8 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -834,7 +834,11 @@
 	struct cs4281_dma *dma = runtime->private_data;
 	struct cs4281 *chip = snd_pcm_substream_chip(substream);
 
-	// printk("DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, jiffies);
+	/*
+	printk(KERN_DEBUG "DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n",
+	       snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size,
+	       jiffies);
+	*/
 	return runtime->buffer_size -
 	       snd_cs4281_peekBA0(chip, dma->regDCC) - 1;
 }
@@ -1925,9 +1929,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	if ((err = snd_cs4281_create(card, pci, &chip, dual_codec[dev])) < 0) {
 		snd_card_free(card);
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index e876b32..c9b3e3d 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -88,9 +88,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	if ((err = snd_cs46xx_create(card, pci,
 				     external_amp[dev], thinkpad[dev],
 				     &chip)) < 0) {
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 8ab07aa..1be96ea 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -194,7 +194,7 @@
 	 *  ACSDA = Status Data Register = 474h
 	 */
 #if 0
-	printk("e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg,
+	printk(KERN_DEBUG "e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg,
 			snd_cs46xx_peekBA0(chip, BA0_ACSDA),
 			snd_cs46xx_peekBA0(chip, BA0_ACCAD));
 #endif
@@ -428,8 +428,8 @@
 	}
   
 	if(status & SERBST_WBSY) {
-		snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n");
-
+		snd_printk(KERN_ERR "cs46xx: failure waiting for "
+			   "FIFO command to complete\n");
 		return -EINVAL;
 	}
 
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h
index 018a7de..4eb55aa 100644
--- a/sound/pci/cs46xx/cs46xx_lib.h
+++ b/sound/pci/cs46xx/cs46xx_lib.h
@@ -62,7 +62,11 @@
 	unsigned int bank = reg >> 16;
 	unsigned int offset = reg & 0xffff;
 
-	/*if (bank == 0) printk("snd_cs46xx_poke: %04X - %08X\n",reg >> 2,val); */
+	/*
+	if (bank == 0)
+		printk(KERN_DEBUG "snd_cs46xx_poke: %04X - %08X\n",
+		       reg >> 2,val);
+	*/
 	writel(val, chip->region.idx[bank+1].remap_addr + offset);
 }
 
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index 6dea5b5..dc46432 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -258,10 +258,10 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
 
-	if (card == NULL)
-		return -ENOMEM;
+	if (err < 0)
+		return err;
 
 	err = snd_cs5530_create(card, pci, &chip);
 	if (err < 0) {
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 826e6de..c89ed1f 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -312,7 +312,7 @@
 
 	if (request_irq(pci->irq, snd_cs5535audio_interrupt,
 			IRQF_SHARED, "CS5535 Audio", cs5535au)) {
-		snd_printk("unable to grab IRQ %d\n", pci->irq);
+		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		err = -EBUSY;
 		goto sndfail;
 	}
@@ -353,9 +353,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0)
 		goto probefail_out;
diff --git a/sound/pci/echoaudio/Makefile b/sound/pci/echoaudio/Makefile
index 7b576ae..1361de7 100644
--- a/sound/pci/echoaudio/Makefile
+++ b/sound/pci/echoaudio/Makefile
@@ -15,6 +15,8 @@
 snd-indigo-objs := indigo.o
 snd-indigoio-objs := indigoio.o
 snd-indigodj-objs := indigodj.o
+snd-indigoiox-objs := indigoiox.o
+snd-indigodjx-objs := indigodjx.o
 
 obj-$(CONFIG_SND_DARLA20) += snd-darla20.o
 obj-$(CONFIG_SND_GINA20) += snd-gina20.o
@@ -28,3 +30,5 @@
 obj-$(CONFIG_SND_INDIGO) += snd-indigo.o
 obj-$(CONFIG_SND_INDIGOIO) += snd-indigoio.o
 obj-$(CONFIG_SND_INDIGODJ) += snd-indigodj.o
+obj-$(CONFIG_SND_INDIGOIOX) += snd-indigoiox.o
+obj-$(CONFIG_SND_INDIGODJX) += snd-indigodjx.o
diff --git a/sound/pci/echoaudio/echo3g_dsp.c b/sound/pci/echoaudio/echo3g_dsp.c
index 417e25a..57967e5 100644
--- a/sound/pci/echoaudio/echo3g_dsp.c
+++ b/sound/pci/echoaudio/echo3g_dsp.c
@@ -56,7 +56,7 @@
 	}
 
 	chip->comm_page->e3g_frq_register =
-		__constant_cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2);
+		cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2);
 	chip->device_id = device_id;
 	chip->subdevice_id = subdevice_id;
 	chip->bad_board = TRUE;
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 8dbc5c4..da2065c 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -950,6 +950,8 @@
 	Control interface
 ******************************************************************************/
 
+#ifndef ECHOCARD_HAS_VMIXER
+
 /******************* PCM output volume *******************/
 static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol,
 				     struct snd_ctl_elem_info *uinfo)
@@ -1001,18 +1003,6 @@
 	return changed;
 }
 
-#ifdef ECHOCARD_HAS_VMIXER
-/* On Vmixer cards this one controls the line-out volume */
-static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
-	.name = "Line Playback Volume",
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-	.info = snd_echo_output_gain_info,
-	.get = snd_echo_output_gain_get,
-	.put = snd_echo_output_gain_put,
-	.tlv = {.p = db_scale_output_gain},
-};
-#else
 static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
 	.name = "PCM Playback Volume",
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1022,6 +1012,7 @@
 	.put = snd_echo_output_gain_put,
 	.tlv = {.p = db_scale_output_gain},
 };
+
 #endif
 
 
@@ -1997,9 +1988,9 @@
 
 	DE_INIT(("Echoaudio driver starting...\n"));
 	i = 0;
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	snd_card_set_dev(card, &pci->dev);
 
@@ -2037,8 +2028,6 @@
 
 #ifdef ECHOCARD_HAS_VMIXER
 	snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip);
-	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_output_gain, chip))) < 0)
-		goto ctl_error;
 	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0)
 		goto ctl_error;
 #else
diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h
index 1c88e05..f9490ae 100644
--- a/sound/pci/echoaudio/echoaudio.h
+++ b/sound/pci/echoaudio/echoaudio.h
@@ -189,6 +189,9 @@
 #define INDIGO			0x0090
 #define INDIGO_IO		0x00a0
 #define INDIGO_DJ		0x00b0
+#define DC8			0x00c0
+#define INDIGO_IOX		0x00d0
+#define INDIGO_DJX		0x00e0
 #define ECHO3G			0x0100
 
 
diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c
index c3736bb..e32a748 100644
--- a/sound/pci/echoaudio/echoaudio_3g.c
+++ b/sound/pci/echoaudio/echoaudio_3g.c
@@ -40,8 +40,7 @@
 	if (wait_handshake(chip))
 		return -EIO;
 
-	chip->comm_page->ext_box_status =
-		__constant_cpu_to_le32(E3G_ASIC_NOT_LOADED);
+	chip->comm_page->ext_box_status = cpu_to_le32(E3G_ASIC_NOT_LOADED);
 	chip->asic_loaded = FALSE;
 	clear_handshake(chip);
 	send_vector(chip, DSP_VC_TEST_ASIC);
diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c
index be0e181..4df51ef 100644
--- a/sound/pci/echoaudio/echoaudio_dsp.c
+++ b/sound/pci/echoaudio/echoaudio_dsp.c
@@ -926,11 +926,11 @@
 
 	/* Init the comm page */
 	chip->comm_page->comm_size =
-		__constant_cpu_to_le32(sizeof(struct comm_page));
+		cpu_to_le32(sizeof(struct comm_page));
 	chip->comm_page->handshake = 0xffffffff;
 	chip->comm_page->midi_out_free_count =
-		__constant_cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE);
-	chip->comm_page->sample_rate = __constant_cpu_to_le32(44100);
+		cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE);
+	chip->comm_page->sample_rate = cpu_to_le32(44100);
 	chip->sample_rate = 44100;
 
 	/* Set line levels so we don't blast any inputs on startup */
diff --git a/sound/pci/echoaudio/echoaudio_dsp.h b/sound/pci/echoaudio/echoaudio_dsp.h
index e352f3a..cb7d75a 100644
--- a/sound/pci/echoaudio/echoaudio_dsp.h
+++ b/sound/pci/echoaudio/echoaudio_dsp.h
@@ -576,8 +576,13 @@
 #define E3G_ASIC_NOT_LOADED		0xffff
 #define E3G_BOX_TYPE_MASK		0xf0
 
-#define EXT_3GBOX_NC			0x01
-#define EXT_3GBOX_NOT_SET		0x02
+/* Indigo express control register values */
+#define INDIGO_EXPRESS_32000		0x02
+#define INDIGO_EXPRESS_44100		0x01
+#define INDIGO_EXPRESS_48000		0x00
+#define INDIGO_EXPRESS_DOUBLE_SPEED	0x10
+#define INDIGO_EXPRESS_QUAD_SPEED	0x04
+#define INDIGO_EXPRESS_CLOCK_MASK	0x17
 
 
 /*
diff --git a/sound/pci/echoaudio/gina20_dsp.c b/sound/pci/echoaudio/gina20_dsp.c
index db6c952..3f1e747 100644
--- a/sound/pci/echoaudio/gina20_dsp.c
+++ b/sound/pci/echoaudio/gina20_dsp.c
@@ -208,10 +208,10 @@
 	DE_ACT(("set_professional_spdif %d\n", prof));
 	if (prof)
 		chip->comm_page->flags |=
-			__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+			cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 	else
 		chip->comm_page->flags &=
-			~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+			~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 	chip->professional_spdif = prof;
 	return update_flags(chip);
 }
diff --git a/sound/pci/echoaudio/indigo_dsp.c b/sound/pci/echoaudio/indigo_dsp.c
index f05e39f..0b2cd9c 100644
--- a/sound/pci/echoaudio/indigo_dsp.c
+++ b/sound/pci/echoaudio/indigo_dsp.c
@@ -63,18 +63,6 @@
 	if ((err = init_line_levels(chip)) < 0)
 		return err;
 
-	/* Default routing of the virtual channels: all vchannels are routed
-	to the stereo output */
-	set_vmixer_gain(chip, 0, 0, 0);
-	set_vmixer_gain(chip, 1, 1, 0);
-	set_vmixer_gain(chip, 0, 2, 0);
-	set_vmixer_gain(chip, 1, 3, 0);
-	set_vmixer_gain(chip, 0, 4, 0);
-	set_vmixer_gain(chip, 1, 5, 0);
-	set_vmixer_gain(chip, 0, 6, 0);
-	set_vmixer_gain(chip, 1, 7, 0);
-	err = update_vmixer_level(chip);
-
 	DE_INIT(("init_hw done\n"));
 	return err;
 }
diff --git a/sound/pci/echoaudio/indigo_express_dsp.c b/sound/pci/echoaudio/indigo_express_dsp.c
new file mode 100644
index 0000000..9ab625e
--- /dev/null
+++ b/sound/pci/echoaudio/indigo_express_dsp.c
@@ -0,0 +1,119 @@
+/************************************************************************
+
+This file is part of Echo Digital Audio's generic driver library.
+Copyright Echo Digital Audio Corporation (c) 1998 - 2005
+All rights reserved
+www.echoaudio.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+*************************************************************************/
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+	u32 clock, control_reg, old_control_reg;
+
+	if (wait_handshake(chip))
+		return -EIO;
+
+	old_control_reg = le32_to_cpu(chip->comm_page->control_register);
+	control_reg = old_control_reg & ~INDIGO_EXPRESS_CLOCK_MASK;
+
+	switch (rate) {
+	case 32000:
+		clock = INDIGO_EXPRESS_32000;
+		break;
+	case 44100:
+		clock = INDIGO_EXPRESS_44100;
+		break;
+	case 48000:
+		clock = INDIGO_EXPRESS_48000;
+		break;
+	case 64000:
+		clock = INDIGO_EXPRESS_32000|INDIGO_EXPRESS_DOUBLE_SPEED;
+		break;
+	case 88200:
+		clock = INDIGO_EXPRESS_44100|INDIGO_EXPRESS_DOUBLE_SPEED;
+		break;
+	case 96000:
+		clock = INDIGO_EXPRESS_48000|INDIGO_EXPRESS_DOUBLE_SPEED;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	control_reg |= clock;
+	if (control_reg != old_control_reg) {
+		chip->comm_page->control_register = cpu_to_le32(control_reg);
+		chip->sample_rate = rate;
+		clear_handshake(chip);
+		return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
+	}
+	return 0;
+}
+
+
+
+/* This function routes the sound from a virtual channel to a real output */
+static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
+			   int gain)
+{
+	int index;
+
+	if (snd_BUG_ON(pipe >= num_pipes_out(chip) ||
+		       output >= num_busses_out(chip)))
+		return -EINVAL;
+
+	if (wait_handshake(chip))
+		return -EIO;
+
+	chip->vmixer_gain[output][pipe] = gain;
+	index = output * num_pipes_out(chip) + pipe;
+	chip->comm_page->vmixer[index] = gain;
+
+	DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain));
+	return 0;
+}
+
+
+
+/* Tell the DSP to read and update virtual mixer levels in comm page. */
+static int update_vmixer_level(struct echoaudio *chip)
+{
+	if (wait_handshake(chip))
+		return -EIO;
+	clear_handshake(chip);
+	return send_vector(chip, DSP_VC_SET_VMIXER_GAIN);
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+	return ECHO_CLOCK_BIT_INTERNAL;
+}
+
+
+
+/* The IndigoIO has no ASIC. Just do nothing */
+static int load_asic(struct echoaudio *chip)
+{
+	return 0;
+}
diff --git a/sound/pci/echoaudio/indigodj_dsp.c b/sound/pci/echoaudio/indigodj_dsp.c
index 90730a5..0839291 100644
--- a/sound/pci/echoaudio/indigodj_dsp.c
+++ b/sound/pci/echoaudio/indigodj_dsp.c
@@ -63,18 +63,6 @@
 	if ((err = init_line_levels(chip)) < 0)
 		return err;
 
-	/* Default routing of the virtual channels: vchannels 0-3 and
-	vchannels 4-7 are routed to real channels 0-4 */
-	set_vmixer_gain(chip, 0, 0, 0);
-	set_vmixer_gain(chip, 1, 1, 0);
-	set_vmixer_gain(chip, 2, 2, 0);
-	set_vmixer_gain(chip, 3, 3, 0);
-	set_vmixer_gain(chip, 0, 4, 0);
-	set_vmixer_gain(chip, 1, 5, 0);
-	set_vmixer_gain(chip, 2, 6, 0);
-	set_vmixer_gain(chip, 3, 7, 0);
-	err = update_vmixer_level(chip);
-
 	DE_INIT(("init_hw done\n"));
 	return err;
 }
diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c
new file mode 100644
index 0000000..3482ef6
--- /dev/null
+++ b/sound/pci/echoaudio/indigodjx.c
@@ -0,0 +1,107 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2009 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define INDIGO_FAMILY
+#define ECHOCARD_INDIGO_DJX
+#define ECHOCARD_NAME "Indigo DJx"
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_VMIXER
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT	0	/* 8 */
+#define PX_DIGITAL_OUT	8	/* 0 */
+#define PX_ANALOG_IN	8	/* 0 */
+#define PX_DIGITAL_IN	8	/* 0 */
+#define PX_NUM		8
+
+/* Bus indexes */
+#define BX_ANALOG_OUT	0	/* 4 */
+#define BX_DIGITAL_OUT	4	/* 0 */
+#define BX_ANALOG_IN	4	/* 0 */
+#define BX_DIGITAL_IN	4	/* 0 */
+#define BX_NUM		4
+
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/indigo_djx_dsp.fw");
+
+#define FW_361_LOADER		0
+#define FW_INDIGO_DJX_DSP	1
+
+static const struct firmware card_fw[] = {
+	{0, "loader_dsp.fw"},
+	{0, "indigo_djx_dsp.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+	{0x1057, 0x3410, 0xECC0, 0x00E0, 0, 0, 0},	/* Indigo DJx*/
+	{0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_PAUSE |
+		SNDRV_PCM_INFO_SYNC_START,
+	.formats =	SNDRV_PCM_FMTBIT_U8 |
+			SNDRV_PCM_FMTBIT_S16_LE |
+			SNDRV_PCM_FMTBIT_S24_3LE |
+			SNDRV_PCM_FMTBIT_S32_LE |
+			SNDRV_PCM_FMTBIT_S32_BE,
+	.rates = 	SNDRV_PCM_RATE_32000 |
+			SNDRV_PCM_RATE_44100 |
+			SNDRV_PCM_RATE_48000 |
+			SNDRV_PCM_RATE_88200 |
+			SNDRV_PCM_RATE_96000,
+	.rate_min = 32000,
+	.rate_max = 96000,
+	.channels_min = 1,
+	.channels_max = 4,
+	.buffer_bytes_max = 262144,
+	.period_bytes_min = 32,
+	.period_bytes_max = 131072,
+	.periods_min = 2,
+	.periods_max = 220,
+};
+
+#include "indigodjx_dsp.c"
+#include "indigo_express_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
diff --git a/sound/pci/echoaudio/indigodjx_dsp.c b/sound/pci/echoaudio/indigodjx_dsp.c
new file mode 100644
index 0000000..f591fc2
--- /dev/null
+++ b/sound/pci/echoaudio/indigodjx_dsp.c
@@ -0,0 +1,68 @@
+/************************************************************************
+
+This file is part of Echo Digital Audio's generic driver library.
+Copyright Echo Digital Audio Corporation (c) 1998 - 2005
+All rights reserved
+www.echoaudio.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+*************************************************************************/
+
+static int update_vmixer_level(struct echoaudio *chip);
+static int set_vmixer_gain(struct echoaudio *chip, u16 output,
+			   u16 pipe, int gain);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+	int err;
+
+	DE_INIT(("init_hw() - Indigo DJx\n"));
+	if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_DJX))
+		return -ENODEV;
+
+	err = init_dsp_comm_page(chip);
+	if (err < 0) {
+		DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+		return err;
+	}
+
+	chip->device_id = device_id;
+	chip->subdevice_id = subdevice_id;
+	chip->bad_board = TRUE;
+	chip->dsp_code_to_load = &card_fw[FW_INDIGO_DJX_DSP];
+	/* Since this card has no ASIC, mark it as loaded so everything
+	   works OK */
+	chip->asic_loaded = TRUE;
+	chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL;
+
+	err = load_firmware(chip);
+	if (err < 0)
+		return err;
+	chip->bad_board = FALSE;
+
+	err = init_line_levels(chip);
+	if (err < 0)
+		return err;
+
+	DE_INIT(("init_hw done\n"));
+	return err;
+}
diff --git a/sound/pci/echoaudio/indigoio_dsp.c b/sound/pci/echoaudio/indigoio_dsp.c
index a7e09ec..0604c8a 100644
--- a/sound/pci/echoaudio/indigoio_dsp.c
+++ b/sound/pci/echoaudio/indigoio_dsp.c
@@ -63,18 +63,6 @@
 	if ((err = init_line_levels(chip)) < 0)
 		return err;
 
-	/* Default routing of the virtual channels: all vchannels are routed
-	to the stereo output */
-	set_vmixer_gain(chip, 0, 0, 0);
-	set_vmixer_gain(chip, 1, 1, 0);
-	set_vmixer_gain(chip, 0, 2, 0);
-	set_vmixer_gain(chip, 1, 3, 0);
-	set_vmixer_gain(chip, 0, 4, 0);
-	set_vmixer_gain(chip, 1, 5, 0);
-	set_vmixer_gain(chip, 0, 6, 0);
-	set_vmixer_gain(chip, 1, 7, 0);
-	err = update_vmixer_level(chip);
-
 	DE_INIT(("init_hw done\n"));
 	return err;
 }
diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c
new file mode 100644
index 0000000..aebee27
--- /dev/null
+++ b/sound/pci/echoaudio/indigoiox.c
@@ -0,0 +1,109 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2009 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define INDIGO_FAMILY
+#define ECHOCARD_INDIGO_IOX
+#define ECHOCARD_NAME "Indigo IOx"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_VMIXER
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT	0	/* 8 */
+#define PX_DIGITAL_OUT	8	/* 0 */
+#define PX_ANALOG_IN	8	/* 2 */
+#define PX_DIGITAL_IN	10	/* 0 */
+#define PX_NUM		10
+
+/* Bus indexes */
+#define BX_ANALOG_OUT	0	/* 2 */
+#define BX_DIGITAL_OUT	2	/* 0 */
+#define BX_ANALOG_IN	2	/* 2 */
+#define BX_DIGITAL_IN	4	/* 0 */
+#define BX_NUM		4
+
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/indigo_iox_dsp.fw");
+
+#define FW_361_LOADER		0
+#define FW_INDIGO_IOX_DSP	1
+
+static const struct firmware card_fw[] = {
+	{0, "loader_dsp.fw"},
+	{0, "indigo_iox_dsp.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+	{0x1057, 0x3410, 0xECC0, 0x00D0, 0, 0, 0},	/* Indigo IOx */
+	{0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_PAUSE |
+		SNDRV_PCM_INFO_SYNC_START,
+	.formats =	SNDRV_PCM_FMTBIT_U8 |
+			SNDRV_PCM_FMTBIT_S16_LE |
+			SNDRV_PCM_FMTBIT_S24_3LE |
+			SNDRV_PCM_FMTBIT_S32_LE |
+			SNDRV_PCM_FMTBIT_S32_BE,
+	.rates = 	SNDRV_PCM_RATE_32000 |
+			SNDRV_PCM_RATE_44100 |
+			SNDRV_PCM_RATE_48000 |
+			SNDRV_PCM_RATE_88200 |
+			SNDRV_PCM_RATE_96000,
+	.rate_min = 32000,
+	.rate_max = 96000,
+	.channels_min = 1,
+	.channels_max = 8,
+	.buffer_bytes_max = 262144,
+	.period_bytes_min = 32,
+	.period_bytes_max = 131072,
+	.periods_min = 2,
+	.periods_max = 220,
+};
+
+#include "indigoiox_dsp.c"
+#include "indigo_express_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
+
diff --git a/sound/pci/echoaudio/indigoiox_dsp.c b/sound/pci/echoaudio/indigoiox_dsp.c
new file mode 100644
index 0000000..f357521
--- /dev/null
+++ b/sound/pci/echoaudio/indigoiox_dsp.c
@@ -0,0 +1,68 @@
+/************************************************************************
+
+This file is part of Echo Digital Audio's generic driver library.
+Copyright Echo Digital Audio Corporation (c) 1998 - 2005
+All rights reserved
+www.echoaudio.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+*************************************************************************/
+
+static int update_vmixer_level(struct echoaudio *chip);
+static int set_vmixer_gain(struct echoaudio *chip, u16 output,
+			   u16 pipe, int gain);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+	int err;
+
+	DE_INIT(("init_hw() - Indigo IOx\n"));
+	if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_IOX))
+		return -ENODEV;
+
+	err = init_dsp_comm_page(chip);
+	if (err < 0) {
+		DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+		return err;
+	}
+
+	chip->device_id = device_id;
+	chip->subdevice_id = subdevice_id;
+	chip->bad_board = TRUE;
+	chip->dsp_code_to_load = &card_fw[FW_INDIGO_IOX_DSP];
+	/* Since this card has no ASIC, mark it as loaded so everything
+	   works OK */
+	chip->asic_loaded = TRUE;
+	chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL;
+
+	err = load_firmware(chip);
+	if (err < 0)
+		return err;
+	chip->bad_board = FALSE;
+
+	err = init_line_levels(chip);
+	if (err < 0)
+		return err;
+
+	DE_INIT(("init_hw done\n"));
+	return err;
+}
diff --git a/sound/pci/echoaudio/layla20_dsp.c b/sound/pci/echoaudio/layla20_dsp.c
index ede75c6..83750e9 100644
--- a/sound/pci/echoaudio/layla20_dsp.c
+++ b/sound/pci/echoaudio/layla20_dsp.c
@@ -284,10 +284,10 @@
 	DE_ACT(("set_professional_spdif %d\n", prof));
 	if (prof)
 		chip->comm_page->flags |=
-			__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+			cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 	else
 		chip->comm_page->flags &=
-			~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+			~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 	chip->professional_spdif = prof;
 	return update_flags(chip);
 }
diff --git a/sound/pci/echoaudio/mia_dsp.c b/sound/pci/echoaudio/mia_dsp.c
index 2273866..5514051 100644
--- a/sound/pci/echoaudio/mia_dsp.c
+++ b/sound/pci/echoaudio/mia_dsp.c
@@ -69,18 +69,6 @@
 	if ((err = init_line_levels(chip)))
 		return err;
 
-	/* Default routing of the virtual channels: vchannels 0-3 go to analog
-	outputs and vchannels 4-7 go to S/PDIF outputs */
-	set_vmixer_gain(chip, 0, 0, 0);
-	set_vmixer_gain(chip, 1, 1, 0);
-	set_vmixer_gain(chip, 0, 2, 0);
-	set_vmixer_gain(chip, 1, 3, 0);
-	set_vmixer_gain(chip, 2, 4, 0);
-	set_vmixer_gain(chip, 3, 5, 0);
-	set_vmixer_gain(chip, 2, 6, 0);
-	set_vmixer_gain(chip, 3, 7, 0);
-	err = update_vmixer_level(chip);
-
 	DE_INIT(("init_hw done\n"));
 	return err;
 }
@@ -222,10 +210,10 @@
 	DE_ACT(("set_professional_spdif %d\n", prof));
 	if (prof)
 		chip->comm_page->flags |=
-			__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+			cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 	else
 		chip->comm_page->flags &=
-			~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+			~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
 	chip->professional_spdif = prof;
 	return update_flags(chip);
 }
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c
index 77bf2a8..a953d14 100644
--- a/sound/pci/echoaudio/midi.c
+++ b/sound/pci/echoaudio/midi.c
@@ -44,10 +44,10 @@
 	if (enable) {
 		chip->mtc_state = MIDI_IN_STATE_NORMAL;
 		chip->comm_page->flags |=
-			__constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT);
+			cpu_to_le32(DSP_FLAG_MIDI_INPUT);
 	} else
 		chip->comm_page->flags &=
-			~__constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT);
+			~cpu_to_le32(DSP_FLAG_MIDI_INPUT);
 
 	clear_handshake(chip);
 	return send_vector(chip, DSP_VC_UPDATE_FLAGS);
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 8354c1a..c7f3b99 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -114,9 +114,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	if (max_buffer_size[dev] < 32)
 		max_buffer_size[dev] = 32;
 	else if (max_buffer_size[dev] > 1024)
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c
index 0e649dc..7ef949d9 100644
--- a/sound/pci/emu10k1/emu10k1_callback.c
+++ b/sound/pci/emu10k1/emu10k1_callback.c
@@ -103,7 +103,10 @@
 			int ch;
 			vp = &emu->voices[best[i].voice];
 			if ((ch = vp->ch) < 0) {
-				//printk("synth_get_voice: ch < 0 (%d) ??", i);
+				/*
+				printk(KERN_WARNING
+				       "synth_get_voice: ch < 0 (%d) ??", i);
+				*/
 				continue;
 			}
 			vp->emu->num_voices--;
@@ -335,7 +338,7 @@
 		return -EINVAL;
 	emem->map_locked++;
 	if (snd_emu10k1_memblk_map(hw, emem) < 0) {
-		// printk("emu: cannot map!\n");
+		/* printk(KERN_ERR "emu: cannot map!\n"); */
 		return -ENOMEM;
 	}
 	mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1;
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 101a1c1..f18bd62 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -711,8 +711,7 @@
 static int emu1010_firmware_thread(void *data)
 {
 	struct snd_emu10k1 *emu = data;
-	int tmp, tmp2;
-	int reg;
+	u32 tmp, tmp2, reg;
 	int err;
 
 	for (;;) {
@@ -758,7 +757,8 @@
 			snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n");
 			snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
 			snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
-			snd_printk("Audio Dock ver:%d.%d\n", tmp, tmp2);
+			snd_printk(KERN_INFO "Audio Dock ver: %u.%u\n",
+				   tmp, tmp2);
 			/* Sync clocking between 1010 and Dock */
 			/* Allow DLL to settle */
 			msleep(10);
@@ -804,8 +804,7 @@
 static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
 {
 	unsigned int i;
-	int tmp, tmp2;
-	int reg;
+	u32 tmp, tmp2, reg;
 	int err;
 	const char *filename = NULL;
 
@@ -887,7 +886,7 @@
 	snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n");
 	snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp);
 	snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2);
-	snd_printk("emu1010: Hana version: %d.%d\n", tmp, tmp2);
+	snd_printk(KERN_INFO "emu1010: Hana version: %u.%u\n", tmp, tmp2);
 	/* Enable 48Volt power to Audio Dock */
 	snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON);
 
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 5ff4dbb..31542ad 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1544,9 +1544,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	if ((err = snd_emu10k1x_create(card, pci, &chip)) < 0) {
 		snd_card_free(card);
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 7dba08f..191e1cd 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -1519,7 +1519,7 @@
 	/* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
 	if (emu->card_capabilities->emu_model) {
 		/* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */
-		snd_printk("EMU outputs on\n");
+		snd_printk(KERN_INFO "EMU outputs on\n");
 		for (z = 0; z < 8; z++) {
 			if (emu->card_capabilities->ca0108_chip) {
 				A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
@@ -1567,7 +1567,7 @@
 
 	if (emu->card_capabilities->emu_model) {
 		if (emu->card_capabilities->ca0108_chip) {
-			snd_printk("EMU2 inputs on\n");
+			snd_printk(KERN_INFO "EMU2 inputs on\n");
 			for (z = 0; z < 0x10; z++) {
 				snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, 
 									bit_shifter16,
@@ -1575,10 +1575,13 @@
 									A_FXBUS2(z*2) );
 			}
 		} else {
-			snd_printk("EMU inputs on\n");
+			snd_printk(KERN_INFO "EMU inputs on\n");
 			/* Capture 16 (originally 8) channels of S32_LE sound */
 
-			/* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
+			/*
+			printk(KERN_DEBUG "emufx.c: gpr=0x%x, tmp=0x%x\n",
+			       gpr, tmp);
+			*/
 			/* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
 			/* A_P16VIN(0) is delayed by one sample,
 			 * so all other A_P16VIN channels will need to also be delayed
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index cf9276d..78f62fd 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -44,7 +44,7 @@
 	if (epcm->substream == NULL)
 		return;
 #if 0
-	printk("IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n",
+	printk(KERN_DEBUG "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n",
 			epcm->substream->runtime->hw->pointer(emu, epcm->substream),
 			snd_pcm_lib_period_bytes(epcm->substream),
 			snd_pcm_lib_buffer_bytes(epcm->substream));
@@ -146,7 +146,11 @@
 					      1,
 					      &epcm->extra);
 		if (err < 0) {
-			/* printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); */
+			/*
+			printk(KERN_DEBUG "pcm_channel_alloc: "
+			       "failed extra: voices=%d, frame=%d\n",
+			       voices, frame);
+			*/
 			for (i = 0; i < voices; i++) {
 				snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
 				epcm->voices[i] = NULL;
@@ -737,7 +741,10 @@
 	struct snd_emu10k1_pcm_mixer *mix;
 	int result = 0;
 
-	/* printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); */
+	/*
+	printk(KERN_DEBUG "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n",
+	       (int)emu, cmd, substream->ops->pointer(substream))
+	*/
 	spin_lock(&emu->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -786,7 +793,10 @@
 		/* hmm this should cause full and half full interrupt to be raised? */
 		outl(epcm->capture_ipr, emu->port + IPR);
 		snd_emu10k1_intr_enable(emu, epcm->capture_inte);
-		/* printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); */
+		/*
+		printk(KERN_DEBUG "adccr = 0x%x, adcbs = 0x%x\n",
+		       epcm->adccr, epcm->adcbs);
+		*/
 		switch (epcm->type) {
 		case CAPTURE_AC97ADC:
 			snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
@@ -857,7 +867,11 @@
 			ptr -= runtime->buffer_size;
 	}
 #endif
-	/* printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size); */
+	/*
+	printk(KERN_DEBUG
+	       "ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n",
+	       ptr, runtime->buffer_size, runtime->period_size);
+	*/
 	return ptr;
 }
 
@@ -1546,7 +1560,11 @@
 						   unsigned int count,
 						   unsigned int tram_shift)
 {
-	/* printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); */
+	/*
+	printk(KERN_DEBUG "tram_poke1: dst_left = 0x%p, dst_right = 0x%p, "
+	       "src = 0x%p, count = 0x%x\n",
+	       dst_left, dst_right, src, count);
+	*/
 	if ((tram_shift & 1) == 0) {
 		while (count--) {
 			*dst_left-- = *src++;
@@ -1623,7 +1641,12 @@
 	struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
 	unsigned int i;
 	
-	/* printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); */
+	/*
+	printk(KERN_DEBUG "prepare: etram_pages = 0x%p, dma_area = 0x%x, "
+	       "buffer_size = 0x%x (0x%x)\n",
+	       emu->fx8010.etram_pages, runtime->dma_area,
+	       runtime->buffer_size, runtime->buffer_size << 2);
+	*/
 	memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
 	pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
 	pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index b5a802b..4bfc31d 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -226,7 +226,9 @@
 				break;
 
 			if (timeout > 1000) {
-                		snd_printk("emu10k1:I2C:timeout status=0x%x\n", status);
+                		snd_printk(KERN_WARNING
+					   "emu10k1:I2C:timeout status=0x%x\n",
+					   status);
 				break;
 			}
 		}
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index 749a21b..e617aca 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -168,7 +168,7 @@
 	struct snd_emu10k1_pcm *epcm = runtime->private_data;
   
 	if (epcm) {
-        	//snd_printk("epcm free: %p\n", epcm);
+        	/* snd_printk(KERN_DEBUG "epcm free: %p\n", epcm); */
 		kfree(epcm);
 	}
 }
@@ -183,14 +183,16 @@
 	int err;
 
 	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
-        //snd_printk("epcm kcalloc: %p\n", epcm);
+        /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */
 
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
 	epcm->substream = substream;
-        //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
-  
+	/*
+	snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n",
+		   substream->pcm->device, channel_id);
+	*/
 	runtime->private_data = epcm;
 	runtime->private_free = snd_p16v_pcm_free_substream;
   
@@ -200,10 +202,15 @@
         channel->number = channel_id;
 
         channel->use=1;
-	//snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
-        //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
-        //channel->interrupt = snd_p16v_pcm_channel_interrupt;
-        channel->epcm=epcm;
+#if 0 /* debug */
+	snd_printk(KERN_DEBUG
+		   "p16v: open channel_id=%d, channel=%p, use=0x%x\n",
+		   channel_id, channel, channel->use);
+	printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n",
+	       channel_id, chip, channel);
+#endif /* debug */
+	/* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
+	channel->epcm = epcm;
 	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
                 return err;
 
@@ -224,14 +231,16 @@
 	int err;
 
 	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
-	//snd_printk("epcm kcalloc: %p\n", epcm);
+	/* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */
 
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
 	epcm->substream = substream;
-	//snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
-
+	/*
+	snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n",
+		   substream->pcm->device, channel_id);
+	*/
 	runtime->private_data = epcm;
 	runtime->private_free = snd_p16v_pcm_free_substream;
   
@@ -241,10 +250,15 @@
 	channel->number = channel_id;
 
 	channel->use=1;
-	//snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
-	//printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
-	//channel->interrupt = snd_p16v_pcm_channel_interrupt;
-	channel->epcm=epcm;
+#if 0 /* debug */
+	snd_printk(KERN_DEBUG
+		   "p16v: open channel_id=%d, channel=%p, use=0x%x\n",
+		   channel_id, channel, channel->use);
+	printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n",
+	       channel_id, chip, channel);
+#endif /* debug */
+	/* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
+	channel->epcm = epcm;
 	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
 		return err;
 
@@ -334,9 +348,19 @@
 	int i;
 	u32 tmp;
 	
-        //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
-        //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
-	//snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer.bytes);
+#if 0 /* debug */
+	snd_printk(KERN_DEBUG "prepare:channel_number=%d, rate=%d, "
+		   "format=0x%x, channels=%d, buffer_size=%ld, "
+		   "period_size=%ld, periods=%u, frames_to_bytes=%d\n",
+		   channel, runtime->rate, runtime->format, runtime->channels,
+		   runtime->buffer_size, runtime->period_size,
+		   runtime->periods, frames_to_bytes(runtime, 1));
+	snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n",
+		   runtime->dma_addr, runtime->dma_area, table_base);
+	snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
+		   emu->p16v_buffer.addr, emu->p16v_buffer.area,
+		   emu->p16v_buffer.bytes);
+#endif /* debug */
 	tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
         switch (runtime->rate) {
 	case 44100:
@@ -379,7 +403,15 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int channel = substream->pcm->device - emu->p16v_device_offset;
 	u32 tmp;
-	//printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size,  frames_to_bytes(runtime, 1));
+
+	/*
+	printk(KERN_DEBUG "prepare capture:channel_number=%d, rate=%d, "
+	       "format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, "
+	       "frames_to_bytes=%d\n",
+	       channel, runtime->rate, runtime->format, runtime->channels,
+	       runtime->buffer_size, runtime->period_size,
+	       frames_to_bytes(runtime, 1));
+	*/
 	tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
         switch (runtime->rate) {
 	case 44100:
@@ -459,13 +491,13 @@
 		runtime = s->runtime;
 		epcm = runtime->private_data;
 		channel = substream->pcm->device-emu->p16v_device_offset;
-		//snd_printk("p16v channel=%d\n",channel);
+		/* snd_printk(KERN_DEBUG "p16v channel=%d\n", channel); */
 		epcm->running = running;
 		basic |= (0x1<<channel);
 		inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel);
                 snd_pcm_trigger_done(s, substream);
         }
-	//snd_printk("basic=0x%x, inte=0x%x\n",basic, inte);
+	/* snd_printk(KERN_DEBUG "basic=0x%x, inte=0x%x\n", basic, inte); */
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -558,8 +590,13 @@
 		ptr -= runtime->buffer_size;
 		printk(KERN_WARNING "buffer capture limited!\n");
 	}
-	//printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
-
+	/*
+	printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
+	       "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n",
+	       ptr1, ptr2, ptr, (int)runtime->buffer_size,
+	       (int)runtime->period_size, (int)runtime->frame_bits,
+	       (int)runtime->rate);
+	*/
 	return ptr;
 }
 
@@ -592,7 +629,10 @@
 	// release the data
 	if (chip->p16v_buffer.area) {
 		snd_dma_free_pages(&chip->p16v_buffer);
-		//snd_printk("period lables free: %p\n", &chip->p16v_buffer);
+		/*
+		snd_printk(KERN_DEBUG "period lables free: %p\n",
+			   &chip->p16v_buffer);
+		*/
 	}
 	return 0;
 }
@@ -604,7 +644,7 @@
 	int err;
         int capture=1;
   
-	//snd_printk("snd_p16v_pcm called. device=%d\n", device);
+	/* snd_printk("KERN_DEBUG snd_p16v_pcm called. device=%d\n", device); */
 	emu->p16v_device_offset = device;
 	if (rpcm)
 		*rpcm = NULL;
@@ -631,7 +671,10 @@
 							 snd_dma_pci_data(emu->pci), 
 							 ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) 
 			return err;
-		//snd_printk("preallocate playback substream: err=%d\n", err);
+		/*
+		snd_printk(KERN_DEBUG
+			   "preallocate playback substream: err=%d\n", err);
+		*/
 	}
 
 	for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 
@@ -642,7 +685,10 @@
 	                                           snd_dma_pci_data(emu->pci), 
 	                                           65536 - 64, 65536 - 64)) < 0)
 			return err;
-		//snd_printk("preallocate capture substream: err=%d\n", err);
+		/*
+		snd_printk(KERN_DEBUG
+			   "preallocate capture substream: err=%d\n", err);
+		*/
 	}
   
 	if (rpcm)
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index d7300a1..20b8da2 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -53,7 +53,10 @@
 	*rvoice = NULL;
 	first_voice = last_voice = 0;
 	for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) {
-		// printk("i %d j %d next free %d!\n", i, j, emu->next_free_voice);
+		/*
+		printk(KERN_DEBUG "i %d j %d next free %d!\n",
+		       i, j, emu->next_free_voice);
+		*/
 		i %= NUM_G;
 
 		/* stereo voices must be even/odd */
@@ -71,7 +74,7 @@
 			}
 		}
 		if (!skip) {
-			// printk("allocated voice %d\n", i);
+			/* printk(KERN_DEBUG "allocated voice %d\n", i); */
 			first_voice = i;
 			last_voice = (i + number) % NUM_G;
 			emu->next_free_voice = last_voice;
@@ -84,7 +87,10 @@
 	
 	for (i = 0; i < number; i++) {
 		voice = &emu->voices[(first_voice + i) % NUM_G];
-		// printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number);
+		/*
+		printk(kERN_DEBUG "voice alloc - %i, %i of %i\n",
+		       voice->number, idx-first_voice+1, number);
+		*/
 		voice->use = 1;
 		switch (type) {
 		case EMU10K1_PCM:
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 9bf9536..18f4d1e 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -584,7 +584,8 @@
 	unsigned long end_time = jiffies + HZ / 10;
 
 #if 0
-	printk("CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n",
+	printk(KERN_DEBUG
+	       "CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n",
 	       reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC));
 #endif
 	do {
@@ -2409,9 +2410,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	if ((err = snd_ensoniq_create(card, pci, &ensoniq)) < 0) {
 		snd_card_free(card);
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 4cd9a1fa..dd63b13 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1673,18 +1673,22 @@
 
 	status = inb(SLIO_REG(chip, IRQCONTROL));
 #if 0
-	printk("Es1938debug - interrupt status: =0x%x\n", status);
+	printk(KERN_DEBUG "Es1938debug - interrupt status: =0x%x\n", status);
 #endif
 	
 	/* AUDIO 1 */
 	if (status & 0x10) {
 #if 0
-                printk("Es1938debug - AUDIO channel 1 interrupt\n");
-		printk("Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n",
+                printk(KERN_DEBUG
+		       "Es1938debug - AUDIO channel 1 interrupt\n");
+		printk(KERN_DEBUG
+		       "Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n",
 		       inw(SLDM_REG(chip, DMACOUNT)));
-		printk("Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n",
+		printk(KERN_DEBUG
+		       "Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n",
 		       inl(SLDM_REG(chip, DMAADDR)));
-		printk("Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n",
+		printk(KERN_DEBUG
+		       "Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n",
 		       inl(SLDM_REG(chip, DMASTATUS)));
 #endif
 		/* clear irq */
@@ -1699,10 +1703,13 @@
 	/* AUDIO 2 */
 	if (status & 0x20) {
 #if 0
-                printk("Es1938debug - AUDIO channel 2 interrupt\n");
-		printk("Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n",
+                printk(KERN_DEBUG
+		       "Es1938debug - AUDIO channel 2 interrupt\n");
+		printk(KERN_DEBUG
+		       "Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n",
 		       inw(SLIO_REG(chip, AUDIO2DMACOUNT)));
-		printk("Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n",
+		printk(KERN_DEBUG
+		       "Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n",
 		       inl(SLIO_REG(chip, AUDIO2DMAADDR)));
 
 #endif
@@ -1799,9 +1806,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	for (idx = 0; idx < 5; idx++) {
 		if (pci_resource_start(pci, idx) == 0 ||
 		    !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index e9c3794..dc97e81 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2645,9 +2645,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (!card)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
                 
 	if (total_bufsize[dev] < 128)
 		total_bufsize[dev] = 128;
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index c129f9e..60cdb9e 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1468,9 +1468,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) {
 		snd_card_free(card);
 		return err;
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 960fd79..4de5bac 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -138,6 +138,7 @@
 
 		input_unregister_device(beep->dev);
 		kfree(beep);
+		codec->beep = NULL;
 	}
 }
 EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
index b9679f0..51bf6a5 100644
--- a/sound/pci/hda/hda_beep.h
+++ b/sound/pci/hda/hda_beep.h
@@ -39,7 +39,7 @@
 int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
 void snd_hda_detach_beep_device(struct hda_codec *codec);
 #else
-#define snd_hda_attach_beep_device(...)
+#define snd_hda_attach_beep_device(...)		0
 #define snd_hda_detach_beep_device(...)
 #endif
 #endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index d03f992..a4e5e59 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -647,9 +647,9 @@
 
 	total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
 	for (i = 0; i < total_nodes; i++, nid++) {
-		unsigned int func;
-		func = snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE);
-		switch (func & 0xff) {
+		codec->function_id = snd_hda_param_read(codec, nid,
+						AC_PAR_FUNCTION_TYPE) & 0xff;
+		switch (codec->function_id) {
 		case AC_GRP_AUDIO_FUNCTION:
 			codec->afg = nid;
 			break;
@@ -682,11 +682,140 @@
 	return 0;
 }
 
+/* read all pin default configurations and save codec->init_pins */
+static int read_pin_defaults(struct hda_codec *codec)
+{
+	int i;
+	hda_nid_t nid = codec->start_nid;
+
+	for (i = 0; i < codec->num_nodes; i++, nid++) {
+		struct hda_pincfg *pin;
+		unsigned int wcaps = get_wcaps(codec, nid);
+		unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
+				AC_WCAP_TYPE_SHIFT;
+		if (wid_type != AC_WID_PIN)
+			continue;
+		pin = snd_array_new(&codec->init_pins);
+		if (!pin)
+			return -ENOMEM;
+		pin->nid = nid;
+		pin->cfg = snd_hda_codec_read(codec, nid, 0,
+					      AC_VERB_GET_CONFIG_DEFAULT, 0);
+	}
+	return 0;
+}
+
+/* look up the given pin config list and return the item matching with NID */
+static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
+					 struct snd_array *array,
+					 hda_nid_t nid)
+{
+	int i;
+	for (i = 0; i < array->used; i++) {
+		struct hda_pincfg *pin = snd_array_elem(array, i);
+		if (pin->nid == nid)
+			return pin;
+	}
+	return NULL;
+}
+
+/* write a config value for the given NID */
+static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
+		       unsigned int cfg)
+{
+	int i;
+	for (i = 0; i < 4; i++) {
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
+				    cfg & 0xff);
+		cfg >>= 8;
+	}
+}
+
+/* set the current pin config value for the given NID.
+ * the value is cached, and read via snd_hda_codec_get_pincfg()
+ */
+int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
+		       hda_nid_t nid, unsigned int cfg)
+{
+	struct hda_pincfg *pin;
+	unsigned int oldcfg;
+
+	oldcfg = snd_hda_codec_get_pincfg(codec, nid);
+	pin = look_up_pincfg(codec, list, nid);
+	if (!pin) {
+		pin = snd_array_new(list);
+		if (!pin)
+			return -ENOMEM;
+		pin->nid = nid;
+	}
+	pin->cfg = cfg;
+
+	/* change only when needed; e.g. if the pincfg is already present
+	 * in user_pins[], don't write it
+	 */
+	cfg = snd_hda_codec_get_pincfg(codec, nid);
+	if (oldcfg != cfg)
+		set_pincfg(codec, nid, cfg);
+	return 0;
+}
+
+int snd_hda_codec_set_pincfg(struct hda_codec *codec,
+			     hda_nid_t nid, unsigned int cfg)
+{
+	return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
+}
+EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
+
+/* get the current pin config value of the given pin NID */
+unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct hda_pincfg *pin;
+
+#ifdef CONFIG_SND_HDA_HWDEP
+	pin = look_up_pincfg(codec, &codec->user_pins, nid);
+	if (pin)
+		return pin->cfg;
+#endif
+	pin = look_up_pincfg(codec, &codec->driver_pins, nid);
+	if (pin)
+		return pin->cfg;
+	pin = look_up_pincfg(codec, &codec->init_pins, nid);
+	if (pin)
+		return pin->cfg;
+	return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
+
+/* restore all current pin configs */
+static void restore_pincfgs(struct hda_codec *codec)
+{
+	int i;
+	for (i = 0; i < codec->init_pins.used; i++) {
+		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+		set_pincfg(codec, pin->nid,
+			   snd_hda_codec_get_pincfg(codec, pin->nid));
+	}
+}
 
 static void init_hda_cache(struct hda_cache_rec *cache,
 			   unsigned int record_size);
 static void free_hda_cache(struct hda_cache_rec *cache);
 
+/* restore the initial pin cfgs and release all pincfg lists */
+static void restore_init_pincfgs(struct hda_codec *codec)
+{
+	/* first free driver_pins and user_pins, then call restore_pincfg
+	 * so that only the values in init_pins are restored
+	 */
+	snd_array_free(&codec->driver_pins);
+#ifdef CONFIG_SND_HDA_HWDEP
+	snd_array_free(&codec->user_pins);
+#endif
+	restore_pincfgs(codec);
+	snd_array_free(&codec->init_pins);
+}
+
 /*
  * codec destructor
  */
@@ -694,6 +823,7 @@
 {
 	if (!codec)
 		return;
+	restore_init_pincfgs(codec);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	cancel_delayed_work(&codec->power_work);
 	flush_workqueue(codec->bus->workq);
@@ -712,6 +842,9 @@
 	kfree(codec);
 }
 
+static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
+				unsigned int power_state);
+
 /**
  * snd_hda_codec_new - create a HDA codec
  * @bus: the bus to assign
@@ -751,6 +884,8 @@
 	init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
 	init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
 	snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
+	snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
+	snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
 	if (codec->bus->modelname) {
 		codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
 		if (!codec->modelname) {
@@ -787,15 +922,18 @@
 	setup_fg_nodes(codec);
 	if (!codec->afg && !codec->mfg) {
 		snd_printdd("hda_codec: no AFG or MFG node found\n");
-		snd_hda_codec_free(codec);
-		return -ENODEV;
+		err = -ENODEV;
+		goto error;
 	}
 
-	if (read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg) < 0) {
+	err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
+	if (err < 0) {
 		snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
-		snd_hda_codec_free(codec);
-		return -ENOMEM;
+		goto error;
 	}
+	err = read_pin_defaults(codec);
+	if (err < 0)
+		goto error;
 
 	if (!codec->subsystem_id) {
 		hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
@@ -806,12 +944,15 @@
 	if (bus->modelname)
 		codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
 
+	/* power-up all before initialization */
+	hda_set_power_state(codec,
+			    codec->afg ? codec->afg : codec->mfg,
+			    AC_PWRST_D0);
+
 	if (do_init) {
 		err = snd_hda_codec_configure(codec);
-		if (err < 0) {
-			snd_hda_codec_free(codec);
-			return err;
-		}
+		if (err < 0)
+			goto error;
 	}
 	snd_hda_codec_proc_new(codec);
 
@@ -824,6 +965,10 @@
 	if (codecp)
 		*codecp = codec;
 	return 0;
+
+ error:
+	snd_hda_codec_free(codec);
+	return err;
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_new);
 
@@ -907,6 +1052,7 @@
 
 /* FIXME: more better hash key? */
 #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
+#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
 #define INFO_AMP_CAPS	(1<<0)
 #define INFO_AMP_VOL(ch)	(1 << (1 + (ch)))
 
@@ -997,6 +1143,21 @@
 }
 EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
 
+u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct hda_amp_info *info;
+
+	info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));
+	if (!info)
+		return 0;
+	if (!info->head.val) {
+		info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+		info->head.val |= INFO_AMP_CAPS;
+	}
+	return info->amp_caps;
+}
+EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
+
 /*
  * read the current volume to info
  * if the cache exists, read the cache value.
@@ -1120,6 +1281,7 @@
 	u16 nid = get_amp_nid(kcontrol);
 	u8 chs = get_amp_channels(kcontrol);
 	int dir = get_amp_direction(kcontrol);
+	unsigned int ofs = get_amp_offset(kcontrol);
 	u32 caps;
 
 	caps = query_amp_caps(codec, nid, dir);
@@ -1131,6 +1293,8 @@
 		       kcontrol->id.name);
 		return -EINVAL;
 	}
+	if (ofs < caps)
+		caps -= ofs;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = chs == 3 ? 2 : 1;
 	uinfo->value.integer.min = 0;
@@ -1139,6 +1303,32 @@
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
 
+
+static inline unsigned int
+read_amp_value(struct hda_codec *codec, hda_nid_t nid,
+	       int ch, int dir, int idx, unsigned int ofs)
+{
+	unsigned int val;
+	val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
+	val &= HDA_AMP_VOLMASK;
+	if (val >= ofs)
+		val -= ofs;
+	else
+		val = 0;
+	return val;
+}
+
+static inline int
+update_amp_value(struct hda_codec *codec, hda_nid_t nid,
+		 int ch, int dir, int idx, unsigned int ofs,
+		 unsigned int val)
+{
+	if (val > 0)
+		val += ofs;
+	return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
+					HDA_AMP_VOLMASK, val);
+}
+
 int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
@@ -1147,14 +1337,13 @@
 	int chs = get_amp_channels(kcontrol);
 	int dir = get_amp_direction(kcontrol);
 	int idx = get_amp_index(kcontrol);
+	unsigned int ofs = get_amp_offset(kcontrol);
 	long *valp = ucontrol->value.integer.value;
 
 	if (chs & 1)
-		*valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx)
-			& HDA_AMP_VOLMASK;
+		*valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
 	if (chs & 2)
-		*valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx)
-			& HDA_AMP_VOLMASK;
+		*valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
 	return 0;
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
@@ -1167,18 +1356,17 @@
 	int chs = get_amp_channels(kcontrol);
 	int dir = get_amp_direction(kcontrol);
 	int idx = get_amp_index(kcontrol);
+	unsigned int ofs = get_amp_offset(kcontrol);
 	long *valp = ucontrol->value.integer.value;
 	int change = 0;
 
 	snd_hda_power_up(codec);
 	if (chs & 1) {
-		change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
-						  0x7f, *valp);
+		change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
 		valp++;
 	}
 	if (chs & 2)
-		change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
-						   0x7f, *valp);
+		change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
 	snd_hda_power_down(codec);
 	return change;
 }
@@ -1190,6 +1378,7 @@
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = get_amp_nid(kcontrol);
 	int dir = get_amp_direction(kcontrol);
+	unsigned int ofs = get_amp_offset(kcontrol);
 	u32 caps, val1, val2;
 
 	if (size < 4 * sizeof(unsigned int))
@@ -1198,6 +1387,7 @@
 	val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
 	val2 = (val2 + 1) * 25;
 	val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
+	val1 += ofs;
 	val1 = ((int)val1) * ((int)val2);
 	if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
 		return -EFAULT;
@@ -1268,7 +1458,6 @@
 }
 EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
 
-#ifdef CONFIG_SND_HDA_RECONFIG
 /* Clear all controls assigned to the given codec */
 void snd_hda_ctls_clear(struct hda_codec *codec)
 {
@@ -1279,9 +1468,52 @@
 	snd_array_free(&codec->mixers);
 }
 
-void snd_hda_codec_reset(struct hda_codec *codec)
+/* pseudo device locking
+ * toggle card->shutdown to allow/disallow the device access (as a hack)
+ */
+static int hda_lock_devices(struct snd_card *card)
 {
-	int i;
+	spin_lock(&card->files_lock);
+	if (card->shutdown) {
+		spin_unlock(&card->files_lock);
+		return -EINVAL;
+	}
+	card->shutdown = 1;
+	spin_unlock(&card->files_lock);
+	return 0;
+}
+
+static void hda_unlock_devices(struct snd_card *card)
+{
+	spin_lock(&card->files_lock);
+	card->shutdown = 0;
+	spin_unlock(&card->files_lock);
+}
+
+int snd_hda_codec_reset(struct hda_codec *codec)
+{
+	struct snd_card *card = codec->bus->card;
+	int i, pcm;
+
+	if (hda_lock_devices(card) < 0)
+		return -EBUSY;
+	/* check whether the codec isn't used by any mixer or PCM streams */
+	if (!list_empty(&card->ctl_files)) {
+		hda_unlock_devices(card);
+		return -EBUSY;
+	}
+	for (pcm = 0; pcm < codec->num_pcms; pcm++) {
+		struct hda_pcm *cpcm = &codec->pcm_info[pcm];
+		if (!cpcm->pcm)
+			continue;
+		if (cpcm->pcm->streams[0].substream_opened ||
+		    cpcm->pcm->streams[1].substream_opened) {
+			hda_unlock_devices(card);
+			return -EBUSY;
+		}
+	}
+
+	/* OK, let it free */
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	cancel_delayed_work(&codec->power_work);
@@ -1291,8 +1523,7 @@
 	/* relase PCMs */
 	for (i = 0; i < codec->num_pcms; i++) {
 		if (codec->pcm_info[i].pcm) {
-			snd_device_free(codec->bus->card,
-					codec->pcm_info[i].pcm);
+			snd_device_free(card, codec->pcm_info[i].pcm);
 			clear_bit(codec->pcm_info[i].device,
 				  codec->bus->pcm_dev_bits);
 		}
@@ -1305,13 +1536,22 @@
 	free_hda_cache(&codec->cmd_cache);
 	init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
 	init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
+	/* free only driver_pins so that init_pins + user_pins are restored */
+	snd_array_free(&codec->driver_pins);
+	restore_pincfgs(codec);
 	codec->num_pcms = 0;
 	codec->pcm_info = NULL;
 	codec->preset = NULL;
+	memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
+	codec->slave_dig_outs = NULL;
+	codec->spdif_status_reset = 0;
 	module_put(codec->owner);
 	codec->owner = NULL;
+
+	/* allow device access again */
+	hda_unlock_devices(card);
+	return 0;
 }
-#endif /* CONFIG_SND_HDA_RECONFIG */
 
 /* create a virtual master control and add slaves */
 int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
@@ -1336,15 +1576,20 @@
 	
 	for (s = slaves; *s; s++) {
 		struct snd_kcontrol *sctl;
-
-		sctl = snd_hda_find_mixer_ctl(codec, *s);
-		if (!sctl) {
-			snd_printdd("Cannot find slave %s, skipped\n", *s);
-			continue;
+		int i = 0;
+		for (;;) {
+			sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
+			if (!sctl) {
+				if (!i)
+					snd_printdd("Cannot find slave %s, "
+						    "skipped\n", *s);
+				break;
+			}
+			err = snd_ctl_add_slave(kctl, sctl);
+			if (err < 0)
+				return err;
+			i++;
 		}
-		err = snd_ctl_add_slave(kctl, sctl);
-		if (err < 0)
-			return err;
 	}
 	return 0;
 }
@@ -1955,6 +2200,8 @@
 	}
 	for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
 		kctl = snd_ctl_new1(dig_mix, codec);
+		if (!kctl)
+			return -ENOMEM;
 		kctl->private_value = nid;
 		err = snd_hda_ctl_add(codec, kctl);
 		if (err < 0)
@@ -2074,8 +2321,7 @@
 				 * don't power down the widget if it controls
 				 * eapd and EAPD_BTLENABLE is set.
 				 */
-				pincap = snd_hda_param_read(codec, nid,
-							    AC_PAR_PIN_CAP);
+				pincap = snd_hda_query_pin_caps(codec, nid);
 				if (pincap & AC_PINCAP_EAPD) {
 					int eapd = snd_hda_codec_read(codec,
 						nid, 0,
@@ -2144,6 +2390,7 @@
 	hda_set_power_state(codec,
 			    codec->afg ? codec->afg : codec->mfg,
 			    AC_PWRST_D0);
+	restore_pincfgs(codec); /* restore all current pin configs */
 	hda_exec_init_verbs(codec);
 	if (codec->patch_ops.resume)
 		codec->patch_ops.resume(codec);
@@ -2171,8 +2418,16 @@
 
 	list_for_each_entry(codec, &bus->codec_list, list) {
 		int err = snd_hda_codec_build_controls(codec);
-		if (err < 0)
-			return err;
+		if (err < 0) {
+			printk(KERN_ERR "hda_codec: cannot build controls"
+			       "for #%d (error %d)\n", codec->addr, err); 
+			err = snd_hda_codec_reset(codec);
+			if (err < 0) {
+				printk(KERN_ERR
+				       "hda_codec: cannot revert codec\n");
+				return err;
+			}
+		}
 	}
 	return 0;
 }
@@ -2181,19 +2436,12 @@
 int snd_hda_codec_build_controls(struct hda_codec *codec)
 {
 	int err = 0;
-	/* fake as if already powered-on */
-	hda_keep_power_on(codec);
-	/* then fire up */
-	hda_set_power_state(codec,
-			    codec->afg ? codec->afg : codec->mfg,
-			    AC_PWRST_D0);
 	hda_exec_init_verbs(codec);
 	/* continue to initialize... */
 	if (codec->patch_ops.init)
 		err = codec->patch_ops.init(codec);
 	if (!err && codec->patch_ops.build_controls)
 		err = codec->patch_ops.build_controls(codec);
-	snd_hda_power_down(codec);
 	if (err < 0)
 		return err;
 	return 0;
@@ -2306,12 +2554,11 @@
 static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 				u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
 {
-	int i;
-	unsigned int val, streams;
+	unsigned int i, val, wcaps;
 
 	val = 0;
-	if (nid != codec->afg &&
-	    (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
+	wcaps = get_wcaps(codec, nid);
+	if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) {
 		val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
 		if (val == -1)
 			return -EIO;
@@ -2325,15 +2572,20 @@
 			if (val & (1 << i))
 				rates |= rate_bits[i].alsa_bits;
 		}
+		if (rates == 0) {
+			snd_printk(KERN_ERR "hda_codec: rates == 0 "
+				   "(nid=0x%x, val=0x%x, ovrd=%i)\n",
+					nid, val,
+					(wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
+			return -EIO;
+		}
 		*ratesp = rates;
 	}
 
 	if (formatsp || bpsp) {
 		u64 formats = 0;
-		unsigned int bps;
-		unsigned int wcaps;
+		unsigned int streams, bps;
 
-		wcaps = get_wcaps(codec, nid);
 		streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
 		if (streams == -1)
 			return -EIO;
@@ -2386,6 +2638,15 @@
 			formats |= SNDRV_PCM_FMTBIT_U8;
 			bps = 8;
 		}
+		if (formats == 0) {
+			snd_printk(KERN_ERR "hda_codec: formats == 0 "
+				   "(nid=0x%x, val=0x%x, ovrd=%i, "
+				   "streams=0x%x)\n",
+					nid, val,
+					(wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
+					streams);
+			return -EIO;
+		}
 		if (formatsp)
 			*formatsp = formats;
 		if (bpsp)
@@ -2501,12 +2762,16 @@
 static int set_pcm_default_values(struct hda_codec *codec,
 				  struct hda_pcm_stream *info)
 {
+	int err;
+
 	/* query support PCM information from the given NID */
 	if (info->nid && (!info->rates || !info->formats)) {
-		snd_hda_query_supported_pcm(codec, info->nid,
+		err = snd_hda_query_supported_pcm(codec, info->nid,
 				info->rates ? NULL : &info->rates,
 				info->formats ? NULL : &info->formats,
 				info->maxbps ? NULL : &info->maxbps);
+		if (err < 0)
+			return err;
 	}
 	if (info->ops.open == NULL)
 		info->ops.open = hda_pcm_default_open_close;
@@ -2549,13 +2814,10 @@
 		for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
 			dev = audio_idx[i];
 			if (!test_bit(dev, bus->pcm_dev_bits))
-				break;
+				goto ok;
 		}
-		if (i >= ARRAY_SIZE(audio_idx)) {
-			snd_printk(KERN_WARNING "Too many audio devices\n");
-			return -EAGAIN;
-		}
-		break;
+		snd_printk(KERN_WARNING "Too many audio devices\n");
+		return -EAGAIN;
 	case HDA_PCM_TYPE_SPDIF:
 	case HDA_PCM_TYPE_HDMI:
 	case HDA_PCM_TYPE_MODEM:
@@ -2570,6 +2832,7 @@
 		snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
 		return -EINVAL;
 	}
+ ok:
 	set_bit(dev, bus->pcm_dev_bits);
 	return dev;
 }
@@ -2606,24 +2869,36 @@
 		if (!codec->patch_ops.build_pcms)
 			return 0;
 		err = codec->patch_ops.build_pcms(codec);
-		if (err < 0)
-			return err;
+		if (err < 0) {
+			printk(KERN_ERR "hda_codec: cannot build PCMs"
+			       "for #%d (error %d)\n", codec->addr, err); 
+			err = snd_hda_codec_reset(codec);
+			if (err < 0) {
+				printk(KERN_ERR
+				       "hda_codec: cannot revert codec\n");
+				return err;
+			}
+		}
 	}
 	for (pcm = 0; pcm < codec->num_pcms; pcm++) {
 		struct hda_pcm *cpcm = &codec->pcm_info[pcm];
 		int dev;
 
 		if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
-			return 0; /* no substreams assigned */
+			continue; /* no substreams assigned */
 
 		if (!cpcm->pcm) {
 			dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
 			if (dev < 0)
-				return 0;
+				continue; /* no fatal error */
 			cpcm->device = dev;
 			err = snd_hda_attach_pcm(codec, cpcm);
-			if (err < 0)
-				return err;
+			if (err < 0) {
+				printk(KERN_ERR "hda_codec: cannot attach "
+				       "PCM stream %d for codec #%d\n",
+				       dev, codec->addr);
+				continue; /* no fatal error */
+			}
 		}
 	}
 	return 0;
@@ -3324,8 +3599,7 @@
 		if (ignore_nids && is_in_nid_list(nid, ignore_nids))
 			continue;
 
-		def_conf = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_CONFIG_DEFAULT, 0);
+		def_conf = snd_hda_codec_get_pincfg(codec, nid);
 		if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
 			continue;
 		loc = get_defcfg_location(def_conf);
@@ -3401,10 +3675,22 @@
 			cfg->input_pins[AUTO_PIN_AUX] = nid;
 			break;
 		case AC_JACK_SPDIF_OUT:
-			cfg->dig_out_pin = nid;
+		case AC_JACK_DIG_OTHER_OUT:
+			if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
+				continue;
+			cfg->dig_out_pins[cfg->dig_outs] = nid;
+			cfg->dig_out_type[cfg->dig_outs] =
+				(loc == AC_JACK_LOC_HDMI) ?
+				HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
+			cfg->dig_outs++;
 			break;
 		case AC_JACK_SPDIF_IN:
+		case AC_JACK_DIG_OTHER_IN:
 			cfg->dig_in_pin = nid;
+			if (loc == AC_JACK_LOC_HDMI)
+				cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
+			else
+				cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
 			break;
 		}
 	}
@@ -3510,6 +3796,9 @@
 		   cfg->hp_pins[1], cfg->hp_pins[2],
 		   cfg->hp_pins[3], cfg->hp_pins[4]);
 	snd_printd("   mono: mono_out=0x%x\n", cfg->mono_out_pin);
+	if (cfg->dig_outs)
+		snd_printd("   dig-out=0x%x/0x%x\n",
+			   cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
 	snd_printd("   inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
 		   " cd=0x%x, aux=0x%x\n",
 		   cfg->input_pins[AUTO_PIN_MIC],
@@ -3518,6 +3807,8 @@
 		   cfg->input_pins[AUTO_PIN_FRONT_LINE],
 		   cfg->input_pins[AUTO_PIN_CD],
 		   cfg->input_pins[AUTO_PIN_AUX]);
+	if (cfg->dig_in_pin)
+		snd_printd("   dig-in=0x%x\n", cfg->dig_in_pin);
 
 	return 0;
 }
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 09a332a..2fdecf4 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -739,6 +739,7 @@
 	hda_nid_t mfg;	/* MFG node id */
 
 	/* ids */
+	u32 function_id;
 	u32 vendor_id;
 	u32 subsystem_id;
 	u32 revision_id;
@@ -778,11 +779,14 @@
 	unsigned short spdif_ctls;	/* SPDIF control bits */
 	unsigned int spdif_in_enable;	/* SPDIF input enable? */
 	hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
+	struct snd_array init_pins;	/* initial (BIOS) pin configurations */
+	struct snd_array driver_pins;	/* pin configs set by codec parser */
 
 #ifdef CONFIG_SND_HDA_HWDEP
 	struct snd_hwdep *hwdep;	/* assigned hwdep device */
 	struct snd_array init_verbs;	/* additional init verbs */
 	struct snd_array hints;		/* additional hints */
+	struct snd_array user_pins;	/* default pin configs to override */
 #endif
 
 	/* misc flags */
@@ -790,6 +794,9 @@
 					     * status change
 					     * (e.g. Realtek codecs)
 					     */
+	unsigned int pin_amp_workaround:1; /* pin out-amp takes index
+					    * (e.g. Conexant codecs)
+					    */
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	unsigned int power_on :1;	/* current (global) power-state */
 	unsigned int power_transition :1; /* power-state in transition */
@@ -855,6 +862,18 @@
 #define snd_hda_sequence_write_cache	snd_hda_sequence_write
 #endif
 
+/* the struct for codec->pin_configs */
+struct hda_pincfg {
+	hda_nid_t nid;
+	unsigned int cfg;
+};
+
+unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid);
+int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid,
+			     unsigned int cfg);
+int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
+		       hda_nid_t nid, unsigned int cfg); /* for hwdep */
+
 /*
  * Mixer
  */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 65745e9..1d5797a 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -144,9 +144,9 @@
 	node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 
 	if (node->type == AC_WID_PIN) {
-		node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP);
+		node->pin_caps = snd_hda_query_pin_caps(codec, node->nid);
 		node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-		node->def_cfg = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+		node->def_cfg = snd_hda_codec_get_pincfg(codec, node->nid);
 	}
 
 	if (node->wid_caps & AC_WCAP_OUT_AMP) {
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 4ae51dc..1c57505 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -30,6 +30,12 @@
 #include <sound/hda_hwdep.h>
 #include <sound/minors.h>
 
+/* hint string pair */
+struct hda_hint {
+	const char *key;
+	const char *val;	/* contained in the same alloc as key */
+};
+
 /*
  * write/read an out-of-bound verb
  */
@@ -99,16 +105,17 @@
 
 static void clear_hwdep_elements(struct hda_codec *codec)
 {
-	char **head;
 	int i;
 
 	/* clear init verbs */
 	snd_array_free(&codec->init_verbs);
 	/* clear hints */
-	head = codec->hints.list;
-	for (i = 0; i < codec->hints.used; i++, head++)
-		kfree(*head);
+	for (i = 0; i < codec->hints.used; i++) {
+		struct hda_hint *hint = snd_array_elem(&codec->hints, i);
+		kfree(hint->key); /* we don't need to free hint->val */
+	}
 	snd_array_free(&codec->hints);
+	snd_array_free(&codec->user_pins);
 }
 
 static void hwdep_free(struct snd_hwdep *hwdep)
@@ -140,7 +147,8 @@
 #endif
 
 	snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
-	snd_array_init(&codec->hints, sizeof(char *), 32);
+	snd_array_init(&codec->hints, sizeof(struct hda_hint), 32);
+	snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
 
 	return 0;
 }
@@ -153,7 +161,13 @@
 
 static int clear_codec(struct hda_codec *codec)
 {
-	snd_hda_codec_reset(codec);
+	int err;
+
+	err = snd_hda_codec_reset(codec);
+	if (err < 0) {
+		snd_printk(KERN_ERR "The codec is being used, can't free.\n");
+		return err;
+	}
 	clear_hwdep_elements(codec);
 	return 0;
 }
@@ -162,20 +176,29 @@
 {
 	int err;
 
+	snd_hda_power_up(codec);
 	snd_printk(KERN_INFO "hda-codec: reconfiguring\n");
-	snd_hda_codec_reset(codec);
+	err = snd_hda_codec_reset(codec);
+	if (err < 0) {
+		snd_printk(KERN_ERR
+			   "The codec is being used, can't reconfigure.\n");
+		goto error;
+	}
 	err = snd_hda_codec_configure(codec);
 	if (err < 0)
-		return err;
+		goto error;
 	/* rebuild PCMs */
 	err = snd_hda_codec_build_pcms(codec);
 	if (err < 0)
-		return err;
+		goto error;
 	/* rebuild mixers */
 	err = snd_hda_codec_build_controls(codec);
 	if (err < 0)
-		return err;
-	return snd_card_register(codec->bus->card);
+		goto error;
+	err = snd_card_register(codec->bus->card);
+ error:
+	snd_hda_power_down(codec);
+	return err;
 }
 
 /*
@@ -271,6 +294,22 @@
 CODEC_ACTION_STORE(reconfig);
 CODEC_ACTION_STORE(clear);
 
+static ssize_t init_verbs_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+	struct hda_codec *codec = hwdep->private_data;
+	int i, len = 0;
+	for (i = 0; i < codec->init_verbs.used; i++) {
+		struct hda_verb *v = snd_array_elem(&codec->init_verbs, i);
+		len += snprintf(buf + len, PAGE_SIZE - len,
+				"0x%02x 0x%03x 0x%04x\n",
+				v->nid, v->verb, v->param);
+	}
+	return len;
+}
+
 static ssize_t init_verbs_store(struct device *dev,
 				struct device_attribute *attr,
 				const char *buf, size_t count)
@@ -293,26 +332,157 @@
 	return count;
 }
 
+static ssize_t hints_show(struct device *dev,
+			  struct device_attribute *attr,
+			  char *buf)
+{
+	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+	struct hda_codec *codec = hwdep->private_data;
+	int i, len = 0;
+	for (i = 0; i < codec->hints.used; i++) {
+		struct hda_hint *hint = snd_array_elem(&codec->hints, i);
+		len += snprintf(buf + len, PAGE_SIZE - len,
+				"%s = %s\n", hint->key, hint->val);
+	}
+	return len;
+}
+
+static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
+{
+	int i;
+
+	for (i = 0; i < codec->hints.used; i++) {
+		struct hda_hint *hint = snd_array_elem(&codec->hints, i);
+		if (!strcmp(hint->key, key))
+			return hint;
+	}
+	return NULL;
+}
+
+static void remove_trail_spaces(char *str)
+{
+	char *p;
+	if (!*str)
+		return;
+	p = str + strlen(str) - 1;
+	for (; isspace(*p); p--) {
+		*p = 0;
+		if (p == str)
+			return;
+	}
+}
+
+#define MAX_HINTS	1024
+
 static ssize_t hints_store(struct device *dev,
 			   struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
 	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
 	struct hda_codec *codec = hwdep->private_data;
-	char *p;
-	char **hint;
+	char *key, *val;
+	struct hda_hint *hint;
 
-	if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n')
+	while (isspace(*buf))
+		buf++;
+	if (!*buf || *buf == '#' || *buf == '\n')
 		return count;
-	p = kstrndup_noeol(buf, 1024);
-	if (!p)
+	if (*buf == '=')
+		return -EINVAL;
+	key = kstrndup_noeol(buf, 1024);
+	if (!key)
 		return -ENOMEM;
-	hint = snd_array_new(&codec->hints);
+	/* extract key and val */
+	val = strchr(key, '=');
+	if (!val) {
+		kfree(key);
+		return -EINVAL;
+	}
+	*val++ = 0;
+	while (isspace(*val))
+		val++;
+	remove_trail_spaces(key);
+	remove_trail_spaces(val);
+	hint = get_hint(codec, key);
+	if (hint) {
+		/* replace */
+		kfree(hint->key);
+		hint->key = key;
+		hint->val = val;
+		return count;
+	}
+	/* allocate a new hint entry */
+	if (codec->hints.used >= MAX_HINTS)
+		hint = NULL;
+	else
+		hint = snd_array_new(&codec->hints);
 	if (!hint) {
-		kfree(p);
+		kfree(key);
 		return -ENOMEM;
 	}
-	*hint = p;
+	hint->key = key;
+	hint->val = val;
+	return count;
+}
+
+static ssize_t pin_configs_show(struct hda_codec *codec,
+				struct snd_array *list,
+				char *buf)
+{
+	int i, len = 0;
+	for (i = 0; i < list->used; i++) {
+		struct hda_pincfg *pin = snd_array_elem(list, i);
+		len += sprintf(buf + len, "0x%02x 0x%08x\n",
+			       pin->nid, pin->cfg);
+	}
+	return len;
+}
+
+static ssize_t init_pin_configs_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+	struct hda_codec *codec = hwdep->private_data;
+	return pin_configs_show(codec, &codec->init_pins, buf);
+}
+
+static ssize_t user_pin_configs_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+	struct hda_codec *codec = hwdep->private_data;
+	return pin_configs_show(codec, &codec->user_pins, buf);
+}
+
+static ssize_t driver_pin_configs_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+	struct hda_codec *codec = hwdep->private_data;
+	return pin_configs_show(codec, &codec->driver_pins, buf);
+}
+
+#define MAX_PIN_CONFIGS		32
+
+static ssize_t user_pin_configs_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+	struct hda_codec *codec = hwdep->private_data;
+	int nid, cfg;
+	int err;
+
+	if (sscanf(buf, "%i %i", &nid, &cfg) != 2)
+		return -EINVAL;
+	if (!nid)
+		return -EINVAL;
+	err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg);
+	if (err < 0)
+		return err;
 	return count;
 }
 
@@ -331,8 +501,11 @@
 	CODEC_ATTR_RO(mfg),
 	CODEC_ATTR_RW(name),
 	CODEC_ATTR_RW(modelname),
-	CODEC_ATTR_WO(init_verbs),
-	CODEC_ATTR_WO(hints),
+	CODEC_ATTR_RW(init_verbs),
+	CODEC_ATTR_RW(hints),
+	CODEC_ATTR_RO(init_pin_configs),
+	CODEC_ATTR_RW(user_pin_configs),
+	CODEC_ATTR_RO(driver_pin_configs),
 	CODEC_ATTR_WO(reconfig),
 	CODEC_ATTR_WO(clear),
 };
@@ -351,4 +524,29 @@
 	return 0;
 }
 
+/*
+ * Look for hint string
+ */
+const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
+{
+	struct hda_hint *hint = get_hint(codec, key);
+	return hint ? hint->val : NULL;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_hint);
+
+int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
+{
+	const char *p = snd_hda_get_hint(codec, key);
+	if (!p || !*p)
+		return -ENOENT;
+	switch (toupper(*p)) {
+	case 'T': /* true */
+	case 'Y': /* yes */
+	case '1':
+		return 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint);
+
 #endif /* CONFIG_SND_HDA_RECONFIG */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 5e909e0..30829ee 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -381,6 +381,7 @@
 
 	/* HD codec */
 	unsigned short codec_mask;
+	int  codec_probe_mask; /* copied from probe_mask option */
 	struct hda_bus *bus;
 
 	/* CORB/RIRB */
@@ -858,13 +859,18 @@
 		      SD_CTL_DMA_START | SD_INT_MASK);
 }
 
-/* stop a stream */
-static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
+/* stop DMA */
+static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev)
 {
-	/* stop DMA */
 	azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
 		      ~(SD_CTL_DMA_START | SD_INT_MASK));
 	azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
+}
+
+/* stop a stream */
+static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
+{
+	azx_stream_clear(chip, azx_dev);
 	/* disable SIE */
 	azx_writeb(chip, INTCTL,
 		   azx_readb(chip, INTCTL) & ~(1 << azx_dev->index));
@@ -1075,8 +1081,7 @@
 	azx_sd_writel(azx_dev, SD_BDLPL, 0);
 	azx_sd_writel(azx_dev, SD_BDLPU, 0);
 
-	period_bytes = snd_pcm_lib_period_bytes(substream);
-	azx_dev->period_bytes = period_bytes;
+	period_bytes = azx_dev->period_bytes;
 	periods = azx_dev->bufsize / period_bytes;
 
 	/* program the initial BDL entries */
@@ -1123,24 +1128,17 @@
  error:
 	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;
 }
 
-/*
- * set up the SD for streaming
- */
-static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
+/* reset stream */
+static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
 {
 	unsigned char val;
 	int timeout;
 
-	/* make sure the run bit is zero for SD */
-	azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
-		      ~SD_CTL_DMA_START);
-	/* reset stream */
+	azx_stream_clear(chip, azx_dev);
+
 	azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
 		      SD_CTL_STREAM_RESET);
 	udelay(3);
@@ -1157,7 +1155,15 @@
 	while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
 	       --timeout)
 		;
+}
 
+/*
+ * set up the SD for streaming
+ */
+static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
+{
+	/* make sure the run bit is zero for SD */
+	azx_stream_clear(chip, azx_dev);
 	/* program the stream_tag */
 	azx_sd_writel(azx_dev, SD_CTL,
 		      (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)|
@@ -1228,7 +1234,6 @@
 };
 
 static int __devinit azx_codec_create(struct azx *chip, const char *model,
-				      unsigned int codec_probe_mask,
 				      int no_init)
 {
 	struct hda_bus_template bus_temp;
@@ -1261,7 +1266,7 @@
 
 	/* First try to probe all given codec slots */
 	for (c = 0; c < max_slots; c++) {
-		if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
+		if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
 			if (probe_codec(chip, c) < 0) {
 				/* Some BIOSen give you wrong codec addresses
 				 * that don't exist
@@ -1285,7 +1290,7 @@
 
 	/* Then create codec instances */
 	for (c = 0; c < max_slots; c++) {
-		if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
+		if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
 			struct hda_codec *codec;
 			err = snd_hda_codec_new(chip->bus, c, !no_init, &codec);
 			if (err < 0)
@@ -1403,6 +1408,8 @@
 	runtime->private_data = azx_dev;
 	snd_pcm_set_sync(substream);
 	mutex_unlock(&chip->open_mutex);
+
+	azx_stream_reset(chip, azx_dev);
 	return 0;
 }
 
@@ -1429,6 +1436,11 @@
 static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *hw_params)
 {
+	struct azx_dev *azx_dev = get_azx_dev(substream);
+
+	azx_dev->bufsize = 0;
+	azx_dev->period_bytes = 0;
+	azx_dev->format_val = 0;
 	return snd_pcm_lib_malloc_pages(substream,
 					params_buffer_bytes(hw_params));
 }
@@ -1443,6 +1455,9 @@
 	azx_sd_writel(azx_dev, SD_BDLPL, 0);
 	azx_sd_writel(azx_dev, SD_BDLPU, 0);
 	azx_sd_writel(azx_dev, SD_CTL, 0);
+	azx_dev->bufsize = 0;
+	azx_dev->period_bytes = 0;
+	azx_dev->format_val = 0;
 
 	hinfo->ops.cleanup(hinfo, apcm->codec, substream);
 
@@ -1456,23 +1471,37 @@
 	struct azx_dev *azx_dev = get_azx_dev(substream);
 	struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned int bufsize, period_bytes, format_val;
+	int err;
 
-	azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
-	azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
-							 runtime->channels,
-							 runtime->format,
-							 hinfo->maxbps);
-	if (!azx_dev->format_val) {
+	format_val = snd_hda_calc_stream_format(runtime->rate,
+						runtime->channels,
+						runtime->format,
+						hinfo->maxbps);
+	if (!format_val) {
 		snd_printk(KERN_ERR SFX
 			   "invalid format_val, rate=%d, ch=%d, format=%d\n",
 			   runtime->rate, runtime->channels, runtime->format);
 		return -EINVAL;
 	}
 
+	bufsize = snd_pcm_lib_buffer_bytes(substream);
+	period_bytes = snd_pcm_lib_period_bytes(substream);
+
 	snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
-		    azx_dev->bufsize, azx_dev->format_val);
-	if (azx_setup_periods(chip, substream, azx_dev) < 0)
-		return -EINVAL;
+		    bufsize, format_val);
+
+	if (bufsize != azx_dev->bufsize ||
+	    period_bytes != azx_dev->period_bytes ||
+	    format_val != azx_dev->format_val) {
+		azx_dev->bufsize = bufsize;
+		azx_dev->period_bytes = period_bytes;
+		azx_dev->format_val = format_val;
+		err = azx_setup_periods(chip, substream, azx_dev);
+		if (err < 0)
+			return err;
+	}
+
 	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;
@@ -2059,26 +2088,31 @@
 {
 	const struct snd_pci_quirk *q;
 
-	/* Check VIA HD Audio Controller exist */
-	if (chip->pci->vendor == PCI_VENDOR_ID_VIA &&
-	    chip->pci->device == VIA_HDAC_DEVICE_ID) {
+	switch (fix) {
+	case POS_FIX_LPIB:
+	case POS_FIX_POSBUF:
+		return fix;
+	}
+
+	/* Check VIA/ATI HD Audio Controller exist */
+	switch (chip->driver_type) {
+	case AZX_DRIVER_VIA:
+	case AZX_DRIVER_ATI:
 		chip->via_dmapos_patch = 1;
 		/* Use link position directly, avoid any transfer problem. */
 		return POS_FIX_LPIB;
 	}
 	chip->via_dmapos_patch = 0;
 
-	if (fix == POS_FIX_AUTO) {
-		q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
-		if (q) {
-			printk(KERN_INFO
-				    "hda_intel: position_fix set to %d "
-				    "for device %04x:%04x\n",
-				    q->value, q->subvendor, q->subdevice);
-			return q->value;
-		}
+	q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
+	if (q) {
+		printk(KERN_INFO
+		       "hda_intel: position_fix set to %d "
+		       "for device %04x:%04x\n",
+		       q->value, q->subvendor, q->subdevice);
+		return q->value;
 	}
-	return fix;
+	return POS_FIX_AUTO;
 }
 
 /*
@@ -2095,25 +2129,36 @@
 	SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
 	/* including bogus ALC268 in slot#2 that conflicts with ALC888 */
 	SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
-	/* conflict of ALC268 in slot#3 (digital I/O); a temporary fix */
-	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba laptop", 0x03),
+	/* forced codec slots */
+	SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
 	{}
 };
 
+#define AZX_FORCE_CODEC_MASK	0x100
+
 static void __devinit check_probe_mask(struct azx *chip, int dev)
 {
 	const struct snd_pci_quirk *q;
 
-	if (probe_mask[dev] == -1) {
+	chip->codec_probe_mask = probe_mask[dev];
+	if (chip->codec_probe_mask == -1) {
 		q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
 		if (q) {
 			printk(KERN_INFO
 			       "hda_intel: probe_mask set to 0x%x "
 			       "for device %04x:%04x\n",
 			       q->value, q->subvendor, q->subdevice);
-			probe_mask[dev] = q->value;
+			chip->codec_probe_mask = q->value;
 		}
 	}
+
+	/* check forced option */
+	if (chip->codec_probe_mask != -1 &&
+	    (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) {
+		chip->codec_mask = chip->codec_probe_mask & 0xff;
+		printk(KERN_INFO "hda_intel: codec_mask forced to 0x%x\n",
+		       chip->codec_mask);
+	}
 }
 
 
@@ -2210,9 +2255,17 @@
 	gcap = azx_readw(chip, GCAP);
 	snd_printdd("chipset global capabilities = 0x%x\n", gcap);
 
+	/* ATI chips seems buggy about 64bit DMA addresses */
+	if (chip->driver_type == AZX_DRIVER_ATI)
+		gcap &= ~0x01;
+
 	/* 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);
+	else {
+		pci_set_dma_mask(pci, DMA_32BIT_MASK);
+		pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK);
+	}
 
 	/* read number of streams from GCAP register instead of using
 	 * hardcoded value
@@ -2334,10 +2387,10 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (!card) {
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0) {
 		snd_printk(KERN_ERR SFX "Error creating card!\n");
-		return -ENOMEM;
+		return err;
 	}
 
 	err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
@@ -2346,8 +2399,7 @@
 	card->private_data = chip;
 
 	/* create codec instances */
-	err = azx_codec_create(chip, model[dev], probe_mask[dev],
-			       probe_only[dev]);
+	err = azx_codec_create(chip, model[dev], probe_only[dev]);
 	if (err < 0)
 		goto out_free;
 
@@ -2444,10 +2496,10 @@
 	{ 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 },
+	{ PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA },
 	/* Teradici */
 	{ PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
 	/* AMD Generic, PCI class code and Vendor ID for HD Audio */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 44f189c..8334901 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -26,8 +26,10 @@
 /*
  * for mixer controls
  */
+#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs)		\
+	((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23))
 #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
-	((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19))
+	HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0)
 /* mono volume with index (index=0,1,...) (channel=1,2) */
 #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx,  \
@@ -96,7 +98,7 @@
 					    const char *name);
 int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
 			unsigned int *tlv, const char **slaves);
-void snd_hda_codec_reset(struct hda_codec *codec);
+int snd_hda_codec_reset(struct hda_codec *codec);
 int snd_hda_codec_configure(struct hda_codec *codec);
 
 /* amp value bits */
@@ -134,7 +136,7 @@
 
 struct hda_bind_ctls {
 	struct hda_ctl_ops *ops;
-	long values[];
+	unsigned long values[];
 };
 
 int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
@@ -227,6 +229,7 @@
 	hda_nid_t hp_nid;	/* optional DAC for HP, 0 when not exists */
 	hda_nid_t extra_out_nid[3];	/* optional DACs, 0 when not exists */
 	hda_nid_t dig_out_nid;	/* digital out audio widget */
+	hda_nid_t *slave_dig_outs;
 	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 */
@@ -354,9 +357,12 @@
 	int line_out_type;	/* AUTO_PIN_XXX_OUT */
 	hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
 	hda_nid_t input_pins[AUTO_PIN_LAST];
-	hda_nid_t dig_out_pin;
+	int dig_outs;
+	hda_nid_t dig_out_pins[2];
 	hda_nid_t dig_in_pin;
 	hda_nid_t mono_out_pin;
+	int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */
+	int dig_in_type; /* HDA_PCM_TYPE_XXX */
 };
 
 #define get_defcfg_connect(cfg) \
@@ -405,6 +411,7 @@
 u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
 int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
 			      unsigned int caps);
+u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
 
 int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl);
 void snd_hda_ctls_clear(struct hda_codec *codec);
@@ -427,6 +434,23 @@
 }
 #endif
 
+#ifdef CONFIG_SND_HDA_RECONFIG
+const char *snd_hda_get_hint(struct hda_codec *codec, const char *key);
+int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key);
+#else
+static inline
+const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
+{
+	return NULL;
+}
+
+static inline
+int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
+{
+	return -ENOENT;
+}
+#endif
+
 /*
  * power-management
  */
@@ -458,6 +482,7 @@
 #define get_amp_channels(kc)	(((kc)->private_value >> 16) & 0x3)
 #define get_amp_direction(kc)	(((kc)->private_value >> 18) & 0x1)
 #define get_amp_index(kc)	(((kc)->private_value >> 19) & 0xf)
+#define get_amp_offset(kc)	(((kc)->private_value >> 23) & 0x3f)
 
 /*
  * CEA Short Audio Descriptor data
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 144b852..93d7499 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -399,8 +399,10 @@
 {
 	int c, curr = -1;
 
-	if (conn_len > 1 && wid_type != AC_WID_AUD_MIX &&
-	    wid_type != AC_WID_VOL_KNB)
+	if (conn_len > 1 &&
+	    wid_type != AC_WID_AUD_MIX &&
+	    wid_type != AC_WID_VOL_KNB &&
+	    wid_type != AC_WID_POWER)
 		curr = snd_hda_codec_read(codec, nid, 0,
 					  AC_VERB_GET_CONNECT_SEL, 0);
 	snd_iprintf(buffer, "  Connection: %d\n", conn_len);
@@ -467,8 +469,9 @@
 	snd_iprintf(buffer, "Codec: %s\n",
 		    codec->name ? codec->name : "Not Set");
 	snd_iprintf(buffer, "Address: %d\n", codec->addr);
-	snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
-	snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
+	snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id);
+	snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
+	snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
 	snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
 
 	if (codec->mfg)
@@ -554,8 +557,14 @@
 			snd_iprintf(buffer, "  Amp-Out caps: ");
 			print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
 			snd_iprintf(buffer, "  Amp-Out vals: ");
-			print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
-				       wid_caps & AC_WCAP_STEREO, 1);
+			if (wid_type == AC_WID_PIN &&
+			    codec->pin_amp_workaround)
+				print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
+					       wid_caps & AC_WCAP_STEREO,
+					       conn_len);
+			else
+				print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
+					       wid_caps & AC_WCAP_STEREO, 1);
 		}
 
 		switch (wid_type) {
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index e486123..5bb48ee 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -27,11 +27,12 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_beep.h"
 
 struct ad198x_spec {
 	struct snd_kcontrol_new *mixers[5];
 	int num_mixers;
-
+	unsigned int beep_amp;	/* beep amp value, set via set_beep_amp() */
 	const struct hda_verb *init_verbs[5];	/* initialization verbs
 						 * don't forget NULL termination!
 						 */
@@ -154,6 +155,16 @@
 
 static void ad198x_free_kctls(struct hda_codec *codec);
 
+/* additional beep mixers; the actual parameters are overwritten at build */
+static struct snd_kcontrol_new ad_beep_mixer[] = {
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+#define set_beep_amp(spec, nid, idx, dir) \
+	((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
+
 static int ad198x_build_controls(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec = codec->spec;
@@ -181,6 +192,21 @@
 			return err;
 	}
 
+	/* create beep controls if needed */
+	if (spec->beep_amp) {
+		struct snd_kcontrol_new *knew;
+		for (knew = ad_beep_mixer; knew->name; knew++) {
+			struct snd_kcontrol *kctl;
+			kctl = snd_ctl_new1(knew, codec);
+			if (!kctl)
+				return -ENOMEM;
+			kctl->private_value = spec->beep_amp;
+			err = snd_hda_ctl_add(codec, kctl);
+			if (err < 0)
+				return err;
+		}
+	}
+
 	/* if we have no master control, let's create it */
 	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
 		unsigned int vmaster_tlv[4];
@@ -406,7 +432,8 @@
 		return;
 
 	ad198x_free_kctls(codec);
-	kfree(codec->spec);
+	kfree(spec);
+	snd_hda_detach_beep_device(codec);
 }
 
 static struct hda_codec_ops ad198x_patch_ops = {
@@ -545,8 +572,6 @@
 	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),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
@@ -610,8 +635,7 @@
 	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),
-	/* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
-	   HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
+	/* 
 	   HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
 	   HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
 	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
@@ -809,8 +833,6 @@
 	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),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
 	{
@@ -1002,10 +1024,8 @@
 	SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
 	SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
-	SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_SAMSUNG),
-	SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_SAMSUNG),
-	SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_SAMSUNG),
 	SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
+	SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
 	SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
 	SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
 	SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
@@ -1027,15 +1047,14 @@
 
 static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
 {
-	unsigned int conf = snd_hda_codec_read(codec, nid, 0,
-					       AC_VERB_GET_CONFIG_DEFAULT, 0);
+	unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
 	return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
 }
 
 static int patch_ad1986a(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
-	int board_config;
+	int err, board_config;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -1043,6 +1062,13 @@
 
 	codec->spec = spec;
 
+	err = snd_hda_attach_beep_device(codec, 0x19);
+	if (err < 0) {
+		ad198x_free(codec);
+		return err;
+	}
+	set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
+
 	spec->multiout.max_channels = 6;
 	spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
 	spec->multiout.dac_nids = ad1986a_dac_nids;
@@ -1222,8 +1248,6 @@
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -1294,6 +1318,7 @@
 static int patch_ad1983(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
+	int err;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -1301,6 +1326,13 @@
 
 	codec->spec = spec;
 
+	err = snd_hda_attach_beep_device(codec, 0x10);
+	if (err < 0) {
+		ad198x_free(codec);
+		return err;
+	}
+	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
+
 	spec->multiout.max_channels = 2;
 	spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
 	spec->multiout.dac_nids = ad1983_dac_nids;
@@ -1370,8 +1402,6 @@
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
@@ -1416,8 +1446,8 @@
 	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
 	{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 	/* Mic boost: 0dB */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	/* Record selector: Front mic */
 	{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
@@ -1682,10 +1712,10 @@
 	SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
 	SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
 	/* All HP models */
-	SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
+	SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
 	SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
 	/* Lenovo Thinkpad T60/X60/Z6xx */
-	SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
 	/* HP nx6320 (reversed SSID, H/W bug) */
 	SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
 	{}
@@ -1694,7 +1724,7 @@
 static int patch_ad1981(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
-	int board_config;
+	int err, board_config;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -1702,6 +1732,13 @@
 
 	codec->spec = spec;
 
+	err = snd_hda_attach_beep_device(codec, 0x10);
+	if (err < 0) {
+		ad198x_free(codec);
+		return err;
+	}
+	set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
+
 	spec->multiout.max_channels = 2;
 	spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
 	spec->multiout.dac_nids = ad1981_dac_nids;
@@ -1988,9 +2025,6 @@
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
 
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
-
 	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
 
@@ -2034,9 +2068,6 @@
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
 
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
-
 	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
 
@@ -2066,9 +2097,6 @@
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
 	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
 
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
-
 	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
 
@@ -2297,10 +2325,6 @@
 	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
 	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
 	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* ADCs; muted */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 
 	{ }
 };
@@ -2408,10 +2432,6 @@
 	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
 	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
 	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* ADCs; muted */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	/* Analog Mix output amp */
 	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
 	{ }
@@ -2483,10 +2503,6 @@
 	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
 	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
 	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* ADCs; muted */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	/* Analog Mix output amp */
 	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
 	{ }
@@ -2890,7 +2906,7 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
 	if (spec->autocfg.dig_in_pin)
 		spec->dig_in_nid = AD1988_SPDIF_IN;
@@ -2940,7 +2956,7 @@
 static int patch_ad1988(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
-	int board_config;
+	int err, board_config;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -2960,7 +2976,7 @@
 
 	if (board_config == AD1988_AUTO) {
 		/* automatic parse from the BIOS config */
-		int err = ad1988_parse_auto_config(codec);
+		err = ad1988_parse_auto_config(codec);
 		if (err < 0) {
 			ad198x_free(codec);
 			return err;
@@ -2970,6 +2986,13 @@
 		}
 	}
 
+	err = snd_hda_attach_beep_device(codec, 0x10);
+	if (err < 0) {
+		ad198x_free(codec);
+		return err;
+	}
+	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
+
 	switch (board_config) {
 	case AD1988_6STACK:
 	case AD1988_6STACK_DIG:
@@ -3126,12 +3149,6 @@
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, 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("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
-	*/
 	HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
@@ -3204,10 +3221,10 @@
 	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
 	/* Port-B (front mic) pin */
 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	/* Port-C (rear mic) pin */
 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	/* 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)},
@@ -3240,7 +3257,7 @@
 	"CD Playback Volume",
 	"Internal Mic Playback Volume",
 	"Docking Mic Playback Volume"
-	"Beep Playback Volume",
+	/* "Beep Playback Volume", */
 	"IEC958 Playback Volume",
 	NULL
 };
@@ -3248,6 +3265,7 @@
 static int patch_ad1884(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
+	int err;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -3255,6 +3273,13 @@
 
 	codec->spec = spec;
 
+	err = snd_hda_attach_beep_device(codec, 0x10);
+	if (err < 0) {
+		ad198x_free(codec);
+		return err;
+	}
+	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
+
 	spec->multiout.max_channels = 2;
 	spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
 	spec->multiout.dac_nids = ad1884_dac_nids;
@@ -3321,8 +3346,6 @@
 	HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
 	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),
@@ -3358,7 +3381,7 @@
 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	/* docking mic boost */
-	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 	/* Analog mixer - docking mic; mute as default */
 	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 	/* enable EAPD bit */
@@ -3379,10 +3402,6 @@
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
 	HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
-	/*
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
-	*/
 	HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
@@ -3468,7 +3487,7 @@
 
 static struct snd_pci_quirk ad1984_cfg_tbl[] = {
 	/* Lenovo Thinkpad T61/X61 */
-	SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
 	SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
 	{}
 };
@@ -3561,8 +3580,6 @@
 	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),
@@ -3622,10 +3639,10 @@
 	{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},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	/* 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},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	/* Port-E (rear mic) pin */
 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
@@ -3695,8 +3712,6 @@
 	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),
@@ -3724,8 +3739,6 @@
 	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("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
@@ -3836,8 +3849,6 @@
 	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),
@@ -3911,9 +3922,9 @@
 	SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
 	SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
 	SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
-	SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP),
-	SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP),
-	SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP),
+	SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
+	SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
 	SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
 	{}
 };
@@ -3921,7 +3932,7 @@
 static int patch_ad1884a(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
-	int board_config;
+	int err, board_config;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -3929,6 +3940,13 @@
 
 	codec->spec = spec;
 
+	err = snd_hda_attach_beep_device(codec, 0x10);
+	if (err < 0) {
+		ad198x_free(codec);
+		return err;
+	}
+	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
+
 	spec->multiout.max_channels = 2;
 	spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
 	spec->multiout.dac_nids = ad1884a_dac_nids;
@@ -3966,6 +3984,14 @@
 		spec->multiout.dig_out_nid = 0;
 		codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
 		codec->patch_ops.init = ad1884a_hp_init;
+		/* set the upper-limit for mixer amp to 0dB for avoiding the
+		 * possible damage by overloading
+		 */
+		snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
+					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
+					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+					  (1 << AC_AMPCAP_MUTE_SHIFT));
 		break;
 	case AD1884A_THINKPAD:
 		spec->mixers[0] = ad1984a_thinkpad_mixers;
@@ -4083,8 +4109,6 @@
 	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -4097,8 +4121,6 @@
 	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT),
 	HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
 	{ } /* end */
 };
@@ -4257,7 +4279,7 @@
 static int patch_ad1882(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
-	int board_config;
+	int err, board_config;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -4265,6 +4287,13 @@
 
 	codec->spec = spec;
 
+	err = snd_hda_attach_beep_device(codec, 0x10);
+	if (err < 0) {
+		ad198x_free(codec);
+		return err;
+	}
+	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
+
 	spec->multiout.max_channels = 6;
 	spec->multiout.num_dacs = 3;
 	spec->multiout.dac_nids = ad1882_dac_nids;
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index f3ebe83..c921264 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -680,13 +680,13 @@
 		struct auto_pin_cfg cfg;
 
 		/* collect pin default configuration */
-		port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
-		port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+		port_e = snd_hda_codec_get_pincfg(codec, 0x0f);
+		port_f = snd_hda_codec_get_pincfg(codec, 0x10);
 		spec->front_panel = 1;
 		if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE ||
 		    get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) {
-			port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
-			port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+			port_g = snd_hda_codec_get_pincfg(codec, 0x1f);
+			port_h = snd_hda_codec_get_pincfg(codec, 0x20);
 			spec->channel_modes = cmi9880_channel_modes;
 			/* no front panel */
 			if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
@@ -703,8 +703,8 @@
 			spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
 		} else {
 			spec->input_mux = &cmi9880_basic_mux;
-			port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
-			port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+			port_spdifi = snd_hda_codec_get_pincfg(codec, 0x13);
+			port_spdifo = snd_hda_codec_get_pincfg(codec, 0x12);
 			if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE)
 				spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
 			if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE)
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 0177ef8..1f2ad76 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -58,6 +58,7 @@
 
 	struct snd_kcontrol_new *mixers[5];
 	int num_mixers;
+	hda_nid_t vmaster_nid;
 
 	const struct hda_verb *init_verbs[5];	/* initialization verbs
 						 * don't forget NULL
@@ -72,6 +73,7 @@
 					 */
 	unsigned int cur_eapd;
 	unsigned int hp_present;
+	unsigned int no_auto_mic;
 	unsigned int need_dac_fix;
 
 	/* capture */
@@ -461,6 +463,29 @@
 	kfree(codec->spec);
 }
 
+static struct snd_kcontrol_new cxt_capture_mixers[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = conexant_mux_enum_info,
+		.get = conexant_mux_enum_get,
+		.put = conexant_mux_enum_put
+	},
+	{}
+};
+
+static const char *slave_vols[] = {
+	"Headphone Playback Volume",
+	"Speaker Playback Volume",
+	NULL
+};
+
+static const char *slave_sws[] = {
+	"Headphone Playback Switch",
+	"Speaker Playback Switch",
+	NULL
+};
+
 static int conexant_build_controls(struct hda_codec *codec)
 {
 	struct conexant_spec *spec = codec->spec;
@@ -488,6 +513,32 @@
 		if (err < 0)
 			return err;
 	}
+
+	/* if we have no master control, let's create it */
+	if (spec->vmaster_nid &&
+	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+		unsigned int vmaster_tlv[4];
+		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
+					HDA_OUTPUT, vmaster_tlv);
+		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+					  vmaster_tlv, slave_vols);
+		if (err < 0)
+			return err;
+	}
+	if (spec->vmaster_nid &&
+	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
+		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
+					  NULL, slave_sws);
+		if (err < 0)
+			return err;
+	}
+
+	if (spec->input_mux) {
+		err = snd_hda_add_new_ctls(codec, cxt_capture_mixers);
+		if (err < 0)
+			return err;
+	}
+
 	return 0;
 }
 
@@ -719,13 +770,6 @@
 }
 
 static struct snd_kcontrol_new cxt5045_mixers[] = {
-	{
-		.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, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
 	HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
@@ -759,13 +803,6 @@
 };
 
 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),
@@ -1002,15 +1039,9 @@
 };
 
 static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x30a5, "HP", CXT5045_LAPTOP_HPSENSE),
-	SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP_HPSENSE),
-	SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP_HPSENSE),
-	SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP_HPSENSE),
-	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_HP530),
-	SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
+			   CXT5045_LAPTOP_HPSENSE),
 	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE),
 	SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
 	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
@@ -1020,8 +1051,8 @@
 	SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE),
 	SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE),
 	SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1631, 0xc106, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1631, 0xc107, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE),
+	SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell",
+			   CXT5045_LAPTOP_HPMICSENSE),
 	SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE),
 	{}
 };
@@ -1035,6 +1066,7 @@
 	if (!spec)
 		return -ENOMEM;
 	codec->spec = spec;
+	codec->pin_amp_workaround = 1;
 
 	spec->multiout.max_channels = 2;
 	spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids);
@@ -1134,7 +1166,7 @@
 /* Conexant 5047 specific */
 #define CXT5047_SPDIF_OUT	0x11
 
-static hda_nid_t cxt5047_dac_nids[2] = { 0x10, 0x1c };
+static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */
 static hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
 static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
 
@@ -1142,20 +1174,6 @@
 	{ 2, NULL },
 };
 
-static struct hda_input_mux cxt5047_capture_source = {
-	.num_items = 1,
-	.items = {
-		{ "Mic", 0x2 },
-	}
-};
-
-static struct hda_input_mux cxt5047_hp_capture_source = {
-	.num_items = 1,
-	.items = {
-		{ "ExtMic", 0x2 },
-	}
-};
-
 static struct hda_input_mux cxt5047_toshiba_capture_source = {
 	.num_items = 2,
 	.items = {
@@ -1179,7 +1197,11 @@
 	 * the headphone jack
 	 */
 	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
-	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0,
+	/* NOTE: Conexat codec needs the index for *OUTPUT* amp of
+	 * pin widgets unlike other codecs.  In this case, we need to
+	 * set index 0x01 for the volume from the mixer amp 0x19.
+	 */
+	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
 				 HDA_AMP_MUTE, bits);
 	bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
 	snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
@@ -1187,16 +1209,6 @@
 	return 1;
 }
 
-/* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */
-static struct hda_bind_ctls cxt5047_bind_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
-
 /* mute internal speaker if HP is plugged */
 static void cxt5047_hp_automute(struct hda_codec *codec)
 {
@@ -1207,27 +1219,8 @@
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
 
 	bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	/* Mute/Unmute PCM 2 for good measure - some systems need this */
-	snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-}
-
-/* mute internal speaker if HP is plugged */
-static void cxt5047_hp2_automute(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int bits;
-
-	spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
-				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-
-	bits = spec->hp_present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	/* Mute/Unmute PCM 2 for good measure - some systems need this */
-	snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0,
+	/* See the note in cxt5047_hp_master_sw_put */
+	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
 				 HDA_AMP_MUTE, bits);
 }
 
@@ -1268,90 +1261,35 @@
 	}
 }
 
-/* unsolicited event for HP jack sensing - non-EAPD systems */
-static void cxt5047_hp2_unsol_event(struct hda_codec *codec,
-				  unsigned int res)
-{
-	res >>= 26;
-	switch (res) {
-	case CONEXANT_HP_EVENT:
-		cxt5047_hp2_automute(codec);
-		break;
-	case CONEXANT_MIC_EVENT:
-		cxt5047_hp_automic(codec);
-		break;
-	}
-}
-
-static struct snd_kcontrol_new cxt5047_mixers[] = {
-	HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT),
+static struct snd_kcontrol_new cxt5047_base_mixers[] = {
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x1a, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
 	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
 	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = cxt_eapd_info,
+		.get = cxt_eapd_get,
+		.put = cxt5047_hp_master_sw_put,
+		.private_value = 0x13,
+	},
+
+	{}
+};
+
+static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = {
+	/* See the note in cxt5047_hp_master_sw_put */
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x13, 0x00, HDA_OUTPUT),
-
 	{}
 };
 
-static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = {
-	{
-		.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("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
-	HDA_BIND_VOL("Master Playback Volume", &cxt5047_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5047_hp_master_sw_put,
-		.private_value = 0x13,
-	},
-
-	{}
-};
-
-static struct snd_kcontrol_new cxt5047_hp_mixers[] = {
-	{
-		.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("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19,0x02,HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
+static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = {
 	HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5047_hp_master_sw_put,
-		.private_value = 0x13,
-	},
 	{ } /* end */
 };
 
@@ -1362,8 +1300,8 @@
 	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
 	/* HP, Speaker  */
 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{0x13, AC_VERB_SET_CONNECT_SEL,0x1},
-	{0x1d, AC_VERB_SET_CONNECT_SEL,0x0},
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */
+	{0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */
 	/* Record selector: Mic */
 	{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
@@ -1383,30 +1321,7 @@
 
 /* configuration for Toshiba Laptops */
 static struct hda_verb cxt5047_toshiba_init_verbs[] = {
-	{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0 }, /* default on */
-	/* pin sensing on HP and Mic jacks */
-	{0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	/* Speaker routing */
-	{0x1d, AC_VERB_SET_CONNECT_SEL,0x1},
-	{}
-};
-
-/* configuration for HP Laptops */
-static struct hda_verb cxt5047_hp_init_verbs[] = {
-	/* pin sensing on HP jack */
-	{0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	/* 0x13 is actually shared by both HP and speaker;
-	 * setting the connection to 0 (=0x19) makes the master volume control
-	 * working mysteriouslly...
-	 */
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Record selector: Ext Mic */
-	{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
-	/* Speaker routing */
-	{0x1d, AC_VERB_SET_CONNECT_SEL,0x1},
+	{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */
 	{}
 };
 
@@ -1571,11 +1486,9 @@
 };
 
 static struct snd_pci_quirk cxt5047_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x30a0, "HP DV1000", CXT5047_LAPTOP),
 	SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
-	SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV2000T/DV3000T", CXT5047_LAPTOP),
-	SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2000Z", CXT5047_LAPTOP),
-	SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6700", CXT5047_LAPTOP),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
+			   CXT5047_LAPTOP),
 	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
 	{}
 };
@@ -1589,6 +1502,7 @@
 	if (!spec)
 		return -ENOMEM;
 	codec->spec = spec;
+	codec->pin_amp_workaround = 1;
 
 	spec->multiout.max_channels = 2;
 	spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids);
@@ -1597,9 +1511,8 @@
 	spec->num_adc_nids = 1;
 	spec->adc_nids = cxt5047_adc_nids;
 	spec->capsrc_nids = cxt5047_capsrc_nids;
-	spec->input_mux = &cxt5047_capture_source;
 	spec->num_mixers = 1;
-	spec->mixers[0] = cxt5047_mixers;
+	spec->mixers[0] = cxt5047_base_mixers;
 	spec->num_init_verbs = 1;
 	spec->init_verbs[0] = cxt5047_init_verbs;
 	spec->spdif_route = 0;
@@ -1613,21 +1526,22 @@
 						  cxt5047_cfg_tbl);
 	switch (board_config) {
 	case CXT5047_LAPTOP:
-		codec->patch_ops.unsol_event = cxt5047_hp2_unsol_event;
+		spec->num_mixers = 2;
+		spec->mixers[1] = cxt5047_hp_spk_mixers;
+		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
 		break;
 	case CXT5047_LAPTOP_HP:
-		spec->input_mux = &cxt5047_hp_capture_source;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = cxt5047_hp_init_verbs;
-		spec->mixers[0] = cxt5047_hp_mixers;
+		spec->num_mixers = 2;
+		spec->mixers[1] = cxt5047_hp_only_mixers;
 		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
 		codec->patch_ops.init = cxt5047_hp_init;
 		break;
 	case CXT5047_LAPTOP_EAPD:
 		spec->input_mux = &cxt5047_toshiba_capture_source;
+		spec->num_mixers = 2;
+		spec->mixers[1] = cxt5047_hp_spk_mixers;
 		spec->num_init_verbs = 2;
 		spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
-		spec->mixers[0] = cxt5047_toshiba_mixers;
 		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
 		break;
 #ifdef CONFIG_SND_DEBUG
@@ -1638,6 +1552,7 @@
 		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
 #endif	
 	}
+	spec->vmaster_nid = 0x13;
 	return 0;
 }
 
@@ -1673,8 +1588,11 @@
 /* toggle input of built-in and mic jack appropriately */
 static void cxt5051_portb_automic(struct hda_codec *codec)
 {
+	struct conexant_spec *spec = codec->spec;
 	unsigned int present;
 
+	if (spec->no_auto_mic)
+		return;
 	present = snd_hda_codec_read(codec, 0x17, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) &
 		AC_PINSENSE_PRESENCE;
@@ -1690,6 +1608,8 @@
 	unsigned int present;
 	hda_nid_t new_adc;
 
+	if (spec->no_auto_mic)
+		return;
 	present = snd_hda_codec_read(codec, 0x18, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) &
 		AC_PINSENSE_PRESENCE;
@@ -1776,6 +1696,22 @@
 	{}
 };
 
+static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
+	HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = cxt_eapd_info,
+		.get = cxt_eapd_get,
+		.put = cxt5051_hp_master_sw_put,
+		.private_value = 0x1a,
+	},
+
+	{}
+};
+
 static struct hda_verb cxt5051_init_verbs[] = {
 	/* Line in, Mic */
 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
@@ -1806,6 +1742,66 @@
 	{ } /* end */
 };
 
+static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
+	/* Line in, Mic */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
+	/* SPK  */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* HP, Amp  */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* DAC1 */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Record selector: Int mic */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
+	/* SPDIF route: PCM */
+	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
+	/* EAPD */
+	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
+	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
+	{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
+	{ } /* end */
+};
+
+static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
+	/* Line in, Mic */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
+	/* SPK  */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* HP, Amp  */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Docking HP */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* DAC1 */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Record selector: Int mic */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
+	/* SPDIF route: PCM */
+	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
+	/* EAPD */
+	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
+	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
+	{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT},
+	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
+	{ } /* end */
+};
+
 /* initialize jack-sensing, too */
 static int cxt5051_init(struct hda_codec *codec)
 {
@@ -1823,18 +1819,24 @@
 enum {
 	CXT5051_LAPTOP,	 /* Laptops w/ EAPD support */
 	CXT5051_HP,	/* no docking */
+	CXT5051_HP_DV6736,	/* HP without mic switch */
+	CXT5051_LENOVO_X200,	/* Lenovo X200 laptop */
 	CXT5051_MODELS
 };
 
 static const char *cxt5051_models[CXT5051_MODELS] = {
 	[CXT5051_LAPTOP]	= "laptop",
 	[CXT5051_HP]		= "hp",
+	[CXT5051_HP_DV6736]	= "hp-dv6736",
+	[CXT5051_LENOVO_X200]	= "lenovo-x200",
 };
 
 static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
 	SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
 		      CXT5051_LAPTOP),
 	SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
+	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
 	{}
 };
 
@@ -1847,6 +1849,7 @@
 	if (!spec)
 		return -ENOMEM;
 	codec->spec = spec;
+	codec->pin_amp_workaround = 1;
 
 	codec->patch_ops = conexant_patch_ops;
 	codec->patch_ops.init = cxt5051_init;
@@ -1867,17 +1870,22 @@
 	spec->cur_adc = 0;
 	spec->cur_adc_idx = 0;
 
+	codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
+
 	board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
 						  cxt5051_models,
 						  cxt5051_cfg_tbl);
 	switch (board_config) {
 	case CXT5051_HP:
-		codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
 		spec->mixers[0] = cxt5051_hp_mixers;
 		break;
-	default:
-	case CXT5051_LAPTOP:
-		codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
+	case CXT5051_HP_DV6736:
+		spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
+		spec->mixers[0] = cxt5051_hp_dv6736_mixers;
+		spec->no_auto_mic = 1;
+		break;
+	case CXT5051_LENOVO_X200:
+		spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
 		break;
 	}
 
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6c26afc..8209779 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_beep.h"
 
 #define ALC880_FRONT_EVENT		0x01
 #define ALC880_DCVOL_EVENT		0x02
@@ -77,6 +78,7 @@
 	ALC260_ACER,
 	ALC260_WILL,
 	ALC260_REPLACER_672V,
+	ALC260_FAVORIT100,
 #ifdef CONFIG_SND_DEBUG
 	ALC260_TEST,
 #endif
@@ -103,6 +105,7 @@
 	ALC262_NEC,
 	ALC262_TOSHIBA_S06,
 	ALC262_TOSHIBA_RX1,
+	ALC262_TYAN,
 	ALC262_AUTO,
 	ALC262_MODEL_LAST /* last tag */
 };
@@ -238,6 +241,13 @@
 	ALC883_MODEL_LAST,
 };
 
+/* styles of capture selection */
+enum {
+	CAPT_MUX = 0,	/* only mux based */
+	CAPT_MIX,	/* only mixer based */
+	CAPT_1MUX_MIX,	/* first mux and other mixers */
+};
+
 /* for GPIO Poll */
 #define GPIO_MASK	0x03
 
@@ -246,6 +256,7 @@
 	struct snd_kcontrol_new *mixers[5];	/* mixer arrays */
 	unsigned int num_mixers;
 	struct snd_kcontrol_new *cap_mixer;	/* capture mixer */
+	unsigned int beep_amp;	/* beep amp value, set via set_beep_amp() */
 
 	const struct hda_verb *init_verbs[5];	/* initialization verbs
 						 * don't forget NULL
@@ -269,13 +280,15 @@
 					 * dig_out_nid and hp_nid are optional
 					 */
 	hda_nid_t alt_dac_nid;
+	hda_nid_t slave_dig_outs[3];	/* optional - for auto-parsing */
+	int dig_out_type;
 
 	/* 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 */
-	unsigned char is_mix_capture;	/* matrix-style capture (non-mux) */
+	int capture_style;		/* capture style (CAPT_*) */
 
 	/* capture source */
 	unsigned int num_mux_defs;
@@ -293,7 +306,7 @@
 	/* dynamic controls, init_verbs and input_mux */
 	struct auto_pin_cfg autocfg;
 	struct snd_array kctls;
-	struct hda_input_mux private_imux;
+	struct hda_input_mux private_imux[3];
 	hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
 
 	/* hooks */
@@ -305,6 +318,9 @@
 	unsigned int jack_present: 1;
 	unsigned int master_sw: 1;
 
+	/* other flags */
+	unsigned int no_analog :1; /* digital I/O only */
+
 	/* for virtual master */
 	hda_nid_t vmaster_nid;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -314,13 +330,6 @@
 	/* for PLL fix */
 	hda_nid_t pll_nid;
 	unsigned int pll_coef_idx, pll_coef_bit;
-
-#ifdef SND_HDA_NEEDS_RESUME
-#define ALC_MAX_PINS	16
-	unsigned int num_pins;
-	hda_nid_t pin_nids[ALC_MAX_PINS];
-	unsigned int pin_cfgs[ALC_MAX_PINS];
-#endif
 };
 
 /*
@@ -336,6 +345,7 @@
 	hda_nid_t *dac_nids;
 	hda_nid_t dig_out_nid;		/* optional */
 	hda_nid_t hp_nid;		/* optional */
+	hda_nid_t *slave_dig_outs;
 	unsigned int num_adc_nids;
 	hda_nid_t *adc_nids;
 	hda_nid_t *capsrc_nids;
@@ -392,7 +402,8 @@
 	mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
 	imux = &spec->input_mux[mux_idx];
 
-	if (spec->is_mix_capture) {
+	if (spec->capture_style &&
+	    !(spec->capture_style == CAPT_1MUX_MIX && !adc_idx)) {
 		/* Matrix-mixer style (e.g. ALC882) */
 		unsigned int *cur_val = &spec->cur_mux[adc_idx];
 		unsigned int i, idx;
@@ -750,6 +761,24 @@
 #endif   /* CONFIG_SND_DEBUG */
 
 /*
+ * set up the input pin config (depending on the given auto-pin type)
+ */
+static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
+			      int auto_pin_type)
+{
+	unsigned int val = PIN_IN;
+
+	if (auto_pin_type <= AUTO_PIN_FRONT_MIC) {
+		unsigned int pincap;
+		pincap = snd_hda_query_pin_caps(codec, nid);
+		pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
+		if (pincap & AC_PINCAP_VREF_80)
+			val = PIN_VREF80;
+	}
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+}
+
+/*
  */
 static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix)
 {
@@ -810,6 +839,7 @@
 	spec->multiout.num_dacs = preset->num_dacs;
 	spec->multiout.dac_nids = preset->dac_nids;
 	spec->multiout.dig_out_nid = preset->dig_out_nid;
+	spec->multiout.slave_dig_outs = preset->slave_dig_outs;
 	spec->multiout.hp_nid = preset->hp_nid;
 
 	spec->num_mux_defs = preset->num_mux_defs;
@@ -921,7 +951,7 @@
 			 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
 }
 #else
-#define alc_mic_automute(codec) /* NOP */
+#define alc_mic_automute(codec) do {} while(0) /* NOP */
 #endif /* disabled */
 
 /* unsolicited event for HP jack sensing */
@@ -952,7 +982,7 @@
 	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
 	tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
 	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
-	if ((tmp & 0xf0) == 2)
+	if ((tmp & 0xf0) == 0x20)
 		/* alc888S-VC */
 		snd_hda_codec_read(codec, 0x20, 0,
 				   AC_VERB_SET_PROC_COEF, 0x830);
@@ -991,8 +1021,7 @@
 	nid = 0x1d;
 	if (codec->vendor_id == 0x10ec0260)
 		nid = 0x17;
-	ass = snd_hda_codec_read(codec, nid, 0,
-				 AC_VERB_GET_CONFIG_DEFAULT, 0);
+	ass = snd_hda_codec_get_pincfg(codec, nid);
 	if (!(ass & 1) && !(ass & 0x100000))
 		return;
 	if ((ass >> 30) != 1)	/* no physical connection */
@@ -1166,16 +1195,8 @@
 		return;
 
 	cfg = pinfix[quirk->value];
-	for (; cfg->nid; cfg++) {
-		int i;
-		u32 val = cfg->val;
-		for (i = 0; i < 4; i++) {
-			snd_hda_codec_write(codec, cfg->nid, 0,
-				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
-				    val & 0xff);
-			val >>= 8;
-		}
-	}
+	for (; cfg->nid; cfg++)
+		snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
 }
 
 /*
@@ -1375,8 +1396,6 @@
 	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("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -1483,8 +1502,6 @@
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1578,8 +1595,7 @@
 				     snd_hda_mixer_amp_switch_put);
 }
 
-#define DEFINE_CAPMIX(num) \
-static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
+#define _DEFINE_CAPMIX(num) \
 	{ \
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 		.name = "Capture Switch", \
@@ -1600,7 +1616,9 @@
 		.get = alc_cap_vol_get, \
 		.put = alc_cap_vol_put, \
 		.tlv = { .c = alc_cap_vol_tlv }, \
-	}, \
+	}
+
+#define _DEFINE_CAPSRC(num) \
 	{ \
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 		/* .name = "Capture Source", */ \
@@ -1609,15 +1627,28 @@
 		.info = alc_mux_enum_info, \
 		.get = alc_mux_enum_get, \
 		.put = alc_mux_enum_put, \
-	}, \
-	{ } /* end */ \
+	}
+
+#define DEFINE_CAPMIX(num) \
+static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
+	_DEFINE_CAPMIX(num),				      \
+	_DEFINE_CAPSRC(num),				      \
+	{ } /* end */					      \
+}
+
+#define DEFINE_CAPMIX_NOSRC(num) \
+static struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
+	_DEFINE_CAPMIX(num),					    \
+	{ } /* end */						    \
 }
 
 /* up to three ADCs */
 DEFINE_CAPMIX(1);
 DEFINE_CAPMIX(2);
 DEFINE_CAPMIX(3);
-
+DEFINE_CAPMIX_NOSRC(1);
+DEFINE_CAPMIX_NOSRC(2);
+DEFINE_CAPMIX_NOSRC(3);
 
 /*
  * ALC880 5-stack model
@@ -1706,8 +1737,6 @@
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Channel Mode",
@@ -1884,13 +1913,6 @@
 	{ } /* end */
 };
 
-/* additional mixers to alc880_asus_mixer */
-static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-	{ } /* end */
-};
-
 /* TCL S700 */
 static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
@@ -1923,8 +1945,6 @@
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Channel Mode",
@@ -1999,6 +2019,13 @@
 
 static void alc_free_kctls(struct hda_codec *codec);
 
+/* additional beep mixers; the actual parameters are overwritten at build */
+static struct snd_kcontrol_new alc_beep_mixer[] = {
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_INPUT),
+	{ } /* end */
+};
+
 static int alc_build_controls(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -2020,11 +2047,13 @@
 						    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->no_analog) {
+			err = snd_hda_create_spdif_share_sw(codec,
+							    &spec->multiout);
+			if (err < 0)
+				return err;
+			spec->multiout.share_spdif = 1;
+		}
 	}
 	if (spec->dig_in_nid) {
 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -2032,8 +2061,24 @@
 			return err;
 	}
 
+	/* create beep controls if needed */
+	if (spec->beep_amp) {
+		struct snd_kcontrol_new *knew;
+		for (knew = alc_beep_mixer; knew->name; knew++) {
+			struct snd_kcontrol *kctl;
+			kctl = snd_ctl_new1(knew, codec);
+			if (!kctl)
+				return -ENOMEM;
+			kctl->private_value = spec->beep_amp;
+			err = snd_hda_ctl_add(codec, kctl);
+			if (err < 0)
+				return err;
+		}
+	}
+
 	/* if we have no master control, let's create it */
-	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+	if (!spec->no_analog &&
+	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
 		unsigned int vmaster_tlv[4];
 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
 					HDA_OUTPUT, vmaster_tlv);
@@ -2042,7 +2087,8 @@
 		if (err < 0)
 			return err;
 	}
-	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
+	if (!spec->no_analog &&
+	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
 		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
 					  NULL, alc_slave_sws);
 		if (err < 0)
@@ -2951,6 +2997,14 @@
 					     stream_tag, format, substream);
 }
 
+static int alc880_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
+}
+
 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 					 struct hda_codec *codec,
 					 struct snd_pcm_substream *substream)
@@ -3034,7 +3088,8 @@
 	.ops = {
 		.open = alc880_dig_playback_pcm_open,
 		.close = alc880_dig_playback_pcm_close,
-		.prepare = alc880_dig_playback_pcm_prepare
+		.prepare = alc880_dig_playback_pcm_prepare,
+		.cleanup = alc880_dig_playback_pcm_cleanup
 	},
 };
 
@@ -3061,6 +3116,9 @@
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
 
+	if (spec->no_analog)
+		goto skip_analog;
+
 	info->name = spec->stream_name_analog;
 	if (spec->stream_analog_playback) {
 		if (snd_BUG_ON(!spec->multiout.dac_nids))
@@ -3084,12 +3142,17 @@
 		}
 	}
 
+ skip_analog:
 	/* SPDIF for stream index #1 */
 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
 		codec->num_pcms = 2;
+	        codec->slave_dig_outs = spec->multiout.slave_dig_outs;
 		info = spec->pcm_rec + 1;
 		info->name = spec->stream_name_digital;
-		info->pcm_type = HDA_PCM_TYPE_SPDIF;
+		if (spec->dig_out_type)
+			info->pcm_type = spec->dig_out_type;
+		else
+			info->pcm_type = HDA_PCM_TYPE_SPDIF;
 		if (spec->multiout.dig_out_nid &&
 		    spec->stream_digital_playback) {
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
@@ -3104,6 +3167,9 @@
 		codec->spdif_status_reset = 1;
 	}
 
+	if (spec->no_analog)
+		return 0;
+
 	/* If the use of more than one ADC is requested for the current
 	 * model, configure a second analog capture-only PCM.
 	 */
@@ -3162,65 +3228,17 @@
 
 	alc_free_kctls(codec);
 	kfree(spec);
-	codec->spec = NULL; /* to be sure */
+	snd_hda_detach_beep_device(codec);
 }
 
 #ifdef SND_HDA_NEEDS_RESUME
-static void store_pin_configs(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t nid, end_nid;
-
-	end_nid = codec->start_nid + codec->num_nodes;
-	for (nid = codec->start_nid; nid < end_nid; nid++) {
-		unsigned int wid_caps = get_wcaps(codec, nid);
-		unsigned int wid_type =
-			(wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-		if (wid_type != AC_WID_PIN)
-			continue;
-		if (spec->num_pins >= ARRAY_SIZE(spec->pin_nids))
-			break;
-		spec->pin_nids[spec->num_pins] = nid;
-		spec->pin_cfgs[spec->num_pins] =
-			snd_hda_codec_read(codec, nid, 0,
-					   AC_VERB_GET_CONFIG_DEFAULT, 0);
-		spec->num_pins++;
-	}
-}
-
-static void resume_pin_configs(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < spec->num_pins; i++) {
-		hda_nid_t pin_nid = spec->pin_nids[i];
-		unsigned int pin_config = spec->pin_cfgs[i];
-		snd_hda_codec_write(codec, pin_nid, 0,
-				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
-				    pin_config & 0x000000ff);
-		snd_hda_codec_write(codec, pin_nid, 0,
-				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
-				    (pin_config & 0x0000ff00) >> 8);
-		snd_hda_codec_write(codec, pin_nid, 0,
-				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
-				    (pin_config & 0x00ff0000) >> 16);
-		snd_hda_codec_write(codec, pin_nid, 0,
-				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
-				    pin_config >> 24);
-	}
-}
-
 static int alc_resume(struct hda_codec *codec)
 {
-	resume_pin_configs(codec);
 	codec->patch_ops.init(codec);
 	snd_hda_codec_resume_amp(codec);
 	snd_hda_codec_resume_cache(codec);
 	return 0;
 }
-#else
-#define store_pin_configs(codec)
 #endif
 
 /*
@@ -3559,7 +3577,7 @@
 	SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
 	SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
 	SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
-	SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS), /* default ASUS */
+	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
 	SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
 	SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
 	SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
@@ -3602,7 +3620,8 @@
 	SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
 	SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
 	SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST), /* default Intel */
+	/* default Intel */
+	SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
 	SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
 	SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
 	{}
@@ -3782,7 +3801,7 @@
 		.input_mux = &alc880_capture_source,
 	},
 	[ALC880_UNIWILL_DIG] = {
-		.mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
+		.mixers = { alc880_asus_mixer },
 		.init_verbs = { alc880_volume_init_verbs,
 				alc880_pin_asus_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
@@ -3820,8 +3839,7 @@
 		.init_hook = alc880_uniwill_p53_hp_automute,
 	},
 	[ALC880_FUJITSU] = {
-		.mixers = { alc880_fujitsu_mixer,
-			    alc880_pcbeep_mixer, },
+		.mixers = { alc880_fujitsu_mixer },
 		.init_verbs = { alc880_volume_init_verbs,
 				alc880_uniwill_p53_init_verbs,
 	       			alc880_beep_init_verbs },
@@ -4114,7 +4132,7 @@
 static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
 						const struct auto_pin_cfg *cfg)
 {
-	struct hda_input_mux *imux = &spec->private_imux;
+	struct hda_input_mux *imux = &spec->private_imux[0];
 	int i, err, idx;
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
@@ -4202,11 +4220,9 @@
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
 		if (alc880_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 != ALC880_PIN_CD_NID)
+			alc_set_input_pin(codec, nid, i);
+			if (nid != ALC880_PIN_CD_NID &&
+			    (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
 				snd_hda_codec_write(codec, nid, 0,
 						    AC_VERB_SET_AMP_GAIN_MUTE,
 						    AMP_OUT_MUTE);
@@ -4221,7 +4237,7 @@
 static int alc880_parse_auto_config(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	int err;
+	int i, err;
 	static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
 
 	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
@@ -4252,8 +4268,23 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
-		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+	/* check multiple SPDIF-out (for recent codecs) */
+	for (i = 0; i < spec->autocfg.dig_outs; i++) {
+		hda_nid_t dig_nid;
+		err = snd_hda_get_connections(codec,
+					      spec->autocfg.dig_out_pins[i],
+					      &dig_nid, 1);
+		if (err < 0)
+			continue;
+		if (!i)
+			spec->multiout.dig_out_nid = dig_nid;
+		else {
+			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
+			spec->slave_dig_outs[i - 1] = dig_nid;
+			if (i == ARRAY_SIZE(spec->slave_dig_outs) - 1)
+				break;
+		}
+	}
 	if (spec->autocfg.dig_in_pin)
 		spec->dig_in_nid = ALC880_DIGIN_NID;
 
@@ -4263,9 +4294,8 @@
 	add_verb(spec, alc880_volume_init_verbs);
 
 	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux;
+	spec->input_mux = &spec->private_imux[0];
 
-	store_pin_configs(codec);
 	return 1;
 }
 
@@ -4280,21 +4310,33 @@
 		alc_inithook(codec);
 }
 
+static void set_capture_mixer(struct alc_spec *spec)
+{
+	static struct snd_kcontrol_new *caps[2][3] = {
+		{ alc_capture_mixer_nosrc1,
+		  alc_capture_mixer_nosrc2,
+		  alc_capture_mixer_nosrc3 },
+		{ alc_capture_mixer1,
+		  alc_capture_mixer2,
+		  alc_capture_mixer3 },
+	};
+	if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
+		int mux;
+		if (spec->input_mux && spec->input_mux->num_items > 1)
+			mux = 1;
+		else
+			mux = 0;
+		spec->cap_mixer = caps[mux][spec->num_adc_nids - 1];
+	}
+}
+
+#define set_beep_amp(spec, nid, idx, dir) \
+	((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
+
 /*
  * OK, here we have finally the patch for ALC880
  */
 
-static void set_capture_mixer(struct alc_spec *spec)
-{
-	static struct snd_kcontrol_new *caps[3] = {
-		alc_capture_mixer1,
-		alc_capture_mixer2,
-		alc_capture_mixer3,
-	};
-	if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3)
-		spec->cap_mixer = caps[spec->num_adc_nids - 1];
-}
-
 static int patch_alc880(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
@@ -4330,6 +4372,12 @@
 		}
 	}
 
+	err = snd_hda_attach_beep_device(codec, 0x1);
+	if (err < 0) {
+		alc_free(codec);
+		return err;
+	}
+
 	if (board_config != ALC880_AUTO)
 		setup_preset(spec, &alc880_presets[board_config]);
 
@@ -4356,6 +4404,7 @@
 		}
 	}
 	set_capture_mixer(spec);
+	set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
 	spec->vmaster_nid = 0x0c;
 
@@ -4463,6 +4512,26 @@
 		},
 	},
 };
+
+/* Maxdata Favorit 100XS */
+static struct hda_input_mux alc260_favorit100_capture_sources[2] = {
+	{
+		.num_items = 2,
+		.items = {
+			{ "Line/Mic", 0x0 },
+			{ "CD", 0x4 },
+		},
+	},
+	{
+		.num_items = 3,
+		.items = {
+			{ "Line/Mic", 0x0 },
+			{ "CD", 0x4 },
+			{ "Mixer", 0x5 },
+		},
+	},
+};
+
 /*
  * This is just place-holder, so there's something for alc_build_pcms to look
  * at when it calculates the maximum number of channels. ALC260 has no mixer
@@ -4505,12 +4574,6 @@
 	{ } /* end */
 };
 
-static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
-	{ } /* end */
-};
-
 /* update HP, line and mono out pins according to the master switch */
 static void alc260_hp_master_update(struct hda_codec *codec,
 				    hda_nid_t hp, hda_nid_t line,
@@ -4702,8 +4765,6 @@
 	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
 	ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
 	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
 	{ } /* end */
@@ -4748,8 +4809,18 @@
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
 	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
 	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
+	{ } /* end */
+};
+
+/* Maxdata Favorit 100XS: one output and one input (0x12) jack
+ */
+static struct snd_kcontrol_new alc260_favorit100_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
+	ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
+	HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
 	{ } /* end */
 };
 
@@ -4767,8 +4838,6 @@
 	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -5126,6 +5195,89 @@
 	{ }
 };
 
+/* Initialisation sequence for Maxdata Favorit 100XS
+ * (adapted from Acer init verbs).
+ */
+static struct hda_verb alc260_favorit100_init_verbs[] = {
+	/* GPIO 0 enables the output jack.
+	 * Turn this on and rely on the standard mute
+	 * methods whenever the user wants to turn these outputs off.
+	 */
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+	/* Line/Mic input jack is connected to Mic1 pin */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+	/* Ensure all other unused pins are disabled and muted. */
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	/* Disable digital (SPDIF) pins */
+	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
+	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
+
+	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
+	 * bus when acting as outputs.
+	 */
+	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
+
+	/* Start with output sum widgets muted and their output gains at min */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* Unmute Line-out pin widget amp left and right
+	 * (no equiv mixer ctrl)
+	 */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
+	 * inputs. If the pin mode is changed by the user the pin mode control
+	 * will take care of enabling the pin's input/output buffers as needed.
+	 * Therefore there's no need to enable the input buffer at this
+	 * stage.
+	 */
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Mute capture amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	/* Set ADC connection select to match default mixer setting - mic
+	 * (on mic1 pin)
+	 */
+	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Do similar with the second ADC: mute capture input amp and
+	 * set ADC connection to mic to match ALSA's default state.
+	 */
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Mute all inputs to mixer widget (even unconnected ones) */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
+
+	{ }
+};
+
 static struct hda_verb alc260_will_verbs[] = {
 	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -5272,8 +5424,6 @@
 	HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
 	HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
 	HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
 	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
@@ -5471,7 +5621,7 @@
 static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
 						const struct auto_pin_cfg *cfg)
 {
-	struct hda_input_mux *imux = &spec->private_imux;
+	struct hda_input_mux *imux = &spec->private_imux[0];
 	int i, err, idx;
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
@@ -5546,11 +5696,9 @@
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
 		if (nid >= 0x12) {
-			snd_hda_codec_write(codec, nid, 0,
-					    AC_VERB_SET_PIN_WIDGET_CONTROL,
-					    i <= AUTO_PIN_FRONT_MIC ?
-					    PIN_VREF80 : PIN_IN);
-			if (nid != ALC260_PIN_CD_NID)
+			alc_set_input_pin(codec, nid, i);
+			if (nid != ALC260_PIN_CD_NID &&
+			    (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
 				snd_hda_codec_write(codec, nid, 0,
 						    AC_VERB_SET_AMP_GAIN_MUTE,
 						    AMP_OUT_MUTE);
@@ -5623,7 +5771,7 @@
 
 	spec->multiout.max_channels = 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
 	if (spec->kctls.list)
 		add_mixer(spec, spec->kctls.list);
@@ -5631,9 +5779,8 @@
 	add_verb(spec, alc260_volume_init_verbs);
 
 	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux;
+	spec->input_mux = &spec->private_imux[0];
 
-	store_pin_configs(codec);
 	return 1;
 }
 
@@ -5670,6 +5817,7 @@
 	[ALC260_ACER]		= "acer",
 	[ALC260_WILL]		= "will",
 	[ALC260_REPLACER_672V]	= "replacer",
+	[ALC260_FAVORIT100]	= "favorit100",
 #ifdef CONFIG_SND_DEBUG
 	[ALC260_TEST]		= "test",
 #endif
@@ -5679,6 +5827,7 @@
 static struct snd_pci_quirk alc260_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
 	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
+	SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
 	SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
 	SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013),
 	SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
@@ -5701,8 +5850,7 @@
 static struct alc_config_preset alc260_presets[] = {
 	[ALC260_BASIC] = {
 		.mixers = { alc260_base_output_mixer,
-			    alc260_input_mixer,
-			    alc260_pc_beep_mixer },
+			    alc260_input_mixer },
 		.init_verbs = { alc260_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
 		.dac_nids = alc260_dac_nids,
@@ -5781,6 +5929,18 @@
 		.num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
 		.input_mux = alc260_acer_capture_sources,
 	},
+	[ALC260_FAVORIT100] = {
+		.mixers = { alc260_favorit100_mixer },
+		.init_verbs = { alc260_favorit100_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
+		.adc_nids = alc260_dual_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
+		.input_mux = alc260_favorit100_capture_sources,
+	},
 	[ALC260_WILL] = {
 		.mixers = { alc260_will_mixer },
 		.init_verbs = { alc260_init_verbs, alc260_will_verbs },
@@ -5857,6 +6017,12 @@
 		}
 	}
 
+	err = snd_hda_attach_beep_device(codec, 0x1);
+	if (err < 0) {
+		alc_free(codec);
+		return err;
+	}
+
 	if (board_config != ALC260_AUTO)
 		setup_preset(spec, &alc260_presets[board_config]);
 
@@ -5882,6 +6048,7 @@
 		}
 	}
 	set_capture_mixer(spec);
+	set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
 
 	spec->vmaster_nid = 0x08;
 
@@ -6053,8 +6220,6 @@
 	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),
 	{ } /* end */
 };
 
@@ -6081,8 +6246,6 @@
 	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("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -6134,8 +6297,6 @@
 	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("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -6244,8 +6405,10 @@
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	/* FIXME: this looks suspicious...
 	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	*/
 	{ } /* end */
 };
 
@@ -6877,19 +7040,9 @@
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
-		unsigned int vref;
 		if (!nid)
 			continue;
-		vref = PIN_IN;
-		if (1 /*i <= AUTO_PIN_FRONT_MIC*/) {
-			unsigned int pincap;
-			pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-			if ((pincap >> AC_PINCAP_VREF_SHIFT) &
-			    AC_PINCAP_VREF_80)
-				vref = PIN_VREF80;
-		}
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_PIN_WIDGET_CONTROL, vref);
+		alc_set_input_pin(codec, nid, AUTO_PIN_FRONT_MIC /*i*/);
 		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
 			snd_hda_codec_write(codec, nid, 0,
 					    AC_VERB_SET_AMP_GAIN_MUTE,
@@ -6900,18 +7053,21 @@
 static void alc882_auto_init_input_src(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	const struct hda_input_mux *imux = spec->input_mux;
 	int c;
 
 	for (c = 0; c < spec->num_adc_nids; c++) {
 		hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
 		hda_nid_t nid = spec->capsrc_nids[c];
+		unsigned int mux_idx;
+		const struct hda_input_mux *imux;
 		int conns, mute, idx, item;
 
 		conns = snd_hda_get_connections(codec, nid, conn_list,
 						ARRAY_SIZE(conn_list));
 		if (conns < 0)
 			continue;
+		mux_idx = c >= spec->num_mux_defs ? 0 : c;
+		imux = &spec->input_mux[mux_idx];
 		for (idx = 0; idx < conns; idx++) {
 			/* if the current connection is the selected one,
 			 * unmute it as default - otherwise mute it
@@ -6924,8 +7080,20 @@
 					break;
 				}
 			}
-			snd_hda_codec_write(codec, nid, 0,
-					    AC_VERB_SET_AMP_GAIN_MUTE, mute);
+			/* check if we have a selector or mixer
+			 * we could check for the widget type instead, but
+			 * just check for Amp-In presence (in case of mixer
+			 * without amp-in there is something wrong, this
+			 * function shouldn't be used or capsrc nid is wrong)
+			 */
+			if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
+				snd_hda_codec_write(codec, nid, 0,
+						    AC_VERB_SET_AMP_GAIN_MUTE,
+						    mute);
+			else if (mute != AMP_IN_MUTE(idx))
+				snd_hda_codec_write(codec, nid, 0,
+						    AC_VERB_SET_CONNECT_SEL,
+						    idx);
 		}
 	}
 }
@@ -7054,6 +7222,12 @@
 		}
 	}
 
+	err = snd_hda_attach_beep_device(codec, 0x1);
+	if (err < 0) {
+		alc_free(codec);
+		return err;
+	}
+
 	if (board_config != ALC882_AUTO)
 		setup_preset(spec, &alc882_presets[board_config]);
 
@@ -7074,7 +7248,7 @@
 	spec->stream_digital_playback = &alc882_pcm_digital_playback;
 	spec->stream_digital_capture = &alc882_pcm_digital_capture;
 
-	spec->is_mix_capture = 1; /* matrix-style capture */
+	spec->capture_style = CAPT_MIX; /* matrix-style capture */
 	if (!spec->adc_nids && spec->input_mux) {
 		/* check whether NID 0x07 is valid */
 		unsigned int wcap = get_wcaps(codec, 0x07);
@@ -7091,6 +7265,7 @@
 		}
 	}
 	set_capture_mixer(spec);
+	set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
 	spec->vmaster_nid = 0x0c;
 
@@ -7142,10 +7317,14 @@
 	0x09, 0x08
 };
 
+#define alc889_adc_nids		alc880_adc_nids
+
 static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
 
 static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
 
+#define alc889_capsrc_nids	alc882_capsrc_nids
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 
@@ -7363,8 +7542,6 @@
 	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),
 	{ } /* end */
 };
 
@@ -7427,8 +7604,6 @@
 	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),
 	{ } /* end */
 };
 
@@ -7452,8 +7627,6 @@
 	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),
 	{ } /* end */
 };
 
@@ -7478,8 +7651,6 @@
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -7503,8 +7674,6 @@
 	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),
 	{ } /* end */
 };
 
@@ -7912,36 +8081,83 @@
 	{ } /* end */
 };
 
-static struct hda_verb alc888_3st_hp_verbs[] = {
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Rear : output 1 (0x0d) */
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},	/* CLFE : output 2 (0x0e) */
-	{ }
-};
-
 static struct hda_verb alc888_6st_dell_verbs[] = {
 	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
 	{ }
 };
 
+static void alc888_3st_hp_front_automute(struct hda_codec *codec)
+{
+	unsigned int present, bits;
+
+	present = snd_hda_codec_read(codec, 0x1b, 0,
+			AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? HDA_AMP_MUTE : 0;
+	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, bits);
+	snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, bits);
+	snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, bits);
+}
+
+static void alc888_3st_hp_unsol_event(struct hda_codec *codec,
+				      unsigned int res)
+{
+	switch (res >> 26) {
+	case ALC880_HP_EVENT:
+		alc888_3st_hp_front_automute(codec);
+		break;
+	}
+}
+
+static struct hda_verb alc888_3st_hp_verbs[] = {
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Rear : output 1 (0x0d) */
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},	/* CLFE : output 2 (0x0e) */
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+	{ } /* end */
+};
+
+/*
+ * 2ch mode
+ */
 static struct hda_verb alc888_3st_hp_2ch_init[] = {
 	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ }
+	{ } /* end */
 };
 
+/*
+ * 4ch mode
+ */
+static struct hda_verb alc888_3st_hp_4ch_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
 static struct hda_verb alc888_3st_hp_6ch_init[] = {
 	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
 	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ }
+	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
 };
 
-static struct hda_channel_mode alc888_3st_hp_modes[2] = {
+static struct hda_channel_mode alc888_3st_hp_modes[3] = {
 	{ 2, alc888_3st_hp_2ch_init },
+	{ 4, alc888_3st_hp_4ch_init },
 	{ 6, alc888_3st_hp_6ch_init },
 };
 
@@ -8202,7 +8418,7 @@
 {
 	switch (res >> 26) {
 	case ALC880_HP_EVENT:
-		printk("hp_event\n");
+		/* printk(KERN_DEBUG "hp_event\n"); */
 		alc888_6st_dell_front_automute(codec);
 		break;
 	}
@@ -8461,6 +8677,7 @@
 	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
 	SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
 	SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
+	SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
 	SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
 	SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
 	SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
@@ -8468,17 +8685,21 @@
 		ALC888_ACER_ASPIRE_4930G),
 	SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
 		ALC888_ACER_ASPIRE_4930G),
+	SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC883_AUTO),
+	SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC883_AUTO),
 	SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
 		ALC888_ACER_ASPIRE_4930G),
 	SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
 		ALC888_ACER_ASPIRE_4930G),
-	SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */
+	/* default Acer */
+	SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER),
 	SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
 	SND_PCI_QUIRK(0x103c, 0x2a3d, "HP 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", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
+	SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
 	SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
 	SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
 	SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
@@ -8518,7 +8739,7 @@
 	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_VENDOR(0x1558, "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, 0x1107, "FSC AMILO Xi2550",
@@ -8543,6 +8764,10 @@
 	{}
 };
 
+static hda_nid_t alc1200_slave_dig_outs[] = {
+	ALC883_DIGOUT_NID, 0,
+};
+
 static struct alc_config_preset alc883_presets[] = {
 	[ALC883_3ST_2ch_DIG] = {
 		.mixers = { alc883_3ST_2ch_mixer },
@@ -8778,6 +9003,8 @@
 		.channel_mode = alc888_3st_hp_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc883_capture_source,
+		.unsol_event = alc888_3st_hp_unsol_event,
+		.init_hook = alc888_3st_hp_front_automute,
 	},
 	[ALC888_6ST_DELL] = {
 		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
@@ -8883,6 +9110,7 @@
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC1200_DIGOUT_NID,
 		.dig_in_nid = ALC883_DIGIN_NID,
+		.slave_dig_outs = alc1200_slave_dig_outs,
 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
 		.channel_mode = alc883_sixstack_modes,
 		.input_mux = &alc883_capture_source,
@@ -8950,11 +9178,9 @@
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
 		if (alc883_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 != ALC883_PIN_CD_NID)
+			alc_set_input_pin(codec, nid, i);
+			if (nid != ALC883_PIN_CD_NID &&
+			    (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
 				snd_hda_codec_write(codec, nid, 0,
 						    AC_VERB_SET_AMP_GAIN_MUTE,
 						    AMP_OUT_MUTE);
@@ -8969,6 +9195,8 @@
 {
 	struct alc_spec *spec = codec->spec;
 	int err = alc880_parse_auto_config(codec);
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i;
 
 	if (err < 0)
 		return err;
@@ -8982,6 +9210,26 @@
 	/* hack - override the init verbs */
 	spec->init_verbs[0] = alc883_auto_init_verbs;
 
+	/* setup input_mux for ALC889 */
+	if (codec->vendor_id == 0x10ec0889) {
+		/* digital-mic input pin is excluded in alc880_auto_create..()
+		 * because it's under 0x18
+		 */
+		if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 ||
+		    cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) {
+			struct hda_input_mux *imux = &spec->private_imux[0];
+			for (i = 1; i < 3; i++)
+				memcpy(&spec->private_imux[i],
+				       &spec->private_imux[0],
+				       sizeof(spec->private_imux[0]));
+			imux->items[imux->num_items].label = "Int DMic";
+			imux->items[imux->num_items].index = 0x0b;
+			imux->num_items++;
+			spec->num_mux_defs = 3;
+			spec->input_mux = spec->private_imux;
+		}
+	}
+
 	return 1; /* config found */
 }
 
@@ -9033,6 +9281,12 @@
 		}
 	}
 
+	err = snd_hda_attach_beep_device(codec, 0x1);
+	if (err < 0) {
+		alc_free(codec);
+		return err;
+	}
+
 	if (board_config != ALC883_AUTO)
 		setup_preset(spec, &alc883_presets[board_config]);
 
@@ -9045,14 +9299,36 @@
 			spec->stream_name_analog = "ALC888 Analog";
 			spec->stream_name_digital = "ALC888 Digital";
 		}
+		if (!spec->num_adc_nids) {
+			spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
+			spec->adc_nids = alc883_adc_nids;
+		}
+		if (!spec->capsrc_nids)
+			spec->capsrc_nids = alc883_capsrc_nids;
+		spec->capture_style = CAPT_MIX; /* matrix-style capture */
 		break;
 	case 0x10ec0889:
 		spec->stream_name_analog = "ALC889 Analog";
 		spec->stream_name_digital = "ALC889 Digital";
+		if (!spec->num_adc_nids) {
+			spec->num_adc_nids = ARRAY_SIZE(alc889_adc_nids);
+			spec->adc_nids = alc889_adc_nids;
+		}
+		if (!spec->capsrc_nids)
+			spec->capsrc_nids = alc889_capsrc_nids;
+		spec->capture_style = CAPT_1MUX_MIX; /* 1mux/Nmix-style
+							capture */
 		break;
 	default:
 		spec->stream_name_analog = "ALC883 Analog";
 		spec->stream_name_digital = "ALC883 Digital";
+		if (!spec->num_adc_nids) {
+			spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
+			spec->adc_nids = alc883_adc_nids;
+		}
+		if (!spec->capsrc_nids)
+			spec->capsrc_nids = alc883_capsrc_nids;
+		spec->capture_style = CAPT_MIX; /* matrix-style capture */
 		break;
 	}
 
@@ -9063,15 +9339,9 @@
 	spec->stream_digital_playback = &alc883_pcm_digital_playback;
 	spec->stream_digital_capture = &alc883_pcm_digital_capture;
 
-	if (!spec->num_adc_nids) {
-		spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
-		spec->adc_nids = alc883_adc_nids;
-	}
-	if (!spec->capsrc_nids)
-		spec->capsrc_nids = alc883_capsrc_nids;
-	spec->is_mix_capture = 1; /* matrix-style capture */
 	if (!spec->cap_mixer)
 		set_capture_mixer(spec);
+	set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
 	spec->vmaster_nid = 0x0c;
 
@@ -9124,8 +9394,6 @@
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
-	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	   HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */
 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
@@ -9146,8 +9414,6 @@
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
-	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	   HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */
 	/*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 	{ } /* end */
@@ -9256,8 +9522,6 @@
 	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
 	HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
 	{ } /* end */
@@ -9286,8 +9550,6 @@
 	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -9435,6 +9697,67 @@
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new alc262_tyan_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
+	HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+static struct hda_verb alc262_tyan_verbs[] = {
+	/* Headphone automute */
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* P11 AUX_IN, white 4-pin connector */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1},
+	{0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93},
+	{0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19},
+
+	{}
+};
+
+/* unsolicited event for HP jack sensing */
+static void alc262_tyan_automute(struct hda_codec *codec)
+{
+	unsigned int mute;
+	unsigned int present;
+
+	snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
+	present = snd_hda_codec_read(codec, 0x1b, 0,
+				     AC_VERB_GET_PIN_SENSE, 0);
+	present = (present & 0x80000000) != 0;
+	if (present) {
+		/* mute line output on ATX panel */
+		snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+					 HDA_AMP_MUTE, HDA_AMP_MUTE);
+	} else {
+		/* unmute line output if necessary */
+		mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
+		snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+					 HDA_AMP_MUTE, mute);
+	}
+}
+
+static void alc262_tyan_unsol_event(struct hda_codec *codec,
+				       unsigned int res)
+{
+	if ((res >> 26) != ALC880_HP_EVENT)
+		return;
+	alc262_tyan_automute(codec);
+}
+
 #define alc262_capture_mixer		alc882_capture_mixer
 #define alc262_capture_alt_mixer	alc882_capture_alt_mixer
 
@@ -9901,8 +10224,6 @@
 	},
 	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),
@@ -10474,8 +10795,14 @@
 					   alc262_ignore);
 	if (err < 0)
 		return err;
-	if (!spec->autocfg.line_outs)
+	if (!spec->autocfg.line_outs) {
+		if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
+			spec->multiout.max_channels = 2;
+			spec->no_analog = 1;
+			goto dig_only;
+		}
 		return 0; /* can't find valid BIOS pin config */
+	}
 	err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
 	if (err < 0)
 		return err;
@@ -10485,8 +10812,11 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+ dig_only:
+	if (spec->autocfg.dig_outs) {
 		spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
+		spec->dig_out_type = spec->autocfg.dig_out_type[0];
+	}
 	if (spec->autocfg.dig_in_pin)
 		spec->dig_in_nid = ALC262_DIGIN_NID;
 
@@ -10495,13 +10825,12 @@
 
 	add_verb(spec, alc262_volume_init_verbs);
 	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux;
+	spec->input_mux = &spec->private_imux[0];
 
 	err = alc_auto_add_mic_boost(codec);
 	if (err < 0)
 		return err;
 
-	store_pin_configs(codec);
 	return 1;
 }
 
@@ -10543,21 +10872,19 @@
 	[ALC262_ULTRA]		= "ultra",
 	[ALC262_LENOVO_3000]	= "lenovo-3000",
 	[ALC262_NEC]		= "nec",
+	[ALC262_TYAN]		= "tyan",
 	[ALC262_AUTO]		= "auto",
 };
 
 static struct snd_pci_quirk alc262_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
 	SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
-	SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x170b, "HP xw*", ALC262_HP_BPC),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
+			   ALC262_HP_BPC),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
+			   ALC262_HP_BPC),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
+			   ALC262_HP_BPC),
 	SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
 	SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
 	SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
@@ -10575,17 +10902,17 @@
 	SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
 	SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
 	SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
-	SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
-	SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
-	SND_PCI_QUIRK(0x104d, 0x9033, "Sony VAIO VGN-SR19XN",
-		      ALC262_SONY_ASSAMD),
+	SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
+	SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
+			   ALC262_SONY_ASSAMD),
 	SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
 		      ALC262_TOSHIBA_RX1),
 	SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
 	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
 	SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
-	SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
-	SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA),
+	SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN),
+	SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
+			   ALC262_ULTRA),
 	SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
 	SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
 	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
@@ -10802,6 +11129,19 @@
 		.unsol_event = alc262_hippo_unsol_event,
 		.init_hook = alc262_hippo_automute,
 	},
+	[ALC262_TYAN] = {
+		.mixers = { alc262_tyan_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_tyan_verbs},
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x02,
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc262_tyan_unsol_event,
+		.init_hook = alc262_tyan_automute,
+	},
 };
 
 static int patch_alc262(struct hda_codec *codec)
@@ -10854,6 +11194,14 @@
 		}
 	}
 
+	if (!spec->no_analog) {
+		err = snd_hda_attach_beep_device(codec, 0x1);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+	}
+
 	if (board_config != ALC262_AUTO)
 		setup_preset(spec, &alc262_presets[board_config]);
 
@@ -10865,7 +11213,7 @@
 	spec->stream_digital_playback = &alc262_pcm_digital_playback;
 	spec->stream_digital_capture = &alc262_pcm_digital_capture;
 
-	spec->is_mix_capture = 1;
+	spec->capture_style = CAPT_MIX;
 	if (!spec->adc_nids && spec->input_mux) {
 		/* check whether NID 0x07 is valid */
 		unsigned int wcap = get_wcaps(codec, 0x07);
@@ -10882,8 +11230,10 @@
 			spec->capsrc_nids = alc262_capsrc_nids;
 		}
 	}
-	if (!spec->cap_mixer)
+	if (!spec->cap_mixer && !spec->no_analog)
 		set_capture_mixer(spec);
+	if (!spec->no_analog)
+		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
 	spec->vmaster_nid = 0x0c;
 
@@ -11263,19 +11613,13 @@
 static struct hda_verb alc268_base_init_verbs[] = {
 	/* Unmute DAC0-1 and set vol = 0 */
 	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 
 	/*
 	 * Set up output mixers (0x0c - 0x0e)
 	 */
 	/* set vol=0 to output mixers */
 	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
         {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
 
 	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -11294,9 +11638,7 @@
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 
 	/* set PCBEEP vol = 0, mute connections */
 	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -11318,10 +11660,8 @@
  */
 static struct hda_verb alc268_volume_init_verbs[] = {
 	/* set output DAC */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 
 	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
 	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
@@ -11329,16 +11669,12 @@
 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
 	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
 
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 
 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 
 	/* set PCBEEP vol = 0, mute connections */
 	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -11537,7 +11873,7 @@
 static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
 						const struct auto_pin_cfg *cfg)
 {
-	struct hda_input_mux *imux = &spec->private_imux;
+	struct hda_input_mux *imux = &spec->private_imux[0];
 	int i, idx1;
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
@@ -11631,9 +11967,14 @@
 					   alc268_ignore);
 	if (err < 0)
 		return err;
-	if (!spec->autocfg.line_outs)
+	if (!spec->autocfg.line_outs) {
+		if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
+			spec->multiout.max_channels = 2;
+			spec->no_analog = 1;
+			goto dig_only;
+		}
 		return 0; /* can't find valid BIOS pin config */
-
+	}
 	err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
 	if (err < 0)
 		return err;
@@ -11643,25 +11984,26 @@
 
 	spec->multiout.max_channels = 2;
 
+ dig_only:
 	/* digital only support output */
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs) {
 		spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
-
+		spec->dig_out_type = spec->autocfg.dig_out_type[0];
+	}
 	if (spec->kctls.list)
 		add_mixer(spec, spec->kctls.list);
 
-	if (spec->autocfg.speaker_pins[0] != 0x1d)
+	if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d)
 		add_mixer(spec, alc268_beep_mixer);
 
 	add_verb(spec, alc268_volume_init_verbs);
 	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux;
+	spec->input_mux = &spec->private_imux[0];
 
 	err = alc_auto_add_mic_boost(codec);
 	if (err < 0)
 		return err;
 
-	store_pin_configs(codec);
 	return 1;
 }
 
@@ -11723,7 +12065,7 @@
 
 static struct alc_config_preset alc268_presets[] = {
 	[ALC267_QUANTA_IL1] = {
-		.mixers = { alc267_quanta_il1_mixer },
+		.mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer },
 		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
 				alc267_quanta_il1_verbs },
 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -11805,7 +12147,8 @@
 	},
 	[ALC268_ACER_ASPIRE_ONE] = {
 		.mixers = { alc268_acer_aspire_one_mixer,
-				alc268_capture_alt_mixer },
+			    alc268_beep_mixer,
+			    alc268_capture_alt_mixer },
 		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
 				alc268_acer_aspire_one_verbs },
 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -11874,7 +12217,7 @@
 {
 	struct alc_spec *spec;
 	int board_config;
-	int err;
+	int i, has_beep, err;
 
 	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -11923,15 +12266,30 @@
 
 	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,
+	has_beep = 0;
+	for (i = 0; i < spec->num_mixers; i++) {
+		if (spec->mixers[i] == alc268_beep_mixer) {
+			has_beep = 1;
+			break;
+		}
+	}
+
+	if (has_beep) {
+		err = snd_hda_attach_beep_device(codec, 0x1);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+		if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
+			/* override the amp caps for beep generator */
+			snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
 					  (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
 					  (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
 					  (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
 					  (0 << AC_AMPCAP_MUTE_SHIFT));
+	}
 
-	if (!spec->adc_nids && spec->input_mux) {
+	if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
 		/* check whether NID 0x07 is valid */
 		unsigned int wcap = get_wcaps(codec, 0x07);
 		int i;
@@ -12012,8 +12370,6 @@
 	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
@@ -12040,8 +12396,6 @@
 	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT),
 	{ }
 };
 
@@ -12065,8 +12419,6 @@
 	HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
 	HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
 	HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT),
 	{ }
 };
 
@@ -12103,13 +12455,6 @@
 	{ } /* end */
 };
 
-/* beep control */
-static struct snd_kcontrol_new alc269_beep_mixer[] = {
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT),
-	{ } /* end */
-};
-
 static struct hda_verb alc269_quanta_fl1_verbs[] = {
 	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
@@ -12509,7 +12854,7 @@
 	 */
 	if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 ||
 	    cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) {
-		struct hda_input_mux *imux = &spec->private_imux;
+		struct hda_input_mux *imux = &spec->private_imux[0];
 		imux->items[imux->num_items].label = "Int Mic";
 		imux->items[imux->num_items].index = 0x05;
 		imux->num_items++;
@@ -12527,13 +12872,34 @@
 #define alc269_pcm_digital_playback	alc880_pcm_digital_playback
 #define alc269_pcm_digital_capture	alc880_pcm_digital_capture
 
+static struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 8,
+	.rates = SNDRV_PCM_RATE_44100, /* fixed rate */
+	/* NID is set in alc_build_pcms */
+	.ops = {
+		.open = alc880_playback_pcm_open,
+		.prepare = alc880_playback_pcm_prepare,
+		.cleanup = alc880_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.rates = SNDRV_PCM_RATE_44100, /* fixed rate */
+	/* NID is set in alc_build_pcms */
+};
+
 /*
  * BIOS auto configuration
  */
 static int alc269_parse_auto_config(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	int i, err;
+	int err;
 	static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
 
 	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
@@ -12550,22 +12916,15 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
 
 	if (spec->kctls.list)
 		add_mixer(spec, spec->kctls.list);
 
-	/* create a beep mixer control if the pin 0x1d isn't assigned */
-	for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++)
-		if (spec->autocfg.input_pins[i] == 0x1d)
-			break;
-	if (i >= ARRAY_SIZE(spec->autocfg.input_pins))
-		add_mixer(spec, alc269_beep_mixer);
-
 	add_verb(spec, alc269_init_verbs);
 	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux;
+	spec->input_mux = &spec->private_imux[0];
 	/* set default input source */
 	snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0],
 				  0, AC_VERB_SET_CONNECT_SEL,
@@ -12575,10 +12934,9 @@
 	if (err < 0)
 		return err;
 
-	if (!spec->cap_mixer)
+	if (!spec->cap_mixer && !spec->no_analog)
 		set_capture_mixer(spec);
 
-	store_pin_configs(codec);
 	return 1;
 }
 
@@ -12675,7 +13033,7 @@
 		.init_hook = alc269_eeepc_dmic_inithook,
 	},
 	[ALC269_FUJITSU] = {
-		.mixers = { alc269_fujitsu_mixer, alc269_beep_mixer },
+		.mixers = { alc269_fujitsu_mixer },
 		.cap_mixer = alc269_epc_capture_mixer,
 		.init_verbs = { alc269_init_verbs,
 				alc269_eeepc_dmic_init_verbs },
@@ -12740,13 +13098,26 @@
 		}
 	}
 
+	err = snd_hda_attach_beep_device(codec, 0x1);
+	if (err < 0) {
+		alc_free(codec);
+		return err;
+	}
+
 	if (board_config != ALC269_AUTO)
 		setup_preset(spec, &alc269_presets[board_config]);
 
 	spec->stream_name_analog = "ALC269 Analog";
-	spec->stream_analog_playback = &alc269_pcm_analog_playback;
-	spec->stream_analog_capture = &alc269_pcm_analog_capture;
-
+	if (codec->subsystem_id == 0x17aa3bf8) {
+		/* Due to a hardware problem on Lenovo Ideadpad, we need to
+		 * fix the sample rate of analog I/O to 44.1kHz
+		 */
+		spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
+		spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
+	} else {
+		spec->stream_analog_playback = &alc269_pcm_analog_playback;
+		spec->stream_analog_capture = &alc269_pcm_analog_capture;
+	}
 	spec->stream_name_digital = "ALC269 Digital";
 	spec->stream_digital_playback = &alc269_pcm_digital_playback;
 	spec->stream_digital_capture = &alc269_pcm_digital_capture;
@@ -12756,6 +13127,7 @@
 	spec->capsrc_nids = alc269_capsrc_nids;
 	if (!spec->cap_mixer)
 		set_capture_mixer(spec);
+	set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
 
 	codec->patch_ops = alc_patch_ops;
 	if (board_config == ALC269_AUTO)
@@ -13006,8 +13378,6 @@
 static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT),
 	{ }
 };
 
@@ -13481,7 +13851,7 @@
 static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
 						const struct auto_pin_cfg *cfg)
 {
-	struct hda_input_mux *imux = &spec->private_imux;
+	struct hda_input_mux *imux = &spec->private_imux[0];
 	int i, err, idx, idx1;
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
@@ -13568,12 +13938,8 @@
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
-		if (nid >= 0x0c && nid <= 0x11) {
-			snd_hda_codec_write(codec, nid, 0,
-					    AC_VERB_SET_PIN_WIDGET_CONTROL,
-					    i <= AUTO_PIN_FRONT_MIC ?
-					    PIN_VREF80 : PIN_IN);
-		}
+		if (nid >= 0x0c && nid <= 0x11)
+			alc_set_input_pin(codec, nid, i);
 	}
 }
 
@@ -13609,7 +13975,7 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
 
 	if (spec->kctls.list)
@@ -13618,13 +13984,12 @@
 	add_verb(spec, alc861_auto_init_verbs);
 
 	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux;
+	spec->input_mux = &spec->private_imux[0];
 
 	spec->adc_nids = alc861_adc_nids;
 	spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
 	set_capture_mixer(spec);
 
-	store_pin_configs(codec);
 	return 1;
 }
 
@@ -13833,6 +14198,12 @@
 		}
 	}
 
+	err = snd_hda_attach_beep_device(codec, 0x23);
+	if (err < 0) {
+		alc_free(codec);
+		return err;
+	}
+
 	if (board_config != ALC861_AUTO)
 		setup_preset(spec, &alc861_presets[board_config]);
 
@@ -13844,6 +14215,8 @@
 	spec->stream_digital_playback = &alc861_pcm_digital_playback;
 	spec->stream_digital_capture = &alc861_pcm_digital_capture;
 
+	set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
+
 	spec->vmaster_nid = 0x03;
 
 	codec->patch_ops = alc_patch_ops;
@@ -14000,9 +14373,6 @@
 	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 Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-
 	{ } /* end */
 };
 
@@ -14026,9 +14396,6 @@
 	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 Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-
 	{ } /* end */
 };
 
@@ -14067,8 +14434,6 @@
 	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 */
 };
 
@@ -14379,9 +14744,7 @@
 	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),
-	SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 N200", ALC861VD_LENOVO),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO),
 	SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
 	{}
 };
@@ -14543,11 +14906,9 @@
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
 		if (alc861vd_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 != ALC861VD_PIN_CD_NID)
+			alc_set_input_pin(codec, nid, i);
+			if (nid != ALC861VD_PIN_CD_NID &&
+			    (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
 				snd_hda_codec_write(codec, nid, 0,
 						AC_VERB_SET_AMP_GAIN_MUTE,
 						AMP_OUT_MUTE);
@@ -14713,7 +15074,7 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
 
 	if (spec->kctls.list)
@@ -14722,13 +15083,12 @@
 	add_verb(spec, alc861vd_volume_init_verbs);
 
 	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux;
+	spec->input_mux = &spec->private_imux[0];
 
 	err = alc_auto_add_mic_boost(codec);
 	if (err < 0)
 		return err;
 
-	store_pin_configs(codec);
 	return 1;
 }
 
@@ -14779,6 +15139,12 @@
 		}
 	}
 
+	err = snd_hda_attach_beep_device(codec, 0x23);
+	if (err < 0) {
+		alc_free(codec);
+		return err;
+	}
+
 	if (board_config != ALC861VD_AUTO)
 		setup_preset(spec, &alc861vd_presets[board_config]);
 
@@ -14801,9 +15167,10 @@
 	spec->adc_nids = alc861vd_adc_nids;
 	spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
 	spec->capsrc_nids = alc861vd_capsrc_nids;
-	spec->is_mix_capture = 1;
+	spec->capture_style = CAPT_MIX;
 
 	set_capture_mixer(spec);
+	set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
 	spec->vmaster_nid = 0x02;
 
@@ -14992,8 +15359,6 @@
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -15015,8 +15380,6 @@
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -15992,56 +16355,55 @@
 };
 
 static struct snd_pci_quirk alc662_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
+	SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
+	SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
+	SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
+	SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
+	SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
 	SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
+	/*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
+	SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
 	SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
+	/*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
+	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
 	SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
 	SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
 	SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
-	SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
-	SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
-	SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
-	SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
-	SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
+	SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
 	SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
 		      ALC662_3ST_6ch_DIG),
-	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
-	SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
-	SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
 	SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
 		      ALC662_3ST_6ch_DIG),
 	SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
+	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
 	SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
 					ALC662_3ST_6ch_DIG),
-	SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13),
-	SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13),
-	SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13),
+	SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
+			   ALC663_ASUS_H13),
 	{}
 };
 
@@ -16361,7 +16723,7 @@
 
 	if (alc880_is_fixed_pin(pin)) {
 		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
-                /* printk("DAC nid=%x\n",nid); */
+		/* printk(KERN_DEBUG "DAC nid=%x\n",nid); */
 		/* specify the DAC as the extra output */
 		if (!spec->multiout.hp_nid)
 			spec->multiout.hp_nid = nid;
@@ -16391,26 +16753,58 @@
 	return 0;
 }
 
+/* return the index of the src widget from the connection list of the nid.
+ * return -1 if not found
+ */
+static int alc662_input_pin_idx(struct hda_codec *codec, hda_nid_t nid,
+				hda_nid_t src)
+{
+	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+	int i, conns;
+
+	conns = snd_hda_get_connections(codec, nid, conn_list,
+					ARRAY_SIZE(conn_list));
+	if (conns < 0)
+		return -1;
+	for (i = 0; i < conns; i++)
+		if (conn_list[i] == src)
+			return i;
+	return -1;
+}
+
+static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
+{
+	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
+	return (pincap & AC_PINCAP_IN) != 0;
+}
+
 /* create playback/capture controls for input pins */
-static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec,
+static int alc662_auto_create_analog_input_ctls(struct hda_codec *codec,
 						const struct auto_pin_cfg *cfg)
 {
-	struct hda_input_mux *imux = &spec->private_imux;
+	struct alc_spec *spec = codec->spec;
+	struct hda_input_mux *imux = &spec->private_imux[0];
 	int i, err, idx;
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
-		if (alc880_is_input_pin(cfg->input_pins[i])) {
-			idx = alc880_input_pin_idx(cfg->input_pins[i]);
-			err = new_analog_input(spec, cfg->input_pins[i],
-					       auto_pin_cfg_labels[i],
-					       idx, 0x0b);
-			if (err < 0)
-				return err;
-			imux->items[imux->num_items].label =
-				auto_pin_cfg_labels[i];
-			imux->items[imux->num_items].index =
-				alc880_input_pin_idx(cfg->input_pins[i]);
-			imux->num_items++;
+		if (alc662_is_input_pin(codec, cfg->input_pins[i])) {
+			idx = alc662_input_pin_idx(codec, 0x0b,
+						   cfg->input_pins[i]);
+			if (idx >= 0) {
+				err = new_analog_input(spec, cfg->input_pins[i],
+						       auto_pin_cfg_labels[i],
+						       idx, 0x0b);
+				if (err < 0)
+					return err;
+			}
+			idx = alc662_input_pin_idx(codec, 0x22,
+						   cfg->input_pins[i]);
+			if (idx >= 0) {
+				imux->items[imux->num_items].label =
+					auto_pin_cfg_labels[i];
+				imux->items[imux->num_items].index = idx;
+				imux->num_items++;
+			}
 		}
 	}
 	return 0;
@@ -16460,7 +16854,6 @@
 		alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
-#define alc662_is_input_pin(nid)	alc880_is_input_pin(nid)
 #define ALC662_PIN_CD_NID		ALC880_PIN_CD_NID
 
 static void alc662_auto_init_analog_input(struct hda_codec *codec)
@@ -16470,12 +16863,10 @@
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
-		if (alc662_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 != ALC662_PIN_CD_NID)
+		if (alc662_is_input_pin(codec, nid)) {
+			alc_set_input_pin(codec, nid, i);
+			if (nid != ALC662_PIN_CD_NID &&
+			    (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
 				snd_hda_codec_write(codec, nid, 0,
 						    AC_VERB_SET_AMP_GAIN_MUTE,
 						    AMP_OUT_MUTE);
@@ -16513,20 +16904,20 @@
 					   "Headphone");
 	if (err < 0)
 		return err;
-	err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg);
+	err = alc662_auto_create_analog_input_ctls(codec, &spec->autocfg);
 	if (err < 0)
 		return err;
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
 
 	if (spec->kctls.list)
 		add_mixer(spec, spec->kctls.list);
 
 	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux;
+	spec->input_mux = &spec->private_imux[0];
 
 	add_verb(spec, alc662_auto_init_verbs);
 	if (codec->vendor_id == 0x10ec0663)
@@ -16536,7 +16927,6 @@
 	if (err < 0)
 		return err;
 
-	store_pin_configs(codec);
 	return 1;
 }
 
@@ -16588,6 +16978,12 @@
 		}
 	}
 
+	err = snd_hda_attach_beep_device(codec, 0x1);
+	if (err < 0) {
+		alc_free(codec);
+		return err;
+	}
+
 	if (board_config != ALC662_AUTO)
 		setup_preset(spec, &alc662_presets[board_config]);
 
@@ -16611,10 +17007,14 @@
 	spec->adc_nids = alc662_adc_nids;
 	spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
 	spec->capsrc_nids = alc662_capsrc_nids;
-	spec->is_mix_capture = 1;
+	spec->capture_style = CAPT_MIX;
 
 	if (!spec->cap_mixer)
 		set_capture_mixer(spec);
+	if (codec->vendor_id == 0x10ec0662)
+		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
+	else
+		set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
 
 	spec->vmaster_nid = 0x02;
 
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 3bc4276..b5e108a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -43,6 +43,7 @@
 };
 
 enum {
+	STAC_AUTO,
 	STAC_REF,
 	STAC_9200_OQO,
 	STAC_9200_DELL_D21,
@@ -62,14 +63,17 @@
 };
 
 enum {
+	STAC_9205_AUTO,
 	STAC_9205_REF,
 	STAC_9205_DELL_M42,
 	STAC_9205_DELL_M43,
 	STAC_9205_DELL_M44,
+	STAC_9205_EAPD,
 	STAC_9205_MODELS
 };
 
 enum {
+	STAC_92HD73XX_AUTO,
 	STAC_92HD73XX_NO_JD, /* no jack-detection */
 	STAC_92HD73XX_REF,
 	STAC_DELL_M6_AMIC,
@@ -80,22 +84,27 @@
 };
 
 enum {
+	STAC_92HD83XXX_AUTO,
 	STAC_92HD83XXX_REF,
 	STAC_92HD83XXX_PWR_REF,
+	STAC_DELL_S14,
 	STAC_92HD83XXX_MODELS
 };
 
 enum {
+	STAC_92HD71BXX_AUTO,
 	STAC_92HD71BXX_REF,
 	STAC_DELL_M4_1,
 	STAC_DELL_M4_2,
 	STAC_DELL_M4_3,
 	STAC_HP_M4,
 	STAC_HP_DV5,
+	STAC_HP_HDX,
 	STAC_92HD71BXX_MODELS
 };
 
 enum {
+	STAC_925x_AUTO,
 	STAC_925x_REF,
 	STAC_M1,
 	STAC_M1_2,
@@ -108,6 +117,7 @@
 };
 
 enum {
+	STAC_922X_AUTO,
 	STAC_D945_REF,
 	STAC_D945GTP3,
 	STAC_D945GTP5,
@@ -135,6 +145,7 @@
 };
 
 enum {
+	STAC_927X_AUTO,
 	STAC_D965_REF_NO_JD, /* no jack-detection */
 	STAC_D965_REF,
 	STAC_D965_3ST,
@@ -144,6 +155,12 @@
 	STAC_927X_MODELS
 };
 
+enum {
+	STAC_9872_AUTO,
+	STAC_9872_VAIO,
+	STAC_9872_MODELS
+};
+
 struct sigmatel_event {
 	hda_nid_t nid;
 	unsigned char type;
@@ -167,6 +184,7 @@
 	unsigned int alt_switch: 1;
 	unsigned int hp_detect: 1;
 	unsigned int spdif_mute: 1;
+	unsigned int check_volume_offset:1;
 
 	/* gpio lines */
 	unsigned int eapd_mask;
@@ -179,6 +197,7 @@
 	unsigned int stream_delay;
 
 	/* analog loopback */
+	struct snd_kcontrol_new *aloopback_ctl;
 	unsigned char aloopback_mask;
 	unsigned char aloopback_shift;
 
@@ -203,6 +222,8 @@
 	hda_nid_t hp_dacs[5];
 	hda_nid_t speaker_dacs[5];
 
+	int volume_offset;
+
 	/* capture */
 	hda_nid_t *adc_nids;
 	unsigned int num_adcs;
@@ -224,7 +245,6 @@
 	/* pin widgets */
 	hda_nid_t *pin_nids;
 	unsigned int num_pins;
-	unsigned int *pin_configs;
 
 	/* codec specific stuff */
 	struct hda_verb *init;
@@ -400,6 +420,10 @@
         0x12, 0x13,
 };
 
+static hda_nid_t stac927x_slave_dig_outs[2] = {
+	0x1f, 0,
+};
+
 static hda_nid_t stac927x_adc_nids[3] = {
         0x07, 0x08, 0x09
 };
@@ -472,15 +496,21 @@
 	0x14, 0x22, 0x23
 };
 
-static hda_nid_t stac92hd83xxx_pin_nids[14] = {
+static hda_nid_t stac92hd83xxx_pin_nids[10] = {
 	0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
-	0x0f, 0x10, 0x11, 0x12, 0x13,
-	0x1d, 0x1e, 0x1f, 0x20
+	0x0f, 0x10, 0x11, 0x1f, 0x20,
 };
-static hda_nid_t stac92hd71bxx_pin_nids[11] = {
+
+#define STAC92HD71BXX_NUM_PINS 13
+static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = {
+	0x0a, 0x0b, 0x0c, 0x0d, 0x00,
+	0x00, 0x14, 0x18, 0x19, 0x1e,
+	0x1f, 0x20, 0x27
+};
+static hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = {
 	0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
 	0x0f, 0x14, 0x18, 0x19, 0x1e,
-	0x1f,
+	0x1f, 0x20, 0x27
 };
 
 static hda_nid_t stac927x_pin_nids[14] = {
@@ -842,9 +872,9 @@
 };
 
 static struct hda_verb stac92hd83xxx_core_init[] = {
-	{ 0xa, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{ 0xb, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{ 0xd, AC_VERB_SET_CONNECT_SEL, 0x1},
+	{ 0xa, AC_VERB_SET_CONNECT_SEL, 0x1},
+	{ 0xb, AC_VERB_SET_CONNECT_SEL, 0x1},
+	{ 0xd, AC_VERB_SET_CONNECT_SEL, 0x0},
 
 	/* power state controls amps */
 	{ 0x01, AC_VERB_SET_EAPD, 1 << 2},
@@ -854,26 +884,25 @@
 static struct hda_verb stac92hd71bxx_core_init[] = {
 	/* set master volume and direct control */
 	{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
-	/* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */
-	{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{}
 };
 
-#define HD_DISABLE_PORTF 2
+#define HD_DISABLE_PORTF 1
 static struct hda_verb stac92hd71bxx_analog_core_init[] = {
 	/* start of config #1 */
 
 	/* connect port 0f to audio mixer */
 	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
-	/* unmute right and left channels for node 0x0f */
-	{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	/* start of config #2 */
 
 	/* set master volume and direct control */
 	{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
-	/* unmute right and left channels for nodes 0x0a, 0xd */
+	{}
+};
+
+static struct hda_verb stac92hd71bxx_unmute_core_init[] = {
+	/* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */
+	{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{}
@@ -954,16 +983,6 @@
 		.private_value = HDA_COMPOSE_AMP_VAL(nid, chs, idx, dir) \
 	}
 
-#define STAC_INPUT_SOURCE(cnt) \
-	{ \
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-		.name = "Input Source", \
-		.count = cnt, \
-		.info = stac92xx_mux_enum_info, \
-		.get = stac92xx_mux_enum_get, \
-		.put = stac92xx_mux_enum_put, \
-	}
-
 #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \
 	{ \
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
@@ -978,7 +997,6 @@
 static struct snd_kcontrol_new stac9200_mixer[] = {
 	HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
-	STAC_INPUT_SOURCE(1),
 	HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
 	{ } /* end */
@@ -1003,8 +1021,6 @@
 	HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT),
 	HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT),
 
-	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3),
-
 	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
 
@@ -1014,9 +1030,22 @@
 	{ } /* end */
 };
 
-static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
-	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4),
+static struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = {
+	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3),
+	{}
+};
 
+static struct snd_kcontrol_new stac92hd73xx_8ch_loopback[] = {
+	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4),
+	{}
+};
+
+static struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = {
+	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5),
+	{}
+};
+
+static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
 	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
 
@@ -1041,8 +1070,6 @@
 };
 
 static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = {
-	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5),
-
 	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
 
@@ -1094,9 +1121,6 @@
 };
 
 static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
-	STAC_INPUT_SOURCE(2),
-	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2),
-
 	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 
@@ -1122,10 +1146,11 @@
 	{ } /* end */
 };
 
-static struct snd_kcontrol_new stac92hd71bxx_mixer[] = {
-	STAC_INPUT_SOURCE(2),
-	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2),
+static struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
+	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2)
+};
 
+static struct snd_kcontrol_new stac92hd71bxx_mixer[] = {
 	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 
@@ -1137,16 +1162,12 @@
 static struct snd_kcontrol_new stac925x_mixer[] = {
 	HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
-	STAC_INPUT_SOURCE(1),
 	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT),
 	{ } /* end */
 };
 
 static struct snd_kcontrol_new stac9205_mixer[] = {
-	STAC_INPUT_SOURCE(2),
-	STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1),
-
 	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT),
 
@@ -1155,9 +1176,13 @@
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new stac9205_loopback[] = {
+	STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1),
+	{}
+};
+
 /* This needs to be generated dynamically based on sequence */
 static struct snd_kcontrol_new stac922x_mixer[] = {
-	STAC_INPUT_SOURCE(2),
 	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT),
 
@@ -1168,9 +1193,6 @@
 
 
 static struct snd_kcontrol_new stac927x_mixer[] = {
-	STAC_INPUT_SOURCE(3),
-	STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1),
-
 	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT),
 
@@ -1182,6 +1204,11 @@
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new stac927x_loopback[] = {
+	STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1),
+	{}
+};
+
 static struct snd_kcontrol_new stac_dmux_mixer = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Digital Input Source",
@@ -1207,10 +1234,7 @@
 	"LFE Playback Volume",
 	"Side Playback Volume",
 	"Headphone Playback Volume",
-	"Headphone Playback Volume",
 	"Speaker Playback Volume",
-	"External Speaker Playback Volume",
-	"Speaker2 Playback Volume",
 	NULL
 };
 
@@ -1221,10 +1245,7 @@
 	"LFE Playback Switch",
 	"Side Playback Switch",
 	"Headphone Playback Switch",
-	"Headphone Playback Switch",
 	"Speaker Playback Switch",
-	"External Speaker Playback Switch",
-	"Speaker2 Playback Switch",
 	"IEC958 Playback Switch",
 	NULL
 };
@@ -1294,6 +1315,8 @@
 		unsigned int vmaster_tlv[4];
 		snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
 					HDA_OUTPUT, vmaster_tlv);
+		/* correct volume offset */
+		vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
 					  vmaster_tlv, slave_vols);
 		if (err < 0)
@@ -1306,6 +1329,13 @@
 			return err;
 	}
 
+	if (spec->aloopback_ctl &&
+	    snd_hda_get_bool_hint(codec, "loopback") == 1) {
+		err = snd_hda_add_new_ctls(codec, spec->aloopback_ctl);
+		if (err < 0)
+			return err;
+	}
+
 	stac92xx_free_kctls(codec); /* no longer needed */
 
 	/* create jack input elements */
@@ -1490,6 +1520,7 @@
 };
 
 static const char *stac9200_models[STAC_9200_MODELS] = {
+	[STAC_AUTO] = "auto",
 	[STAC_REF] = "ref",
 	[STAC_9200_OQO] = "oqo",
 	[STAC_9200_DELL_D21] = "dell-d21",
@@ -1511,6 +1542,8 @@
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
 		      "DFI LanParty", STAC_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
+		      "DFI LanParty", STAC_REF),
 	/* Dell laptops have BIOS problem */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8,
 		      "unknown Dell", STAC_9200_DELL_D21),
@@ -1633,6 +1666,7 @@
 };
 
 static const char *stac925x_models[STAC_925x_MODELS] = {
+	[STAC_925x_AUTO] = "auto",
 	[STAC_REF] = "ref",
 	[STAC_M1] = "m1",
 	[STAC_M1_2] = "m1-2",
@@ -1660,6 +1694,7 @@
 static struct snd_pci_quirk stac925x_cfg_tbl[] = {
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF),
 	SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF),
 
 	/* Default table for unknown ID */
@@ -1691,6 +1726,7 @@
 };
 
 static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
+	[STAC_92HD73XX_AUTO] = "auto",
 	[STAC_92HD73XX_NO_JD] = "no-jd",
 	[STAC_92HD73XX_REF] = "ref",
 	[STAC_DELL_M6_AMIC] = "dell-m6-amic",
@@ -1703,6 +1739,8 @@
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
 				"DFI LanParty", STAC_92HD73XX_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
+				"DFI LanParty", STAC_92HD73XX_REF),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
 				"Dell Studio 1535", STAC_DELL_M6_DMIC),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
@@ -1726,52 +1764,68 @@
 	{} /* terminator */
 };
 
-static unsigned int ref92hd83xxx_pin_configs[14] = {
+static unsigned int ref92hd83xxx_pin_configs[10] = {
 	0x02214030, 0x02211010, 0x02a19020, 0x02170130,
 	0x01014050, 0x01819040, 0x01014020, 0x90a3014e,
-	0x40f000f0, 0x40f000f0, 0x40f000f0, 0x40f000f0,
 	0x01451160, 0x98560170,
 };
 
+static unsigned int dell_s14_pin_configs[10] = {
+	0x02214030, 0x02211010, 0x02a19020, 0x01014050,
+	0x40f000f0, 0x01819040, 0x40f000f0, 0x90a60160,
+	0x40f000f0, 0x40f000f0,
+};
+
 static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
 	[STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
 	[STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
+	[STAC_DELL_S14] = dell_s14_pin_configs,
 };
 
 static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
+	[STAC_92HD83XXX_AUTO] = "auto",
 	[STAC_92HD83XXX_REF] = "ref",
 	[STAC_92HD83XXX_PWR_REF] = "mic-ref",
+	[STAC_DELL_S14] = "dell-s14",
 };
 
 static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
 		      "DFI LanParty", STAC_92HD83XXX_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
+		      "DFI LanParty", STAC_92HD83XXX_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
+		      "unknown Dell", STAC_DELL_S14),
 	{} /* terminator */
 };
 
-static unsigned int ref92hd71bxx_pin_configs[11] = {
+static unsigned int ref92hd71bxx_pin_configs[STAC92HD71BXX_NUM_PINS] = {
 	0x02214030, 0x02a19040, 0x01a19020, 0x01014010,
 	0x0181302e, 0x01014010, 0x01019020, 0x90a000f0,
-	0x90a000f0, 0x01452050, 0x01452050,
+	0x90a000f0, 0x01452050, 0x01452050, 0x00000000,
+	0x00000000
 };
 
-static unsigned int dell_m4_1_pin_configs[11] = {
+static unsigned int dell_m4_1_pin_configs[STAC92HD71BXX_NUM_PINS] = {
 	0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
 	0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0,
-	0x40f000f0, 0x4f0000f0, 0x4f0000f0,
+	0x40f000f0, 0x4f0000f0, 0x4f0000f0, 0x00000000,
+	0x00000000
 };
 
-static unsigned int dell_m4_2_pin_configs[11] = {
+static unsigned int dell_m4_2_pin_configs[STAC92HD71BXX_NUM_PINS] = {
 	0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
 	0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0,
-	0x40f000f0, 0x044413b0, 0x044413b0,
+	0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000,
+	0x00000000
 };
 
-static unsigned int dell_m4_3_pin_configs[11] = {
+static unsigned int dell_m4_3_pin_configs[STAC92HD71BXX_NUM_PINS] = {
 	0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
 	0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0,
-	0x40f000f0, 0x044413b0, 0x044413b0,
+	0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000,
+	0x00000000
 };
 
 static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
@@ -1781,35 +1835,38 @@
 	[STAC_DELL_M4_3]	= dell_m4_3_pin_configs,
 	[STAC_HP_M4]		= NULL,
 	[STAC_HP_DV5]		= NULL,
+	[STAC_HP_HDX]           = NULL,
 };
 
 static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
+	[STAC_92HD71BXX_AUTO] = "auto",
 	[STAC_92HD71BXX_REF] = "ref",
 	[STAC_DELL_M4_1] = "dell-m4-1",
 	[STAC_DELL_M4_2] = "dell-m4-2",
 	[STAC_DELL_M4_3] = "dell-m4-3",
 	[STAC_HP_M4] = "hp-m4",
 	[STAC_HP_DV5] = "hp-dv5",
+	[STAC_HP_HDX] = "hp-hdx",
 };
 
 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_HP, 0x30f2,
-		      "HP dv5", STAC_HP_M4),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4,
-		      "HP dv7", STAC_HP_DV5),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f7,
-		      "HP dv4", STAC_HP_DV5),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc,
-		      "HP dv7", STAC_HP_M4),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3600,
-		      "HP dv5", STAC_HP_DV5),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3603,
-		      "HP dv5", STAC_HP_DV5),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
+		      "DFI LanParty", STAC_92HD71BXX_REF),
+	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080,
+		      "HP", STAC_HP_DV5),
+	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0,
+		      "HP dv4-7", STAC_HP_DV5),
+	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600,
+		      "HP dv4-7", STAC_HP_DV5),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610,
+		      "HP HDX", STAC_HP_HDX),  /* HDX18 */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a,
-				"unknown HP", STAC_HP_M4),
+		      "HP mini 1000", STAC_HP_M4),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b,
+		      "HP HDX", STAC_HP_HDX),  /* HDX16 */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
 				"unknown Dell", STAC_DELL_M4_1),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234,
@@ -1961,6 +2018,7 @@
 };
 
 static const char *stac922x_models[STAC_922X_MODELS] = {
+	[STAC_922X_AUTO] = "auto",
 	[STAC_D945_REF]	= "ref",
 	[STAC_D945GTP5]	= "5stack",
 	[STAC_D945GTP3]	= "3stack",
@@ -1988,6 +2046,8 @@
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
 		      "DFI LanParty", STAC_D945_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
+		      "DFI LanParty", STAC_D945_REF),
 	/* Intel 945G based systems */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101,
 		      "Intel D945G", STAC_D945GTP3),
@@ -2041,6 +2101,9 @@
 		      "Intel D945P", STAC_D945GTP3),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707,
 		      "Intel D945P", STAC_D945GTP5),
+	/* other intel */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0204,
+		      "Intel D945", STAC_D945_REF),
 	/* other systems  */
 	/* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */
 	SND_PCI_QUIRK(0x8384, 0x7680,
@@ -2065,31 +2128,7 @@
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7,
 		      "Dell XPS M1210", STAC_922X_DELL_M82),
 	/* ECS/PC Chips boards */
-	SND_PCI_QUIRK(0x1019, 0x2144,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2608,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2633,
-		      "ECS/PC chips P17G/1333", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2811,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2812,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2813,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2814,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2815,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2816,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2817,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2818,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2819,
-		      "ECS/PC chips", STAC_ECS_202),
-	SND_PCI_QUIRK(0x1019, 0x2820,
+	SND_PCI_QUIRK_MASK(0x1019, 0xf000, 0x2000,
 		      "ECS/PC chips", STAC_ECS_202),
 	{} /* terminator */
 };
@@ -2132,6 +2171,7 @@
 };
 
 static const char *stac927x_models[STAC_927X_MODELS] = {
+	[STAC_927X_AUTO]	= "auto",
 	[STAC_D965_REF_NO_JD]	= "ref-no-jd",
 	[STAC_D965_REF]		= "ref",
 	[STAC_D965_3ST]		= "3stack",
@@ -2144,26 +2184,16 @@
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
 		      "DFI LanParty", STAC_D965_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
+		      "DFI LanParty", STAC_D965_REF),
 	 /* Intel 946 based systems */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST),
 	/* 965 based 3 stack systems */
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2116, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2115, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2114, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2113, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2112, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2111, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2110, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2009, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2008, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2007, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2006, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2005, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2004, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2100,
+			   "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000,
+			   "Intel D965", STAC_D965_3ST),
 	/* Dell 3 stack systems */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f7, "Dell XPS M1730", STAC_DELL_3ST),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01dd, "Dell Dimension E520", STAC_DELL_3ST),
@@ -2179,15 +2209,10 @@
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x02ff, "Dell     ", STAC_DELL_BIOS),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0209, "Dell XPS 1330", STAC_DELL_BIOS),
 	/* 965 based 5 stack systems */
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2304, "Intel D965", STAC_D965_5ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2305, "Intel D965", STAC_D965_5ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2501, "Intel D965", STAC_D965_5ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2502, "Intel D965", STAC_D965_5ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2503, "Intel D965", STAC_D965_5ST),
-	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2504, "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2300,
+			   "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500,
+			   "Intel D965", STAC_D965_5ST),
 	{} /* terminator */
 };
 
@@ -2240,19 +2265,25 @@
 	[STAC_9205_DELL_M42] = dell_9205_m42_pin_configs,
 	[STAC_9205_DELL_M43] = dell_9205_m43_pin_configs,
 	[STAC_9205_DELL_M44] = dell_9205_m44_pin_configs,
+	[STAC_9205_EAPD] = NULL,
 };
 
 static const char *stac9205_models[STAC_9205_MODELS] = {
+	[STAC_9205_AUTO] = "auto",
 	[STAC_9205_REF] = "ref",
 	[STAC_9205_DELL_M42] = "dell-m42",
 	[STAC_9205_DELL_M43] = "dell-m43",
 	[STAC_9205_DELL_M44] = "dell-m44",
+	[STAC_9205_EAPD] = "eapd",
 };
 
 static struct snd_pci_quirk stac9205_cfg_tbl[] = {
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
 		      "DFI LanParty", STAC_9205_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
+		      "DFI LanParty", STAC_9205_REF),
+	/* Dell */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
 		      "unknown Dell", STAC_9205_DELL_M42),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2,
@@ -2283,101 +2314,24 @@
 		      "Dell Inspiron", STAC_9205_DELL_M44),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
 		      "Dell Vostro 1500", STAC_9205_DELL_M42),
+	/* Gateway */
+	SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
 	{} /* terminator */
 };
 
-static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
-{
-	int i;
-	struct sigmatel_spec *spec = codec->spec;
-	
-	kfree(spec->pin_configs);
-	spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs),
-				    GFP_KERNEL);
-	if (!spec->pin_configs)
-		return -ENOMEM;
-	
-	for (i = 0; i < spec->num_pins; i++) {
-		hda_nid_t nid = spec->pin_nids[i];
-		unsigned int pin_cfg;
-		
-		pin_cfg = snd_hda_codec_read(codec, nid, 0, 
-			AC_VERB_GET_CONFIG_DEFAULT, 0x00);	
-		snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n",
-					nid, pin_cfg);
-		spec->pin_configs[i] = pin_cfg;
-	}
-	
-	return 0;
-}
-
-static void stac92xx_set_config_reg(struct hda_codec *codec,
-				    hda_nid_t pin_nid, unsigned int pin_config)
-{
-	int i;
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
-			    pin_config & 0x000000ff);
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
-			    (pin_config & 0x0000ff00) >> 8);
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
-			    (pin_config & 0x00ff0000) >> 16);
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
-			    pin_config >> 24);
-	i = snd_hda_codec_read(codec, pin_nid, 0,
-			       AC_VERB_GET_CONFIG_DEFAULT,
-			       0x00);	
-	snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n",
-		    pin_nid, i);
-}
-
-static void stac92xx_set_config_regs(struct hda_codec *codec)
+static void stac92xx_set_config_regs(struct hda_codec *codec,
+				     unsigned int *pincfgs)
 {
 	int i;
 	struct sigmatel_spec *spec = codec->spec;
 
- 	if (!spec->pin_configs)
- 		return;
+	if (!pincfgs)
+		return;
 
 	for (i = 0; i < spec->num_pins; i++)
-		stac92xx_set_config_reg(codec, spec->pin_nids[i],
-					spec->pin_configs[i]);
-}
-
-static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins)
-{
-	struct sigmatel_spec *spec = codec->spec;
-
-	if (!pins)
-		return stac92xx_save_bios_config_regs(codec);
-
-	kfree(spec->pin_configs);
-	spec->pin_configs = kmemdup(pins,
-				    spec->num_pins * sizeof(*pins),
-				    GFP_KERNEL);
-	if (!spec->pin_configs)
-		return -ENOMEM;
-
-	stac92xx_set_config_regs(codec);
-	return 0;
-}
-
-static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid,
-				   unsigned int cfg)
-{
-	struct sigmatel_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < spec->num_pins; i++) {
-		if (spec->pin_nids[i] == nid) {
-			spec->pin_configs[i] = cfg;
-			stac92xx_set_config_reg(codec, nid, cfg);
-			break;
-		}
-	}
+		if (spec->pin_nids[i] && pincfgs[i])
+			snd_hda_codec_set_pincfg(codec, spec->pin_nids[i],
+						 pincfgs[i]);
 }
 
 /*
@@ -2567,7 +2521,7 @@
 		codec->num_pcms++;
 		info++;
 		info->name = "STAC92xx Digital";
-		info->pcm_type = HDA_PCM_TYPE_SPDIF;
+		info->pcm_type = spec->autocfg.dig_out_type[0];
 		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;
@@ -2583,8 +2537,7 @@
 
 static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)
 {
-	unsigned int pincap = snd_hda_param_read(codec, nid,
-						 AC_PAR_PIN_CAP);
+	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
 	if (pincap & AC_PINCAP_VREF_100)
 		return AC_PINCTL_VREF_100;
@@ -2759,22 +2712,37 @@
 };
 
 /* add dynamic controls */
-static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
-				     struct snd_kcontrol_new *ktemp,
-				     int idx, const char *name,
-				     unsigned long val)
+static struct snd_kcontrol_new *
+stac_control_new(struct sigmatel_spec *spec,
+		 struct snd_kcontrol_new *ktemp,
+		 const char *name)
 {
 	struct snd_kcontrol_new *knew;
 
 	snd_array_init(&spec->kctls, sizeof(*knew), 32);
 	knew = snd_array_new(&spec->kctls);
 	if (!knew)
-		return -ENOMEM;
+		return NULL;
 	*knew = *ktemp;
-	knew->index = idx;
 	knew->name = kstrdup(name, GFP_KERNEL);
-	if (!knew->name)
+	if (!knew->name) {
+		/* roolback */
+		memset(knew, 0, sizeof(*knew));
+		spec->kctls.alloced--;
+		return NULL;
+	}
+	return knew;
+}
+
+static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
+				     struct snd_kcontrol_new *ktemp,
+				     int idx, const char *name,
+				     unsigned long val)
+{
+	struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name);
+	if (!knew)
 		return -ENOMEM;
+	knew->index = idx;
 	knew->private_value = val;
 	return 0;
 }
@@ -2796,6 +2764,29 @@
 	return stac92xx_add_control_idx(spec, type, 0, name, val);
 }
 
+static struct snd_kcontrol_new stac_input_src_temp = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Input Source",
+	.info = stac92xx_mux_enum_info,
+	.get = stac92xx_mux_enum_get,
+	.put = stac92xx_mux_enum_put,
+};
+
+static int stac92xx_add_input_source(struct sigmatel_spec *spec)
+{
+	struct snd_kcontrol_new *knew;
+	struct hda_input_mux *imux = &spec->private_imux;
+
+	if (!spec->num_adcs || imux->num_items <= 1)
+		return 0; /* no need for input source control */
+	knew = stac_control_new(spec, &stac_input_src_temp,
+				stac_input_src_temp.name);
+	if (!knew)
+		return -ENOMEM;
+	knew->count = spec->num_adcs;
+	return 0;
+}
+
 /* check whether the line-input can be used as line-out */
 static hda_nid_t check_line_out_switch(struct hda_codec *codec)
 {
@@ -2807,7 +2798,7 @@
 	if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
 		return 0;
 	nid = cfg->input_pins[AUTO_PIN_LINE];
-	pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+	pincap = snd_hda_query_pin_caps(codec, nid);
 	if (pincap & AC_PINCAP_OUT)
 		return nid;
 	return 0;
@@ -2826,12 +2817,11 @@
 	mic_pin = AUTO_PIN_MIC;
 	for (;;) {
 		hda_nid_t nid = cfg->input_pins[mic_pin];
-		def_conf = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_CONFIG_DEFAULT, 0);
+		def_conf = snd_hda_codec_get_pincfg(codec, nid);
 		/* 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) {
-			pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+			pincap = snd_hda_query_pin_caps(codec, nid);
 			if (pincap & AC_PINCAP_OUT)
 				return nid;
 		}
@@ -2879,8 +2869,7 @@
 	conn_len = snd_hda_get_connections(codec, nid, conn,
 					   HDA_MAX_CONNECTIONS);
 	for (j = 0; j < conn_len; j++) {
-		wcaps = snd_hda_param_read(codec, conn[j],
-					   AC_PAR_AUDIO_WIDGET_CAP);
+		wcaps = get_wcaps(codec, conn[j]);
 		wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 		/* we check only analog outputs */
 		if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL))
@@ -2895,6 +2884,16 @@
 			return conn[j];
 		}
 	}
+	/* if all DACs are already assigned, connect to the primary DAC */
+	if (conn_len > 1) {
+		for (j = 0; j < conn_len; j++) {
+			if (conn[j] == spec->multiout.dac_nids[0]) {
+				snd_hda_codec_write_cache(codec, nid, 0,
+						  AC_VERB_SET_CONNECT_SEL, j);
+				break;
+			}
+		}
+	}
 	return 0;
 }
 
@@ -2935,6 +2934,26 @@
 		add_spec_dacs(spec, dac);
 	}
 
+	for (i = 0; i < cfg->hp_outs; i++) {
+		nid = cfg->hp_pins[i];
+		dac = get_unassigned_dac(codec, nid);
+		if (dac) {
+			if (!spec->multiout.hp_nid)
+				spec->multiout.hp_nid = dac;
+			else
+				add_spec_extra_dacs(spec, dac);
+		}
+		spec->hp_dacs[i] = dac;
+	}
+
+	for (i = 0; i < cfg->speaker_outs; i++) {
+		nid = cfg->speaker_pins[i];
+		dac = get_unassigned_dac(codec, nid);
+		if (dac)
+			add_spec_extra_dacs(spec, dac);
+		spec->speaker_dacs[i] = dac;
+	}
+
 	/* add line-in as output */
 	nid = check_line_out_switch(codec);
 	if (nid) {
@@ -2962,26 +2981,6 @@
 		}
 	}
 
-	for (i = 0; i < cfg->hp_outs; i++) {
-		nid = cfg->hp_pins[i];
-		dac = get_unassigned_dac(codec, nid);
-		if (dac) {
-			if (!spec->multiout.hp_nid)
-				spec->multiout.hp_nid = dac;
-			else
-				add_spec_extra_dacs(spec, dac);
-		}
-		spec->hp_dacs[i] = dac;
-	}
-
-	for (i = 0; i < cfg->speaker_outs; i++) {
-		nid = cfg->speaker_pins[i];
-		dac = get_unassigned_dac(codec, nid);
-		if (dac)
-			add_spec_extra_dacs(spec, dac);
-		spec->speaker_dacs[i] = dac;
-	}
-
 	snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
 		   spec->multiout.num_dacs,
 		   spec->multiout.dac_nids[0],
@@ -2994,24 +2993,47 @@
 }
 
 /* create volume control/switch for the given prefx type */
-static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs)
+static int create_controls_idx(struct hda_codec *codec, const char *pfx,
+			       int idx, hda_nid_t nid, int chs)
 {
+	struct sigmatel_spec *spec = codec->spec;
 	char name[32];
 	int err;
 
+	if (!spec->check_volume_offset) {
+		unsigned int caps, step, nums, db_scale;
+		caps = query_amp_caps(codec, nid, HDA_OUTPUT);
+		step = (caps & AC_AMPCAP_STEP_SIZE) >>
+			AC_AMPCAP_STEP_SIZE_SHIFT;
+		step = (step + 1) * 25; /* in .01dB unit */
+		nums = (caps & AC_AMPCAP_NUM_STEPS) >>
+			AC_AMPCAP_NUM_STEPS_SHIFT;
+		db_scale = nums * step;
+		/* if dB scale is over -64dB, and finer enough,
+		 * let's reduce it to half
+		 */
+		if (db_scale > 6400 && nums >= 0x1f)
+			spec->volume_offset = nums / 2;
+		spec->check_volume_offset = 1;
+	}
+
 	sprintf(name, "%s Playback Volume", pfx);
-	err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name,
-				   HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
+	err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_VOL, idx, name,
+		HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT,
+					spec->volume_offset));
 	if (err < 0)
 		return err;
 	sprintf(name, "%s Playback Switch", pfx);
-	err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name,
+	err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_MUTE, idx, name,
 				   HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
 	if (err < 0)
 		return err;
 	return 0;
 }
 
+#define create_controls(codec, pfx, nid, chs) \
+	create_controls_idx(codec, pfx, 0, nid, chs)
+
 static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
 {
 	if (spec->multiout.num_dacs > 4) {
@@ -3037,40 +3059,32 @@
 	return 1;
 }
 
-static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid)
-{
-	int i;
-
-	if (spec->autocfg.line_outs != 1)
-		return 0;
-	if (spec->multiout.hp_nid == nid)
-		return 0;
-	for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++)
-		if (spec->multiout.extra_out_nid[i] == nid)
-			return 0;
-	return 1;
-}
-
-/* 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)
+/* Create output controls
+ * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT)
+ */
+static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
+				 const hda_nid_t *pins,
+				 const hda_nid_t *dac_nids,
+				 int type)
 {
 	struct sigmatel_spec *spec = codec->spec;
 	static const char *chname[4] = {
 		"Front", "Surround", NULL /*CLFE*/, "Side"
 	};
-	hda_nid_t nid = 0;
+	hda_nid_t nid;
 	int i, err;
 	unsigned int wid_caps;
 
-	for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) {
-		nid = spec->multiout.dac_nids[i];
-		if (i == 2) {
+	for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) {
+		nid = dac_nids[i];
+		if (!nid)
+			continue;
+		if (type != AUTO_PIN_HP_OUT && i == 2) {
 			/* Center/LFE */
-			err = create_controls(spec, "Center", nid, 1);
+			err = create_controls(codec, "Center", nid, 1);
 			if (err < 0)
 				return err;
-			err = create_controls(spec, "LFE", nid, 2);
+			err = create_controls(codec, "LFE", nid, 2);
 			if (err < 0)
 				return err;
 
@@ -3086,23 +3100,47 @@
 			}
 
 		} else {
-			const char *name = chname[i];
-			/* if it's a single DAC, assign a better name */
-			if (!i && is_unique_dac(spec, nid)) {
-				switch (cfg->line_out_type) {
-				case AUTO_PIN_HP_OUT:
-					name = "Headphone";
-					break;
-				case AUTO_PIN_SPEAKER_OUT:
-					name = "Speaker";
-					break;
-				}
+			const char *name;
+			int idx;
+			switch (type) {
+			case AUTO_PIN_HP_OUT:
+				name = "Headphone";
+				idx = i;
+				break;
+			case AUTO_PIN_SPEAKER_OUT:
+				name = "Speaker";
+				idx = i;
+				break;
+			default:
+				name = chname[i];
+				idx = 0;
+				break;
 			}
-			err = create_controls(spec, name, nid, 3);
+			err = create_controls_idx(codec, name, idx, nid, 3);
 			if (err < 0)
 				return err;
+			if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) {
+				wid_caps = get_wcaps(codec, pins[i]);
+				if (wid_caps & AC_WCAP_UNSOL_CAP)
+					spec->hp_detect = 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)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	int err;
+
+	err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins,
+				    spec->multiout.dac_nids,
+				    cfg->line_out_type);
+	if (err < 0)
+		return err;
 
 	if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) {
 		err = stac92xx_add_control(spec,
@@ -3137,40 +3175,18 @@
 					struct auto_pin_cfg *cfg)
 {
 	struct sigmatel_spec *spec = codec->spec;
-	hda_nid_t nid;
-	int i, err, nums;
+	int err;
 
-	nums = 0;
-	for (i = 0; i < cfg->hp_outs; i++) {
-		static const char *pfxs[] = {
-			"Headphone", "Headphone2", "Headphone3",
-		};
-		unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]);
-		if (wid_caps & AC_WCAP_UNSOL_CAP)
-			spec->hp_detect = 1;
-		if (nums >= ARRAY_SIZE(pfxs))
-			continue;
-		nid = spec->hp_dacs[i];
-		if (!nid)
-			continue;
-		err = create_controls(spec, pfxs[nums++], nid, 3);
-		if (err < 0)
-			return err;
-	}
-	nums = 0;
-	for (i = 0; i < cfg->speaker_outs; i++) {
-		static const char *pfxs[] = {
-			"Speaker", "External Speaker", "Speaker2",
-		};
-		if (nums >= ARRAY_SIZE(pfxs))
-			continue;
-		nid = spec->speaker_dacs[i];
-		if (!nid)
-			continue;
-		err = create_controls(spec, pfxs[nums++], nid, 3);
-		if (err < 0)
-			return err;
-	}
+	err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins,
+				    spec->hp_dacs, AUTO_PIN_HP_OUT);
+	if (err < 0)
+		return err;
+
+	err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins,
+				    spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT);
+	if (err < 0)
+		return err;
+
 	return 0;
 }
 
@@ -3379,11 +3395,7 @@
 		unsigned int wcaps;
 		unsigned int def_conf;
 
-		def_conf = snd_hda_codec_read(codec,
-					      spec->dmic_nids[i],
-					      0,
-					      AC_VERB_GET_CONFIG_DEFAULT,
-					      0);
+		def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]);
 		if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
 			continue;
 
@@ -3507,6 +3519,7 @@
 static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
 {
 	struct sigmatel_spec *spec = codec->spec;
+	int hp_swap = 0;
 	int err;
 
 	if ((err = snd_hda_parse_pin_def_config(codec,
@@ -3534,6 +3547,7 @@
 		spec->autocfg.line_outs = spec->autocfg.hp_outs;
 		spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
 		spec->autocfg.hp_outs = 0;
+		hp_swap = 1;
 	}
 	if (spec->autocfg.mono_out_pin) {
 		int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) &
@@ -3627,12 +3641,19 @@
 #endif
 
 	err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg);
-
 	if (err < 0)
 		return err;
 
-	err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
+	/* All output parsing done, now restore the swapped hp pins */
+	if (hp_swap) {
+		memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins,
+		       sizeof(spec->autocfg.hp_pins));
+		spec->autocfg.hp_outs = spec->autocfg.line_outs;
+		spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
+		spec->autocfg.line_outs = 0;
+	}
 
+	err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
 	if (err < 0)
 		return err;
 
@@ -3661,11 +3682,15 @@
 			return err;
 	}
 
+	err = stac92xx_add_input_source(spec);
+	if (err < 0)
+		return err;
+
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 	if (spec->multiout.max_channels > 2)
 		spec->surr_switch = 1;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = dig_out;
 	if (dig_in && spec->autocfg.dig_in_pin)
 		spec->dig_in_nid = dig_in;
@@ -3728,9 +3753,7 @@
 		for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {
 			hda_nid_t pin = spec->autocfg.line_out_pins[i];
 			unsigned int defcfg;
-			defcfg = snd_hda_codec_read(codec, pin, 0,
-						 AC_VERB_GET_CONFIG_DEFAULT,
-						 0x00);
+			defcfg = snd_hda_codec_get_pincfg(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);
@@ -3743,7 +3766,7 @@
 	}
 
 	if (lfe_pin) {
-		err = create_controls(spec, "LFE", lfe_pin, 1);
+		err = create_controls(codec, "LFE", lfe_pin, 1);
 		if (err < 0)
 			return err;
 	}
@@ -3774,7 +3797,11 @@
 			return err;
 	}
 
-	if (spec->autocfg.dig_out_pin)
+	err = stac92xx_add_input_source(spec);
+	if (err < 0)
+		return err;
+
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = 0x05;
 	if (spec->autocfg.dig_in_pin)
 		spec->dig_in_nid = 0x04;
@@ -3830,8 +3857,7 @@
 #ifdef CONFIG_SND_JACK
 	struct sigmatel_spec *spec = codec->spec;
 	struct sigmatel_jack *jack;
-	int def_conf = snd_hda_codec_read(codec, nid,
-			0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+	int def_conf = snd_hda_codec_get_pincfg(codec, nid);
 	int connectivity = get_defcfg_connect(def_conf);
 	char name[32];
 
@@ -3946,6 +3972,36 @@
 static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
 				  int enable);
 
+/* override some hints from the hwdep entry */
+static void stac_store_hints(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	const char *p;
+	int val;
+
+	val = snd_hda_get_bool_hint(codec, "hp_detect");
+	if (val >= 0)
+		spec->hp_detect = val;
+	p = snd_hda_get_hint(codec, "gpio_mask");
+	if (p) {
+		spec->gpio_mask = simple_strtoul(p, NULL, 0);
+		spec->eapd_mask = spec->gpio_dir = spec->gpio_data =
+			spec->gpio_mask;
+	}
+	p = snd_hda_get_hint(codec, "gpio_dir");
+	if (p)
+		spec->gpio_dir = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
+	p = snd_hda_get_hint(codec, "gpio_data");
+	if (p)
+		spec->gpio_data = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
+	p = snd_hda_get_hint(codec, "eapd_mask");
+	if (p)
+		spec->eapd_mask = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
+	val = snd_hda_get_bool_hint(codec, "eapd_switch");
+	if (val >= 0)
+		spec->eapd_switch = val;
+}
+
 static int stac92xx_init(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
@@ -3962,6 +4018,9 @@
 				spec->adc_nids[i], 0,
 				AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
 
+	/* override some hints */
+	stac_store_hints(codec);
+
 	/* set up GPIO */
 	gpio = spec->gpio_data;
 	/* turn on EAPD statically when spec->eapd_switch isn't set.
@@ -4011,8 +4070,7 @@
 								 pinctl);
 				}
 			}
-			conf = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_CONFIG_DEFAULT, 0);
+			conf = snd_hda_codec_get_pincfg(codec, nid);
 			if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
 				enable_pin_detect(codec, nid,
 						  STAC_INSERT_EVENT);
@@ -4024,8 +4082,8 @@
 	for (i = 0; i < spec->num_dmics; i++)
 		stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
 					AC_PINCTL_IN_EN);
-	if (cfg->dig_out_pin)
-		stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
+	if (cfg->dig_out_pins[0])
+		stac92xx_auto_set_pinctl(codec, cfg->dig_out_pins[0],
 					 AC_PINCTL_OUT_EN);
 	if (cfg->dig_in_pin)
 		stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
@@ -4053,8 +4111,7 @@
 			stac_toggle_power_map(codec, nid, 1);
 			continue;
 		}
-		def_conf = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_CONFIG_DEFAULT, 0);
+		def_conf = snd_hda_codec_get_pincfg(codec, nid);
 		def_conf = get_defcfg_connect(def_conf);
 		/* skip any ports that don't have jacks since presence
  		 * detection is useless */
@@ -4108,7 +4165,6 @@
 	if (! spec)
 		return;
 
-	kfree(spec->pin_configs);
 	stac92xx_free_jacks(codec);
 	snd_array_free(&spec->events);
 
@@ -4119,7 +4175,9 @@
 static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
 				unsigned int flag)
 {
-	unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
+	unsigned int old_ctl, pin_ctl;
+
+	pin_ctl = snd_hda_codec_read(codec, nid,
 			0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
 
 	if (pin_ctl & AC_PINCTL_IN_EN) {
@@ -4133,14 +4191,17 @@
 			return;
 	}
 
+	old_ctl = pin_ctl;
 	/* if setting pin direction bits, clear the current
 	   direction bits first */
 	if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))
 		pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
 	
-	snd_hda_codec_write_cache(codec, nid, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL,
-			pin_ctl | flag);
+	pin_ctl |= flag;
+	if (old_ctl != pin_ctl)
+		snd_hda_codec_write_cache(codec, nid, 0,
+					  AC_VERB_SET_PIN_WIDGET_CONTROL,
+					  pin_ctl);
 }
 
 static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
@@ -4148,9 +4209,10 @@
 {
 	unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
 			0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
-	snd_hda_codec_write_cache(codec, nid, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL,
-			pin_ctl & ~flag);
+	if (pin_ctl & flag)
+		snd_hda_codec_write_cache(codec, nid, 0,
+					  AC_VERB_SET_PIN_WIDGET_CONTROL,
+					  pin_ctl & ~flag);
 }
 
 static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
@@ -4413,7 +4475,6 @@
 {
 	struct sigmatel_spec *spec = codec->spec;
 
-	stac92xx_set_config_regs(codec);
 	stac92xx_init(codec);
 	snd_hda_codec_resume_amp(codec);
 	snd_hda_codec_resume_cache(codec);
@@ -4424,6 +4485,37 @@
 	return 0;
 }
 
+
+/*
+ * using power check for controlling mute led of HP HDX notebooks
+ * check for mute state only on Speakers (nid = 0x10)
+ *
+ * For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise
+ * the LED is NOT working properly !
+ */
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int stac92xx_hp_hdx_check_power_status(struct hda_codec *codec,
+					      hda_nid_t nid)
+{
+	struct sigmatel_spec *spec = codec->spec;
+
+	if (nid == 0x10) {
+		if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
+		    HDA_AMP_MUTE)
+			spec->gpio_data &= ~0x08;  /* orange */
+		else
+			spec->gpio_data |= 0x08;   /* white */
+
+		stac_gpio_set(codec, spec->gpio_mask,
+			      spec->gpio_dir,
+			      spec->gpio_data);
+	}
+
+	return 0;
+}
+#endif
+
 static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
 {
 	struct sigmatel_spec *spec = codec->spec;
@@ -4462,16 +4554,11 @@
 	spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
 							stac9200_models,
 							stac9200_cfg_tbl);
-	if (spec->board_config < 0) {
+	if (spec->board_config < 0)
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
-		err = stac92xx_save_bios_config_regs(codec);
-	} else
-		err = stac_save_pin_cfgs(codec,
+	else
+		stac92xx_set_config_regs(codec,
 					 stac9200_brd_tbl[spec->board_config]);
-	if (err < 0) {
-		stac92xx_free(codec);
-		return err;
-	}
 
 	spec->multiout.max_channels = 2;
 	spec->multiout.num_dacs = 1;
@@ -4539,17 +4626,12 @@
 							stac925x_models,
 							stac925x_cfg_tbl);
  again:
-	if (spec->board_config < 0) {
+	if (spec->board_config < 0)
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"
 				      "using BIOS defaults\n");
-		err = stac92xx_save_bios_config_regs(codec);
-	} else
-		err = stac_save_pin_cfgs(codec,
+	else
+		stac92xx_set_config_regs(codec,
 					 stac925x_brd_tbl[spec->board_config]);
-	if (err < 0) {
-		stac92xx_free(codec);
-		return err;
-	}
 
 	spec->multiout.max_channels = 2;
 	spec->multiout.num_dacs = 1;
@@ -4627,17 +4709,12 @@
 							stac92hd73xx_models,
 							stac92hd73xx_cfg_tbl);
 again:
-	if (spec->board_config < 0) {
+	if (spec->board_config < 0)
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for"
 			" STAC92HD73XX, using BIOS defaults\n");
-		err = stac92xx_save_bios_config_regs(codec);
-	} else
-		err = stac_save_pin_cfgs(codec,
+	else
+		stac92xx_set_config_regs(codec,
 				stac92hd73xx_brd_tbl[spec->board_config]);
-	if (err < 0) {
-		stac92xx_free(codec);
-		return err;
-	}
 
 	num_dacs = snd_hda_get_connections(codec, 0x0a,
 			conn, STAC92HD73_DAC_COUNT + 2) - 1;
@@ -4651,14 +4728,18 @@
 	case 0x3: /* 6 Channel */
 		spec->mixer = stac92hd73xx_6ch_mixer;
 		spec->init = stac92hd73xx_6ch_core_init;
+		spec->aloopback_ctl = stac92hd73xx_6ch_loopback;
 		break;
 	case 0x4: /* 8 Channel */
 		spec->mixer = stac92hd73xx_8ch_mixer;
 		spec->init = stac92hd73xx_8ch_core_init;
+		spec->aloopback_ctl = stac92hd73xx_8ch_loopback;
 		break;
 	case 0x5: /* 10 Channel */
 		spec->mixer = stac92hd73xx_10ch_mixer;
 		spec->init = stac92hd73xx_10ch_core_init;
+		spec->aloopback_ctl = stac92hd73xx_10ch_loopback;
+		break;
 	}
 	spec->multiout.dac_nids = spec->dac_nids;
 
@@ -4697,18 +4778,18 @@
 			spec->init = dell_m6_core_init;
 		switch (spec->board_config) {
 		case STAC_DELL_M6_AMIC: /* Analog Mics */
-			stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
+			snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170);
 			spec->num_dmics = 0;
 			spec->private_dimux.num_items = 1;
 			break;
 		case STAC_DELL_M6_DMIC: /* Digital Mics */
-			stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+			snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160);
 			spec->num_dmics = 1;
 			spec->private_dimux.num_items = 2;
 			break;
 		case STAC_DELL_M6_BOTH: /* Both */
-			stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
-			stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+			snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170);
+			snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160);
 			spec->num_dmics = 1;
 			spec->private_dimux.num_items = 2;
 			break;
@@ -4771,6 +4852,7 @@
 	hda_nid_t conn[STAC92HD83_DAC_COUNT + 1];
 	int err;
 	int num_dacs;
+	hda_nid_t nid;
 
 	spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -4789,15 +4871,6 @@
 	spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
 	spec->multiout.dac_nids = spec->dac_nids;
 
-
-	/* set port 0xe to select the last DAC
-	 */
-	num_dacs = snd_hda_get_connections(codec, 0x0e,
-		conn, STAC92HD83_DAC_COUNT + 1) - 1;
-
-	snd_hda_codec_write_cache(codec, 0xe, 0,
-		AC_VERB_SET_CONNECT_SEL, num_dacs);
-
 	spec->init = stac92hd83xxx_core_init;
 	spec->mixer = stac92hd83xxx_mixer;
 	spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids);
@@ -4812,17 +4885,12 @@
 							stac92hd83xxx_models,
 							stac92hd83xxx_cfg_tbl);
 again:
-	if (spec->board_config < 0) {
+	if (spec->board_config < 0)
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for"
 			" STAC92HD83XXX, using BIOS defaults\n");
-		err = stac92xx_save_bios_config_regs(codec);
-	} else
-		err = stac_save_pin_cfgs(codec,
+	else
+		stac92xx_set_config_regs(codec,
 				stac92hd83xxx_brd_tbl[spec->board_config]);
-	if (err < 0) {
-		stac92xx_free(codec);
-		return err;
-	}
 
 	switch (codec->vendor_id) {
 	case 0x111d7604:
@@ -4849,6 +4917,23 @@
 		return err;
 	}
 
+	switch (spec->board_config) {
+	case STAC_DELL_S14:
+		nid = 0xf;
+		break;
+	default:
+		nid = 0xe;
+		break;
+	}
+
+	num_dacs = snd_hda_get_connections(codec, nid,
+				conn, STAC92HD83_DAC_COUNT + 1) - 1;
+
+	/* set port X to select the last DAC
+	 */
+	snd_hda_codec_write_cache(codec, nid, 0,
+			AC_VERB_SET_CONNECT_SEL, num_dacs);
+
 	codec->patch_ops = stac92xx_patch_ops;
 
 	codec->proc_widget_hook = stac92hd_proc_hook;
@@ -4856,7 +4941,16 @@
 	return 0;
 }
 
-static struct hda_input_mux stac92hd71bxx_dmux = {
+static struct hda_input_mux stac92hd71bxx_dmux_nomixer = {
+	.num_items = 3,
+	.items = {
+		{ "Analog Inputs", 0x00 },
+		{ "Digital Mic 1", 0x02 },
+		{ "Digital Mic 2", 0x03 },
+	}
+};
+
+static struct hda_input_mux stac92hd71bxx_dmux_amixer = {
 	.num_items = 4,
 	.items = {
 		{ "Analog Inputs", 0x00 },
@@ -4866,10 +4960,67 @@
 	}
 };
 
+/* get the pin connection (fixed, none, etc) */
+static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	unsigned int cfg;
+
+	cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
+	return get_defcfg_connect(cfg);
+}
+
+static int stac92hd71bxx_connected_ports(struct hda_codec *codec,
+					 hda_nid_t *nids, int num_nids)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	int idx, num;
+	unsigned int def_conf;
+
+	for (num = 0; num < num_nids; num++) {
+		for (idx = 0; idx < spec->num_pins; idx++)
+			if (spec->pin_nids[idx] == nids[num])
+				break;
+		if (idx >= spec->num_pins)
+			break;
+		def_conf = stac_get_defcfg_connect(codec, idx);
+		if (def_conf == AC_JACK_PORT_NONE)
+			break;
+	}
+	return num;
+}
+
+static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec,
+					  hda_nid_t dig0pin)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	int idx;
+
+	for (idx = 0; idx < spec->num_pins; idx++)
+		if (spec->pin_nids[idx] == dig0pin)
+			break;
+	if ((idx + 2) >= spec->num_pins)
+		return 0;
+
+	/* dig1pin case */
+	if (stac_get_defcfg_connect(codec, idx + 1) != AC_JACK_PORT_NONE)
+		return 2;
+
+	/* dig0pin + dig2pin case */
+	if (stac_get_defcfg_connect(codec, idx + 2) != AC_JACK_PORT_NONE)
+		return 2;
+	if (stac_get_defcfg_connect(codec, idx) != AC_JACK_PORT_NONE)
+		return 1;
+	else
+		return 0;
+}
+
 static int patch_stac92hd71bxx(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec;
+	struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init;
 	int err = 0;
+	unsigned int ndmic_nids = 0;
 
 	spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -4877,27 +5028,32 @@
 
 	codec->spec = spec;
 	codec->patch_ops = stac92xx_patch_ops;
-	spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids);
+	spec->num_pins = STAC92HD71BXX_NUM_PINS;
+	switch (codec->vendor_id) {
+	case 0x111d76b6:
+	case 0x111d76b7:
+		spec->pin_nids = stac92hd71bxx_pin_nids_4port;
+		break;
+	case 0x111d7603:
+	case 0x111d7608:
+		/* On 92HD75Bx 0x27 isn't a pin nid */
+		spec->num_pins--;
+		/* fallthrough */
+	default:
+		spec->pin_nids = stac92hd71bxx_pin_nids_6port;
+	}
 	spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
-	spec->pin_nids = stac92hd71bxx_pin_nids;
-	memcpy(&spec->private_dimux, &stac92hd71bxx_dmux,
-			sizeof(stac92hd71bxx_dmux));
 	spec->board_config = snd_hda_check_board_config(codec,
 							STAC_92HD71BXX_MODELS,
 							stac92hd71bxx_models,
 							stac92hd71bxx_cfg_tbl);
 again:
-	if (spec->board_config < 0) {
+	if (spec->board_config < 0)
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for"
 			" STAC92HD71BXX, using BIOS defaults\n");
-		err = stac92xx_save_bios_config_regs(codec);
-	} else
-		err = stac_save_pin_cfgs(codec,
+	else
+		stac92xx_set_config_regs(codec,
 				stac92hd71bxx_brd_tbl[spec->board_config]);
-	if (err < 0) {
-		stac92xx_free(codec);
-		return err;
-	}
 
 	if (spec->board_config > STAC_92HD71BXX_REF) {
 		/* GPIO0 = EAPD */
@@ -4906,16 +5062,34 @@
 		spec->gpio_data = 0x01;
 	}
 
+	spec->dmic_nids = stac92hd71bxx_dmic_nids;
+	spec->dmux_nids = stac92hd71bxx_dmux_nids;
+
 	switch (codec->vendor_id) {
 	case 0x111d76b6: /* 4 Port without Analog Mixer */
 	case 0x111d76b7:
+		unmute_init++;
+		/* fallthru */
 	case 0x111d76b4: /* 6 Port without Analog Mixer */
 	case 0x111d76b5:
+		memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer,
+		       sizeof(stac92hd71bxx_dmux_nomixer));
 		spec->mixer = stac92hd71bxx_mixer;
 		spec->init = stac92hd71bxx_core_init;
 		codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
+		spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+					stac92hd71bxx_dmic_nids,
+					STAC92HD71BXX_NUM_DMICS);
+		if (spec->num_dmics) {
+			spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+			spec->dinput_mux = &spec->private_dimux;
+			ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1;
+		}
 		break;
 	case 0x111d7608: /* 5 Port with Analog Mixer */
+		memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
+		       sizeof(stac92hd71bxx_dmux_amixer));
+		spec->private_dimux.num_items--;
 		switch (spec->board_config) {
 		case STAC_HP_M4:
 			/* Enable VREF power saving on GPIO1 detect */
@@ -4942,7 +5116,15 @@
 
 		/* disable VSW */
 		spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
-		stac_change_pin_config(codec, 0xf, 0x40f000f0);
+		unmute_init++;
+		snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
+		snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
+		stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0;
+		spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+					stac92hd71bxx_dmic_nids,
+					STAC92HD71BXX_NUM_DMICS - 1);
+		spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+		ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2;
 		break;
 	case 0x111d7603: /* 6 Port with Analog Mixer */
 		if ((codec->revision_id & 0xf) == 1)
@@ -4952,12 +5134,23 @@
 		spec->num_pwrs = 0;
 		/* fallthru */
 	default:
+		memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
+		       sizeof(stac92hd71bxx_dmux_amixer));
 		spec->dinput_mux = &spec->private_dimux;
 		spec->mixer = stac92hd71bxx_analog_mixer;
 		spec->init = stac92hd71bxx_analog_core_init;
 		codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
+		spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+					stac92hd71bxx_dmic_nids,
+					STAC92HD71BXX_NUM_DMICS);
+		spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+		ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1;
 	}
 
+	if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)
+		snd_hda_sequence_write_cache(codec, unmute_init);
+
+	spec->aloopback_ctl = stac92hd71bxx_loopback;
 	spec->aloopback_mask = 0x50;
 	spec->aloopback_shift = 0;
 
@@ -4965,18 +5158,17 @@
 	spec->digbeep_nid = 0x26;
 	spec->mux_nids = stac92hd71bxx_mux_nids;
 	spec->adc_nids = stac92hd71bxx_adc_nids;
-	spec->dmic_nids = stac92hd71bxx_dmic_nids;
-	spec->dmux_nids = stac92hd71bxx_dmux_nids;
 	spec->smux_nids = stac92hd71bxx_smux_nids;
 	spec->pwr_nids = stac92hd71bxx_pwr_nids;
 
 	spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids);
 	spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids);
+	spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e);
 
 	switch (spec->board_config) {
 	case STAC_HP_M4:
 		/* enable internal microphone */
-		stac_change_pin_config(codec, 0x0e, 0x01813040);
+		snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040);
 		stac92xx_auto_set_pinctl(codec, 0x0e,
 			AC_PINCTL_IN_EN | AC_PINCTL_VREF_80);
 		/* fallthru */
@@ -4991,19 +5183,36 @@
 		spec->num_smuxes = 0;
 		spec->num_dmuxes = 1;
 		break;
-	default:
-		spec->num_dmics = STAC92HD71BXX_NUM_DMICS;
-		spec->num_smuxes = ARRAY_SIZE(stac92hd71bxx_smux_nids);
-		spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+	case STAC_HP_DV5:
+		snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010);
+		stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN);
+		break;
+	case STAC_HP_HDX:
+		spec->num_dmics = 1;
+		spec->num_dmuxes = 1;
+		spec->num_smuxes = 1;
+		/*
+		 * For controlling MUTE LED on HP HDX16/HDX18 notebooks,
+		 * the CONFIG_SND_HDA_POWER_SAVE is needed to be set.
+		 */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+		/* orange/white mute led on GPIO3, orange=0, white=1 */
+		spec->gpio_mask |= 0x08;
+		spec->gpio_dir  |= 0x08;
+		spec->gpio_data |= 0x08;  /* set to white */
+
+		/* register check_power_status callback. */
+		codec->patch_ops.check_power_status =
+		    stac92xx_hp_hdx_check_power_status;
+#endif	
+		break;
 	};
 
 	spec->multiout.dac_nids = spec->dac_nids;
 	if (spec->dinput_mux)
-		spec->private_dimux.num_items +=
-			spec->num_dmics -
-				(ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1);
+		spec->private_dimux.num_items += spec->num_dmics - ndmic_nids;
 
-	err = stac92xx_parse_auto_config(codec, 0x21, 0x23);
+	err = stac92xx_parse_auto_config(codec, 0x21, 0);
 	if (!err) {
 		if (spec->board_config < 0) {
 			printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -5078,17 +5287,12 @@
 	}
 
  again:
-	if (spec->board_config < 0) {
+	if (spec->board_config < 0)
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
 			"using BIOS defaults\n");
-		err = stac92xx_save_bios_config_regs(codec);
-	} else
-		err = stac_save_pin_cfgs(codec,
+	else
+		stac92xx_set_config_regs(codec,
 				stac922x_brd_tbl[spec->board_config]);
-	if (err < 0) {
-		stac92xx_free(codec);
-		return err;
-	}
 
 	spec->adc_nids = stac922x_adc_nids;
 	spec->mux_nids = stac922x_mux_nids;
@@ -5139,24 +5343,19 @@
 		return -ENOMEM;
 
 	codec->spec = spec;
+	codec->slave_dig_outs = stac927x_slave_dig_outs;
 	spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
 	spec->pin_nids = stac927x_pin_nids;
 	spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
 							stac927x_models,
 							stac927x_cfg_tbl);
  again:
-	if (spec->board_config < 0 || !stac927x_brd_tbl[spec->board_config]) {
-		if (spec->board_config < 0)
-			snd_printdd(KERN_INFO "hda_codec: Unknown model for"
-				    "STAC927x, using BIOS defaults\n");
-		err = stac92xx_save_bios_config_regs(codec);
-	} else
-		err = stac_save_pin_cfgs(codec,
+	if (spec->board_config < 0)
+		snd_printdd(KERN_INFO "hda_codec: Unknown model for"
+			    "STAC927x, using BIOS defaults\n");
+	else
+		stac92xx_set_config_regs(codec,
 				stac927x_brd_tbl[spec->board_config]);
-	if (err < 0) {
-		stac92xx_free(codec);
-		return err;
-	}
 
 	spec->digbeep_nid = 0x23;
 	spec->adc_nids = stac927x_adc_nids;
@@ -5185,15 +5384,15 @@
 		case 0x10280209:
 		case 0x1028022e:
 			/* correct the device field to SPDIF out */
-			stac_change_pin_config(codec, 0x21, 0x01442070);
+			snd_hda_codec_set_pincfg(codec, 0x21, 0x01442070);
 			break;
 		};
 		/* configure the analog microphone on some laptops */
-		stac_change_pin_config(codec, 0x0c, 0x90a79130);
+		snd_hda_codec_set_pincfg(codec, 0x0c, 0x90a79130);
 		/* correct the front output jack as a hp out */
-		stac_change_pin_config(codec, 0x0f, 0x0227011f);
+		snd_hda_codec_set_pincfg(codec, 0x0f, 0x0227011f);
 		/* correct the front input jack as a mic */
-		stac_change_pin_config(codec, 0x0e, 0x02a79130);
+		snd_hda_codec_set_pincfg(codec, 0x0e, 0x02a79130);
 		/* fallthru */
 	case STAC_DELL_3ST:
 		/* GPIO2 High = Enable EAPD */
@@ -5220,6 +5419,7 @@
 	}
 
 	spec->num_pwrs = 0;
+	spec->aloopback_ctl = stac927x_loopback;
 	spec->aloopback_mask = 0x40;
 	spec->aloopback_shift = 0;
 	spec->eapd_switch = 1;
@@ -5278,16 +5478,11 @@
 							stac9205_models,
 							stac9205_cfg_tbl);
  again:
-	if (spec->board_config < 0) {
+	if (spec->board_config < 0)
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
-		err = stac92xx_save_bios_config_regs(codec);
-	} else
-		err = stac_save_pin_cfgs(codec,
+	else
+		stac92xx_set_config_regs(codec,
 					 stac9205_brd_tbl[spec->board_config]);
-	if (err < 0) {
-		stac92xx_free(codec);
-		return err;
-	}
 
 	spec->digbeep_nid = 0x23;
 	spec->adc_nids = stac9205_adc_nids;
@@ -5304,17 +5499,20 @@
 
 	spec->init = stac9205_core_init;
 	spec->mixer = stac9205_mixer;
+	spec->aloopback_ctl = stac9205_loopback;
 
 	spec->aloopback_mask = 0x40;
 	spec->aloopback_shift = 0;
-	spec->eapd_switch = 1;
+	/* Turn on/off EAPD per HP plugging */
+	if (spec->board_config != STAC_9205_EAPD)
+		spec->eapd_switch = 1;
 	spec->multiout.dac_nids = spec->dac_nids;
 	
 	switch (spec->board_config){
 	case STAC_9205_DELL_M43:
 		/* Enable SPDIF in/out */
-		stac_change_pin_config(codec, 0x1f, 0x01441030);
-		stac_change_pin_config(codec, 0x20, 0x1c410030);
+		snd_hda_codec_set_pincfg(codec, 0x1f, 0x01441030);
+		snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030);
 
 		/* Enable unsol response for GPIO4/Dock HP connection */
 		err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
@@ -5371,223 +5569,87 @@
  * STAC9872 hack
  */
 
-/* static config for Sony VAIO FE550G and Sony VAIO AR */
-static hda_nid_t vaio_dacs[] = { 0x2 };
-#define VAIO_HP_DAC	0x5
-static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ };
-static hda_nid_t vaio_mux_nids[] = { 0x15 };
-
-static struct hda_input_mux vaio_mux = {
-	.num_items = 3,
-	.items = {
-		/* { "HP", 0x0 }, */
-		{ "Mic Jack", 0x1 },
-		{ "Internal Mic", 0x2 },
-		{ "PCM", 0x3 },
-	}
-};
-
-static struct hda_verb vaio_init[] = {
-	{0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */
-	{0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT},
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */
-	{0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
-	{0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
+static struct hda_verb stac9872_core_init[] = {
 	{0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
 	{}
 };
 
-static struct hda_verb vaio_ar_init[] = {
-	{0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */
-	{0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
-	{0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
-/*	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
-/*	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
-	{}
-};
-
-static struct snd_kcontrol_new vaio_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
-	/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
+static struct snd_kcontrol_new stac9872_mixer[] = {
 	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.count = 1,
-		.info = stac92xx_mux_enum_info,
-		.get = stac92xx_mux_enum_get,
-		.put = stac92xx_mux_enum_put,
-	},
-	{}
+	{ } /* end */
 };
 
-static struct snd_kcontrol_new vaio_ar_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
-	/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
-	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
-	/*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.count = 1,
-		.info = stac92xx_mux_enum_info,
-		.get = stac92xx_mux_enum_get,
-		.put = stac92xx_mux_enum_put,
-	},
-	{}
+static hda_nid_t stac9872_pin_nids[] = {
+	0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	0x11, 0x13, 0x14,
 };
 
-static struct hda_codec_ops stac9872_patch_ops = {
-	.build_controls = stac92xx_build_controls,
-	.build_pcms = stac92xx_build_pcms,
-	.init = stac92xx_init,
-	.free = stac92xx_free,
-#ifdef SND_HDA_NEEDS_RESUME
-	.resume = stac92xx_resume,
-#endif
+static hda_nid_t stac9872_adc_nids[] = {
+	0x8 /*,0x6*/
 };
 
-static int stac9872_vaio_init(struct hda_codec *codec)
-{
-	int err;
-
-	err = stac92xx_init(codec);
-	if (err < 0)
-		return err;
-	if (codec->patch_ops.unsol_event)
-		codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
-	return 0;
-}
-
-static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res)
-{
-	if (get_pin_presence(codec, 0x0a)) {
-		stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
-		stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
-	} else {
-		stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
-		stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
-	}
-} 
-
-static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	switch (res >> 26) {
-	case STAC_HP_EVENT:
-		stac9872_vaio_hp_detect(codec, res);
-		break;
-	}
-}
-
-static struct hda_codec_ops stac9872_vaio_patch_ops = {
-	.build_controls = stac92xx_build_controls,
-	.build_pcms = stac92xx_build_pcms,
-	.init = stac9872_vaio_init,
-	.free = stac92xx_free,
-	.unsol_event = stac9872_vaio_unsol_event,
-#ifdef CONFIG_PM
-	.resume = stac92xx_resume,
-#endif
+static hda_nid_t stac9872_mux_nids[] = {
+	0x15
 };
 
-enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */
-       CXD9872RD_VAIO,
-       /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */
-       STAC9872AK_VAIO, 
-       /* Unknown. id=0x83847661 and subsys=0x104D1200. */
-       STAC9872K_VAIO,
-       /* AR Series. id=0x83847664 and subsys=104D1300 */
-       CXD9872AKD_VAIO,
-       STAC_9872_MODELS,
+static unsigned int stac9872_vaio_pin_configs[9] = {
+	0x03211020, 0x411111f0, 0x411111f0, 0x03a15030,
+	0x411111f0, 0x90170110, 0x411111f0, 0x411111f0,
+	0x90a7013e
 };
 
 static const char *stac9872_models[STAC_9872_MODELS] = {
-	[CXD9872RD_VAIO]	= "vaio",
-	[CXD9872AKD_VAIO]	= "vaio-ar",
+	[STAC_9872_AUTO] = "auto",
+	[STAC_9872_VAIO] = "vaio",
+};
+
+static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = {
+	[STAC_9872_VAIO] = stac9872_vaio_pin_configs,
 };
 
 static struct snd_pci_quirk stac9872_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO),
-	SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO),
-	SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO),
-	SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO),
-	{}
+	{} /* terminator */
 };
 
 static int patch_stac9872(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec;
-	int board_config;
+	int err;
 
-	board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
-						  stac9872_models,
-						  stac9872_cfg_tbl);
-	if (board_config < 0)
-		/* unknown config, let generic-parser do its job... */
-		return snd_hda_parse_generic_codec(codec);
-	
 	spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
-
 	codec->spec = spec;
-	switch (board_config) {
-	case CXD9872RD_VAIO:
-	case STAC9872AK_VAIO:
-	case STAC9872K_VAIO:
-		spec->mixer = vaio_mixer;
-		spec->init = vaio_init;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs);
-		spec->multiout.dac_nids = vaio_dacs;
-		spec->multiout.hp_nid = VAIO_HP_DAC;
-		spec->num_adcs = ARRAY_SIZE(vaio_adcs);
-		spec->adc_nids = vaio_adcs;
-		spec->num_pwrs = 0;
-		spec->input_mux = &vaio_mux;
-		spec->mux_nids = vaio_mux_nids;
-		codec->patch_ops = stac9872_vaio_patch_ops;
-		break;
-	
-	case CXD9872AKD_VAIO:
-		spec->mixer = vaio_ar_mixer;
-		spec->init = vaio_ar_init;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs);
-		spec->multiout.dac_nids = vaio_dacs;
-		spec->multiout.hp_nid = VAIO_HP_DAC;
-		spec->num_adcs = ARRAY_SIZE(vaio_adcs);
-		spec->num_pwrs = 0;
-		spec->adc_nids = vaio_adcs;
-		spec->input_mux = &vaio_mux;
-		spec->mux_nids = vaio_mux_nids;
-		codec->patch_ops = stac9872_patch_ops;
-		break;
-	}
 
+	spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
+							stac9872_models,
+							stac9872_cfg_tbl);
+	if (spec->board_config < 0)
+		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9872, "
+			    "using BIOS defaults\n");
+	else
+		stac92xx_set_config_regs(codec,
+					 stac9872_brd_tbl[spec->board_config]);
+
+	spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
+	spec->pin_nids = stac9872_pin_nids;
+	spec->multiout.dac_nids = spec->dac_nids;
+	spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids);
+	spec->adc_nids = stac9872_adc_nids;
+	spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids);
+	spec->mux_nids = stac9872_mux_nids;
+	spec->mixer = stac9872_mixer;
+	spec->init = stac9872_core_init;
+
+	err = stac92xx_parse_auto_config(codec, 0x10, 0x12);
+	if (err < 0) {
+		stac92xx_free(codec);
+		return -EINVAL;
+	}
+	spec->input_mux = &spec->private_imux;
+	codec->patch_ops = stac92xx_patch_ops;
 	return 0;
 }
 
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index c761394..b25a5cc 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -1308,16 +1308,13 @@
 	unsigned int def_conf;
 	unsigned char seqassoc;
 
-	def_conf = snd_hda_codec_read(codec, nid, 0,
-				      AC_VERB_GET_CONFIG_DEFAULT, 0);
+	def_conf = snd_hda_codec_get_pincfg(codec, nid);
 	seqassoc = (unsigned char) get_defcfg_association(def_conf);
 	seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
 	if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) {
 		if (seqassoc == 0xff) {
 			def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
-			snd_hda_codec_write(codec, nid, 0,
-					    AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
-					    def_conf >> 24);
+			snd_hda_codec_set_pincfg(codec, nid, def_conf);
 		}
 	}
 
@@ -1354,7 +1351,7 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
 	if (spec->autocfg.dig_in_pin)
 		spec->dig_in_nid = VT1708_DIGIN_NID;
@@ -1827,7 +1824,7 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
 	if (spec->autocfg.dig_in_pin)
 		spec->dig_in_nid = VT1709_DIGIN_NID;
@@ -2371,7 +2368,7 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
 	if (spec->autocfg.dig_in_pin)
 		spec->dig_in_nid = VT1708B_DIGIN_NID;
@@ -2836,7 +2833,7 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
 
 	spec->extra_dig_out_nid = 0x15;
@@ -3155,7 +3152,7 @@
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-	if (spec->autocfg.dig_out_pin)
+	if (spec->autocfg.dig_outs)
 		spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
 
 	spec->extra_dig_out_nid = 0x1B;
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 58d7cda..3dd63f1 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -458,7 +458,7 @@
 			u16 pbkstatus;
 			struct snd_pcm_substream *substream;
 			pbkstatus = inw(ICEDS(ice, INTSTAT));
-			/* printk("pbkstatus = 0x%x\n", pbkstatus); */
+			/* printk(KERN_DEBUG "pbkstatus = 0x%x\n", pbkstatus); */
 			for (idx = 0; idx < 6; idx++) {
 				if ((pbkstatus & (3 << (idx * 2))) == 0)
 					continue;
@@ -2648,9 +2648,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "ICE1712");
 	strcpy(card->shortname, "ICEnsemble ICE1712");
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index bb8d8c7..128510e7 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -241,6 +241,8 @@
 				struct snd_rawmidi_substream, list);
 }
 
+static void enable_midi_irq(struct snd_ice1712 *ice, u8 flag, int enable);
+
 static void vt1724_midi_write(struct snd_ice1712 *ice)
 {
 	struct snd_rawmidi_substream *s;
@@ -254,6 +256,11 @@
 		for (i = 0; i < count; ++i)
 			outb(buffer[i], ICEREG1724(ice, MPU_DATA));
 	}
+	/* mask irq when all bytes have been transmitted.
+	 * enabled again in output_trigger when the new data comes in.
+	 */
+	enable_midi_irq(ice, VT1724_IRQ_MPU_TX,
+			!snd_rawmidi_transmit_empty(s));
 }
 
 static void vt1724_midi_read(struct snd_ice1712 *ice)
@@ -272,31 +279,34 @@
 	}
 }
 
-static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream,
-				   u8 flag, int enable)
+/* call with ice->reg_lock */
+static void enable_midi_irq(struct snd_ice1712 *ice, u8 flag, int enable)
 {
-	struct snd_ice1712 *ice = substream->rmidi->private_data;
-	u8 mask;
-
-	spin_lock_irq(&ice->reg_lock);
-	mask = inb(ICEREG1724(ice, IRQMASK));
+	u8 mask = inb(ICEREG1724(ice, IRQMASK));
 	if (enable)
 		mask &= ~flag;
 	else
 		mask |= flag;
 	outb(mask, ICEREG1724(ice, IRQMASK));
+}
+
+static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream,
+				   u8 flag, int enable)
+{
+	struct snd_ice1712 *ice = substream->rmidi->private_data;
+
+	spin_lock_irq(&ice->reg_lock);
+	enable_midi_irq(ice, flag, enable);
 	spin_unlock_irq(&ice->reg_lock);
 }
 
 static int vt1724_midi_output_open(struct snd_rawmidi_substream *s)
 {
-	vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 1);
 	return 0;
 }
 
 static int vt1724_midi_output_close(struct snd_rawmidi_substream *s)
 {
-	vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 0);
 	return 0;
 }
 
@@ -311,6 +321,7 @@
 		vt1724_midi_write(ice);
 	} else {
 		ice->midi_output = 0;
+		enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0);
 	}
 	spin_unlock_irqrestore(&ice->reg_lock, flags);
 }
@@ -320,6 +331,7 @@
 	struct snd_ice1712 *ice = s->rmidi->private_data;
 	unsigned long timeout;
 
+	vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 0);
 	/* 32 bytes should be transmitted in less than about 12 ms */
 	timeout = jiffies + msecs_to_jiffies(15);
 	do {
@@ -389,24 +401,24 @@
 		status &= status_mask;
 		if (status == 0)
 			break;
+		spin_lock(&ice->reg_lock);
 		if (++timeout > 10) {
 			status = inb(ICEREG1724(ice, IRQSTAT));
 			printk(KERN_ERR "ice1724: Too long irq loop, "
 			       "status = 0x%x\n", status);
 			if (status & VT1724_IRQ_MPU_TX) {
 				printk(KERN_ERR "ice1724: Disabling MPU_TX\n");
-				outb(inb(ICEREG1724(ice, IRQMASK)) |
-				     VT1724_IRQ_MPU_TX,
-				     ICEREG1724(ice, IRQMASK));
+				enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0);
 			}
+			spin_unlock(&ice->reg_lock);
 			break;
 		}
 		handled = 1;
 		if (status & VT1724_IRQ_MPU_TX) {
-			spin_lock(&ice->reg_lock);
 			if (ice->midi_output)
 				vt1724_midi_write(ice);
-			spin_unlock(&ice->reg_lock);
+			else
+				enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0);
 			/* 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
@@ -415,15 +427,14 @@
 			status_mask &= ~VT1724_IRQ_MPU_TX;
 		}
 		if (status & VT1724_IRQ_MPU_RX) {
-			spin_lock(&ice->reg_lock);
 			if (ice->midi_input)
 				vt1724_midi_read(ice);
 			else
 				vt1724_midi_clear_rx(ice);
-			spin_unlock(&ice->reg_lock);
 		}
 		/* ack MPU irq */
 		outb(status, ICEREG1724(ice, IRQSTAT));
+		spin_unlock(&ice->reg_lock);
 		if (status & VT1724_IRQ_MTPCM) {
 			/*
 			 * Multi-track PCM
@@ -745,7 +756,14 @@
 
 	spin_unlock_irq(&ice->reg_lock);
 
-	/* printk("pro prepare: ch = %d, addr = 0x%x, buffer = 0x%x, period = 0x%x\n", substream->runtime->channels, (unsigned int)substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream)); */
+	/*
+	printk(KERN_DEBUG "pro prepare: ch = %d, addr = 0x%x, "
+	       "buffer = 0x%x, period = 0x%x\n",
+	       substream->runtime->channels,
+	       (unsigned int)substream->runtime->dma_addr,
+	       snd_pcm_lib_buffer_bytes(substream),
+	       snd_pcm_lib_period_bytes(substream));
+	*/
 	return 0;
 }
 
@@ -2122,7 +2140,9 @@
 	wait_i2c_busy(ice);
 	val = inb(ICEREG1724(ice, I2C_DATA));
 	mutex_unlock(&ice->i2c_mutex);
-	/* printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); */
+	/*
+	printk(KERN_DEBUG "i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val);
+	*/
 	return val;
 }
 
@@ -2131,7 +2151,9 @@
 {
 	mutex_lock(&ice->i2c_mutex);
 	wait_i2c_busy(ice);
-	/* printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); */
+	/*
+	printk(KERN_DEBUG "i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data);
+	*/
 	outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));
 	outb(data, ICEREG1724(ice, I2C_DATA));
 	outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));
@@ -2456,9 +2478,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "ICE1724");
 	strcpy(card->shortname, "ICEnsemble ICE1724");
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index c51659b..fd948bf 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -345,8 +345,9 @@
 			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",
+	/* printk(KERN_DEBUG
+		"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) {
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 48d3679..2a8e5cd 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -133,8 +133,10 @@
 		idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
 	/* due to possible conflicts with stac9460_set_rate_val, mutexing */
 	mutex_lock(&spec->mute_mutex);
-	/*printk("Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx,
-		ucontrol->value.integer.value[0]);*/
+	/*
+	printk(KERN_DEBUG "Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx,
+	       ucontrol->value.integer.value[0]);
+	*/
 	change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]);
 	mutex_unlock(&spec->mute_mutex);
 	return change;
@@ -185,7 +187,10 @@
 	change = (ovol != nvol);
 	if (change) {
 		ovol =  (0x7f - nvol) | (tmp & 0x80);
-		/*printk("DAC Volume: reg 0x%02x: 0x%02x\n", idx, ovol);*/
+		/*
+		printk(KERN_DEBUG "DAC Volume: reg 0x%02x: 0x%02x\n",
+		       idx, ovol);
+		*/
 		stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
 	}
 	return change;
@@ -344,7 +349,7 @@
 	for (idx = 0; idx < 7 ; ++idx)
 		changed[idx] = stac9460_dac_mute(ice,
 				STAC946X_MASTER_VOLUME + idx, 0);
-	/*printk("Rate change: %d, new MC: 0x%02x\n", rate, new);*/
+	/*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/
 	stac9460_put(ice, STAC946X_MASTER_CLOCKING, new);
 	udelay(10);
 	/* unmuting - only originally unmuted dacs -
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index e900cdc..5764881 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -689,7 +689,7 @@
 			bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */
 						     ichdev->fragsize >> ichdev->pos_shift);
 #if 0
-			printk("bdbar[%i] = 0x%x [0x%x]\n",
+			printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n",
 			       idx + 0, bdbar[idx + 0], bdbar[idx + 1]);
 #endif
 		}
@@ -701,8 +701,10 @@
 	ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags;
 	ichdev->position = 0;
 #if 0
-	printk("lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n",
-			ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1);
+	printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, "
+	       "period_size1 = 0x%x\n",
+	       ichdev->lvi_frag, ichdev->frags, ichdev->fragsize,
+	       ichdev->fragsize1);
 #endif
 	/* clear interrupts */
 	iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
@@ -768,7 +770,8 @@
 		ichdev->lvi_frag %= ichdev->frags;
 		ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1);
 #if 0
-	printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n",
+	printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, "
+	       "all = 0x%x, 0x%x\n",
 	       ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2],
 	       ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port),
 	       inl(port + 4), inb(port + ICH_REG_OFF_CR));
@@ -2287,23 +2290,23 @@
 	iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000);
 }
 
-static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
-{
-	unsigned long end_time;
-	unsigned int cnt, status, nstatus;
-	
-	/* put logic to right state */
-	/* first clear status bits */
-	status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT;
-	if (chip->device_type == DEVICE_NFORCE)
-		status |= ICH_NVSPINT;
-	cnt = igetdword(chip, ICHREG(GLOB_STA));
-	iputdword(chip, ICHREG(GLOB_STA), cnt & status);
+#ifdef CONFIG_SND_AC97_POWER_SAVE
+static struct snd_pci_quirk ich_chip_reset_mode[] = {
+	SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1),
+	{ } /* end */
+};
 
+static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip)
+{
+	unsigned int cnt;
 	/* ACLink on, 2 channels */
+
+	if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
+		return -EIO;
+
 	cnt = igetdword(chip, ICHREG(GLOB_CNT));
 	cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK);
-#ifdef CONFIG_SND_AC97_POWER_SAVE
+
 	/* do cold reset - the full ac97 powerdown may leave the controller
 	 * in a warm state but actually it cannot communicate with the codec.
 	 */
@@ -2312,22 +2315,58 @@
 	udelay(10);
 	iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD);
 	msleep(1);
+	return 0;
+}
+#define snd_intel8x0_ich_chip_can_cold_reset(chip) \
+	(!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
 #else
+#define snd_intel8x0_ich_chip_cold_reset(chip)	0
+#define snd_intel8x0_ich_chip_can_cold_reset(chip) (0)
+#endif
+
+static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip)
+{
+	unsigned long end_time;
+	unsigned int cnt;
+	/* ACLink on, 2 channels */
+	cnt = igetdword(chip, ICHREG(GLOB_CNT));
+	cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK);
 	/* finish cold or do warm reset */
 	cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM;
 	iputdword(chip, ICHREG(GLOB_CNT), cnt);
 	end_time = (jiffies + (HZ / 4)) + 1;
 	do {
 		if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)
-			goto __ok;
+			return 0;
 		schedule_timeout_uninterruptible(1);
 	} while (time_after_eq(end_time, jiffies));
 	snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n",
 		   igetdword(chip, ICHREG(GLOB_CNT)));
 	return -EIO;
+}
 
-      __ok:
-#endif
+static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
+{
+	unsigned long end_time;
+	unsigned int status, nstatus;
+	unsigned int cnt;
+	int err;
+
+	/* put logic to right state */
+	/* first clear status bits */
+	status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT;
+	if (chip->device_type == DEVICE_NFORCE)
+		status |= ICH_NVSPINT;
+	cnt = igetdword(chip, ICHREG(GLOB_STA));
+	iputdword(chip, ICHREG(GLOB_STA), cnt & status);
+
+	if (snd_intel8x0_ich_chip_can_cold_reset(chip))
+		err = snd_intel8x0_ich_chip_cold_reset(chip);
+	else
+		err = snd_intel8x0_ich_chip_reset(chip);
+	if (err < 0)
+		return err;
+
 	if (probing) {
 		/* wait for any codec ready status.
 		 * Once it becomes ready it should remain ready
@@ -3058,9 +3097,9 @@
 	int err;
 	struct shortname_table *name;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	if (spdif_aclink < 0)
 		spdif_aclink = check_default_spdif_aclink(pci);
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 93449e4..6ec0fc5 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -411,7 +411,10 @@
 			bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf + (((idx >> 1) * ichdev->fragsize) % ichdev->size));
 			bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */
 						     ichdev->fragsize >> chip->pcm_pos_shift);
-			// printk("bdbar[%i] = 0x%x [0x%x]\n", idx + 0, bdbar[idx + 0], bdbar[idx + 1]);
+			/*
+			printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n",
+			       idx + 0, bdbar[idx + 0], bdbar[idx + 1]);
+			*/
 		}
 		ichdev->frags = ichdev->size / ichdev->fragsize;
 	}
@@ -421,8 +424,10 @@
 	ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags;
 	ichdev->position = 0;
 #if 0
-	printk("lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n",
-			ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1);
+	printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, "
+	       "period_size1 = 0x%x\n",
+	       ichdev->lvi_frag, ichdev->frags, ichdev->fragsize,
+	       ichdev->fragsize1);
 #endif
 	/* clear interrupts */
 	iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
@@ -465,7 +470,8 @@
 							     ichdev->lvi_frag *
 							     ichdev->fragsize1);
 #if 0
-		printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n",
+		printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], "
+		       "prefetch = %i, all = 0x%x, 0x%x\n",
 		       ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2],
 		       ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port),
 		       inl(port + 4), inb(port + ICH_REG_OFF_CR));
@@ -1269,9 +1275,9 @@
 	int err;
 	struct shortname_table *name;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "ICH-MODEM");
 	strcpy(card->shortname, "Intel ICH");
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 5f8006b..8b79969 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2443,9 +2443,9 @@
 		dev++;
 		return -ENOENT;
 	}
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-        if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
         if ((err = snd_korg1212_create(card, pci, &korg1212)) < 0) {
 		snd_card_free(card);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 59bbaf8..7014154 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2691,9 +2691,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	switch (pci->device) {
 	case PCI_DEVICE_ID_ESS_ALLEGRO:
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index f23a735..c1eb84a 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -607,6 +607,7 @@
 	/* set the format to the board */
 	err = mixart_set_format(stream, format);
 	if(err < 0) {
+		mutex_unlock(&mgr->setup_mutex);
 		return err;
 	}
 
@@ -1365,12 +1366,12 @@
 		else
 			idx = index[dev] + i;
 		snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i);
-		card = snd_card_new(idx, tmpid, THIS_MODULE, 0);
+		err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card);
 
-		if (! card) {
+		if (err < 0) {
 			snd_printk(KERN_ERR "cannot allocate the card %d\n", i);
 			snd_mixart_free(mgr);
-			return -ENOMEM;
+			return err;
 		}
 
 		strcpy(card->driver, CARD_NAME);
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index 3782b52..4cf4cd8 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -345,8 +345,8 @@
 	status_daught = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_DXLX_STATUS_OFFSET ));
 
 	/* motherboard xilinx status 5 will say that the board is performing a reset */
-	if( status_xilinx == 5 ) {
-		snd_printk( KERN_ERR "miXart is resetting !\n");
+	if (status_xilinx == 5) {
+		snd_printk(KERN_ERR "miXart is resetting !\n");
 		return -EAGAIN; /* try again later */
 	}
 
@@ -354,13 +354,14 @@
 	case MIXART_MOTHERBOARD_XLX_INDEX:
 
 		/* xilinx already loaded ? */ 
-		if( status_xilinx == 4 ) {
-			snd_printk( KERN_DEBUG "xilinx is already loaded !\n");
+		if (status_xilinx == 4) {
+			snd_printk(KERN_DEBUG "xilinx is already loaded !\n");
 			return 0;
 		}
 		/* the status should be 0 == "idle" */
-		if( status_xilinx != 0 ) {
-			snd_printk( KERN_ERR "xilinx load error ! status = %d\n", status_xilinx);
+		if (status_xilinx != 0) {
+			snd_printk(KERN_ERR "xilinx load error ! status = %d\n",
+				   status_xilinx);
 			return -EIO; /* modprob -r may help ? */
 		}
 
@@ -389,21 +390,23 @@
 
 	case MIXART_MOTHERBOARD_ELF_INDEX:
 
-		if( status_elf == 4 ) {
-			snd_printk( KERN_DEBUG "elf file already loaded !\n");
+		if (status_elf == 4) {
+			snd_printk(KERN_DEBUG "elf file already loaded !\n");
 			return 0;
 		}
 
 		/* the status should be 0 == "idle" */
-		if( status_elf != 0 ) {
-			snd_printk( KERN_ERR "elf load error ! status = %d\n", status_elf);
+		if (status_elf != 0) {
+			snd_printk(KERN_ERR "elf load error ! status = %d\n",
+				   status_elf);
 			return -EIO; /* modprob -r may help ? */
 		}
 
 		/* wait for xilinx status == 4 */
 		err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET, 1, 4, 500); /* 5sec */
 		if (err < 0) {
-			snd_printk( KERN_ERR "xilinx was not loaded or could not be started\n");
+			snd_printk(KERN_ERR "xilinx was not loaded or "
+				   "could not be started\n");
 			return err;
 		}
 
@@ -424,7 +427,7 @@
 		/* wait for elf status == 4 */
 		err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET, 1, 4, 300); /* 3sec */
 		if (err < 0) {
-			snd_printk( KERN_ERR "elf could not be started\n");
+			snd_printk(KERN_ERR "elf could not be started\n");
 			return err;
 		}
 
@@ -437,15 +440,16 @@
 	default:
 
 		/* elf and xilinx should be loaded */
-		if( (status_elf != 4) || (status_xilinx != 4) ) {
-			printk( KERN_ERR "xilinx or elf not successfully loaded\n");
+		if (status_elf != 4 || status_xilinx != 4) {
+			printk(KERN_ERR "xilinx or elf not "
+			       "successfully loaded\n");
 			return -EIO; /* modprob -r may help ? */
 		}
 
 		/* wait for daughter detection != 0 */
 		err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET, 0, 0, 30); /* 300msec */
 		if (err < 0) {
-			snd_printk( KERN_ERR "error starting elf file\n");
+			snd_printk(KERN_ERR "error starting elf file\n");
 			return err;
 		}
 
@@ -460,8 +464,9 @@
 			return -EINVAL;
 
 		/* daughter should be idle */
-		if( status_daught != 0 ) {
-			printk( KERN_ERR "daughter load error ! status = %d\n", status_daught);
+		if (status_daught != 0) {
+			printk(KERN_ERR "daughter load error ! status = %d\n",
+			       status_daught);
 			return -EIO; /* modprob -r may help ? */
 		}
  
@@ -480,7 +485,7 @@
 		/* wait for status == 2 */
 		err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 2, 30); /* 300msec */
 		if (err < 0) {
-			snd_printk( KERN_ERR "daughter board load error\n");
+			snd_printk(KERN_ERR "daughter board load error\n");
 			return err;
 		}
 
@@ -502,7 +507,8 @@
         /* wait for daughter status == 3 */
         err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 3, 300); /* 3sec */
         if (err < 0) {
-		snd_printk( KERN_ERR "daughter board could not be initialised\n");
+		snd_printk(KERN_ERR
+			   "daughter board could not be initialised\n");
 		return err;
 	}
 
@@ -512,7 +518,7 @@
 	/* first communication with embedded */
 	err = mixart_first_init(mgr);
         if (err < 0) {
-		snd_printk( KERN_ERR "miXart could not be set up\n");
+		snd_printk(KERN_ERR "miXart could not be set up\n");
 		return err;
 	}
 
@@ -581,16 +587,6 @@
 /* miXart hwdep interface id string */
 #define SND_MIXART_HWDEP_ID       "miXart Loader"
 
-static int mixart_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
-static int mixart_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
 static int mixart_hwdep_dsp_status(struct snd_hwdep *hw,
 				   struct snd_hwdep_dsp_status *info)
 {
@@ -643,8 +639,6 @@
 
 	hw->iface = SNDRV_HWDEP_IFACE_MIXART;
 	hw->private_data = mgr;
-	hw->ops.open = mixart_hwdep_open;
-	hw->ops.release = mixart_hwdep_release;
 	hw->ops.dsp_status = mixart_hwdep_dsp_status;
 	hw->ops.dsp_load = mixart_hwdep_dsp_load;
 	hw->exclusive = 1;
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 50c9f8a..522a040 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1668,9 +1668,9 @@
 		}
 	}
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	switch (pci->device) {
 	case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO:
diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index 1ab833f..84ef131 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -45,6 +45,7 @@
 static struct pci_device_id hifier_ids[] __devinitdata = {
 	{ OXYGEN_PCI_SUBID(0x14c3, 0x1710) },
 	{ OXYGEN_PCI_SUBID(0x14c3, 0x1711) },
+	{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, hifier_ids);
@@ -151,7 +152,6 @@
 	.shortname = "C-Media CMI8787",
 	.longname = "C-Media Oxygen HD Audio",
 	.chip = "CMI8788",
-	.owner = THIS_MODULE,
 	.init = hifier_init,
 	.control_filter = hifier_control_filter,
 	.cleanup = hifier_cleanup,
@@ -173,6 +173,13 @@
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
 
+static int __devinit get_hifier_model(struct oxygen *chip,
+				      const struct pci_device_id *id)
+{
+	chip->model = model_hifier;
+	return 0;
+}
+
 static int __devinit hifier_probe(struct pci_dev *pci,
 				  const struct pci_device_id *pci_id)
 {
@@ -185,7 +192,8 @@
 		++dev;
 		return -ENOENT;
 	}
-	err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier, 0);
+	err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
+			       hifier_ids, get_hifier_model);
 	if (err >= 0)
 		++dev;
 	return err;
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index de999c6..72db4c3 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -1,5 +1,5 @@
 /*
- * C-Media CMI8788 driver for C-Media's reference design and for the X-Meridian
+ * C-Media CMI8788 driver for C-Media's reference design and similar models
  *
  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  *
@@ -26,6 +26,7 @@
  *
  * GPIO 0 -> DFS0 of AK5385
  * GPIO 1 -> DFS1 of AK5385
+ * GPIO 8 -> enable headphone amplifier on HT-Omega models
  */
 
 #include <linux/delay.h>
@@ -61,7 +62,8 @@
 enum {
 	MODEL_CMEDIA_REF,	/* C-Media's reference design */
 	MODEL_MERIDIAN,		/* AuzenTech X-Meridian */
-	MODEL_HALO,		/* HT-Omega Claro halo */
+	MODEL_CLARO,		/* HT-Omega Claro */
+	MODEL_CLARO_HALO,	/* HT-Omega Claro halo */
 };
 
 static struct pci_device_id oxygen_ids[] __devinitdata = {
@@ -74,8 +76,8 @@
 	{ OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF },
 	{ OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF },
 	{ OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN },
-	{ OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CMEDIA_REF },
-	{ OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_HALO },
+	{ OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO },
+	{ OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, oxygen_ids);
@@ -86,6 +88,8 @@
 #define GPIO_AK5385_DFS_DOUBLE	0x0001
 #define GPIO_AK5385_DFS_QUAD	0x0002
 
+#define GPIO_CLARO_HP		0x0100
+
 struct generic_data {
 	u8 ak4396_ctl2;
 	u16 saved_wm8785_registers[2];
@@ -196,10 +200,46 @@
 	ak5385_init(chip);
 }
 
+static void claro_enable_hp(struct oxygen *chip)
+{
+	msleep(300);
+	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_HP);
+	oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP);
+}
+
+static void claro_init(struct oxygen *chip)
+{
+	ak4396_init(chip);
+	wm8785_init(chip);
+	claro_enable_hp(chip);
+}
+
+static void claro_halo_init(struct oxygen *chip)
+{
+	ak4396_init(chip);
+	ak5385_init(chip);
+	claro_enable_hp(chip);
+}
+
 static void generic_cleanup(struct oxygen *chip)
 {
 }
 
+static void claro_disable_hp(struct oxygen *chip)
+{
+	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP);
+}
+
+static void claro_cleanup(struct oxygen *chip)
+{
+	claro_disable_hp(chip);
+}
+
+static void claro_suspend(struct oxygen *chip)
+{
+	claro_disable_hp(chip);
+}
+
 static void generic_resume(struct oxygen *chip)
 {
 	ak4396_registers_init(chip);
@@ -211,6 +251,12 @@
 	ak4396_registers_init(chip);
 }
 
+static void claro_resume(struct oxygen *chip)
+{
+	ak4396_registers_init(chip);
+	claro_enable_hp(chip);
+}
+
 static void set_ak4396_params(struct oxygen *chip,
 			      struct snd_pcm_hw_params *params)
 {
@@ -293,30 +339,10 @@
 
 static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
-static int generic_probe(struct oxygen *chip, unsigned long driver_data)
-{
-	if (driver_data == MODEL_MERIDIAN) {
-		chip->model.init = meridian_init;
-		chip->model.resume = meridian_resume;
-		chip->model.set_adc_params = set_ak5385_params;
-		chip->model.device_config = PLAYBACK_0_TO_I2S |
-					    PLAYBACK_1_TO_SPDIF |
-					    CAPTURE_0_FROM_I2S_2 |
-					    CAPTURE_1_FROM_SPDIF;
-	}
-	if (driver_data == MODEL_MERIDIAN || driver_data == MODEL_HALO) {
-		chip->model.misc_flags = OXYGEN_MISC_MIDI;
-		chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT;
-	}
-	return 0;
-}
-
 static const struct oxygen_model model_generic = {
 	.shortname = "C-Media CMI8788",
 	.longname = "C-Media Oxygen HD Audio",
 	.chip = "CMI8788",
-	.owner = THIS_MODULE,
-	.probe = generic_probe,
 	.init = generic_init,
 	.cleanup = generic_cleanup,
 	.resume = generic_resume,
@@ -341,6 +367,42 @@
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
 
+static int __devinit get_oxygen_model(struct oxygen *chip,
+				      const struct pci_device_id *id)
+{
+	chip->model = model_generic;
+	switch (id->driver_data) {
+	case MODEL_MERIDIAN:
+		chip->model.init = meridian_init;
+		chip->model.resume = meridian_resume;
+		chip->model.set_adc_params = set_ak5385_params;
+		chip->model.device_config = PLAYBACK_0_TO_I2S |
+					    PLAYBACK_1_TO_SPDIF |
+					    CAPTURE_0_FROM_I2S_2 |
+					    CAPTURE_1_FROM_SPDIF;
+		break;
+	case MODEL_CLARO:
+		chip->model.init = claro_init;
+		chip->model.cleanup = claro_cleanup;
+		chip->model.suspend = claro_suspend;
+		chip->model.resume = claro_resume;
+		break;
+	case MODEL_CLARO_HALO:
+		chip->model.init = claro_halo_init;
+		chip->model.cleanup = claro_cleanup;
+		chip->model.suspend = claro_suspend;
+		chip->model.resume = claro_resume;
+		chip->model.set_adc_params = set_ak5385_params;
+		break;
+	}
+	if (id->driver_data == MODEL_MERIDIAN ||
+	    id->driver_data == MODEL_CLARO_HALO) {
+		chip->model.misc_flags = OXYGEN_MISC_MIDI;
+		chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT;
+	}
+	return 0;
+}
+
 static int __devinit generic_oxygen_probe(struct pci_dev *pci,
 					  const struct pci_device_id *pci_id)
 {
@@ -353,8 +415,8 @@
 		++dev;
 		return -ENOENT;
 	}
-	err = oxygen_pci_probe(pci, index[dev], id[dev],
-			       &model_generic, pci_id->driver_data);
+	err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
+			       oxygen_ids, get_oxygen_model);
 	if (err >= 0)
 		++dev;
 	return err;
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index 19107c6..bd615db 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -18,6 +18,8 @@
 
 #define OXYGEN_IO_SIZE	0x100
 
+#define OXYGEN_EEPROM_ID	0x434d	/* "CM" */
+
 /* model-specific configuration of outputs/inputs */
 #define PLAYBACK_0_TO_I2S	0x0001
      /* PLAYBACK_0_TO_AC97_0		not implemented */
@@ -49,7 +51,13 @@
 	.subvendor = sv, \
 	.subdevice = sd
 
+#define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1)
+#define OXYGEN_PCI_SUBID_BROKEN_EEPROM \
+	OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \
+	.driver_data = BROKEN_EEPROM_DRIVER_DATA
+
 struct pci_dev;
+struct pci_device_id;
 struct snd_card;
 struct snd_pcm_substream;
 struct snd_pcm_hardware;
@@ -62,8 +70,6 @@
 	const char *shortname;
 	const char *longname;
 	const char *chip;
-	struct module *owner;
-	int (*probe)(struct oxygen *chip, unsigned long driver_data);
 	void (*init)(struct oxygen *chip);
 	int (*control_filter)(struct snd_kcontrol_new *template);
 	int (*mixer_init)(struct oxygen *chip);
@@ -83,6 +89,7 @@
 	void (*ac97_switch)(struct oxygen *chip,
 			    unsigned int reg, unsigned int mute);
 	const unsigned int *dac_tlv;
+	unsigned long private_data;
 	size_t model_data_size;
 	unsigned int device_config;
 	u8 dac_channels;
@@ -134,8 +141,12 @@
 /* oxygen_lib.c */
 
 int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
-		     const struct oxygen_model *model,
-		     unsigned long driver_data);
+		     struct module *owner,
+		     const struct pci_device_id *ids,
+		     int (*get_model)(struct oxygen *chip,
+				      const struct pci_device_id *id
+				     )
+		    );
 void oxygen_pci_remove(struct pci_dev *pci);
 #ifdef CONFIG_PM
 int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state);
@@ -180,6 +191,9 @@
 void oxygen_reset_uart(struct oxygen *chip);
 void oxygen_write_uart(struct oxygen *chip, u8 data);
 
+u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index);
+void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value);
+
 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 3126c4b..c1eb923 100644
--- a/sound/pci/oxygen/oxygen_io.c
+++ b/sound/pci/oxygen/oxygen_io.c
@@ -254,3 +254,34 @@
 	_write_uart(chip, 0, data);
 }
 EXPORT_SYMBOL(oxygen_write_uart);
+
+u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index)
+{
+	unsigned int timeout;
+
+	oxygen_write8(chip, OXYGEN_EEPROM_CONTROL,
+		      index | OXYGEN_EEPROM_DIR_READ);
+	for (timeout = 0; timeout < 100; ++timeout) {
+		udelay(1);
+		if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS)
+		      & OXYGEN_EEPROM_BUSY))
+			break;
+	}
+	return oxygen_read16(chip, OXYGEN_EEPROM_DATA);
+}
+
+void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value)
+{
+	unsigned int timeout;
+
+	oxygen_write16(chip, OXYGEN_EEPROM_DATA, value);
+	oxygen_write8(chip, OXYGEN_EEPROM_CONTROL,
+		      index | OXYGEN_EEPROM_DIR_WRITE);
+	for (timeout = 0; timeout < 10; ++timeout) {
+		msleep(1);
+		if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS)
+		      & OXYGEN_EEPROM_BUSY))
+			return;
+	}
+	snd_printk(KERN_ERR "EEPROM write timeout\n");
+}
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 84f481d..312251d 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -34,6 +34,7 @@
 MODULE_DESCRIPTION("C-Media CMI8788 helper library");
 MODULE_LICENSE("GPL v2");
 
+#define DRIVER "oxygen"
 
 static inline int oxygen_uart_input_ready(struct oxygen *chip)
 {
@@ -243,6 +244,62 @@
 #define oxygen_proc_init(chip)
 #endif
 
+static const struct pci_device_id *
+oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[])
+{
+	u16 subdevice;
+
+	/*
+	 * Make sure the EEPROM pins are available, i.e., not used for SPI.
+	 * (This function is called before we initialize or use SPI.)
+	 */
+	oxygen_clear_bits8(chip, OXYGEN_FUNCTION,
+			   OXYGEN_FUNCTION_ENABLE_SPI_4_5);
+	/*
+	 * Read the subsystem device ID directly from the EEPROM, because the
+	 * chip didn't if the first EEPROM word was overwritten.
+	 */
+	subdevice = oxygen_read_eeprom(chip, 2);
+	/*
+	 * We use only the subsystem device ID for searching because it is
+	 * unique even without the subsystem vendor ID, which may have been
+	 * overwritten in the EEPROM.
+	 */
+	for (; ids->vendor; ++ids)
+		if (ids->subdevice == subdevice &&
+		    ids->driver_data != BROKEN_EEPROM_DRIVER_DATA)
+			return ids;
+	return NULL;
+}
+
+static void oxygen_restore_eeprom(struct oxygen *chip,
+				  const struct pci_device_id *id)
+{
+	if (oxygen_read_eeprom(chip, 0) != OXYGEN_EEPROM_ID) {
+		/*
+		 * This function gets called only when a known card model has
+		 * been detected, i.e., we know there is a valid subsystem
+		 * product ID at index 2 in the EEPROM.  Therefore, we have
+		 * been able to deduce the correct subsystem vendor ID, and
+		 * this is enough information to restore the original EEPROM
+		 * contents.
+		 */
+		oxygen_write_eeprom(chip, 1, id->subvendor);
+		oxygen_write_eeprom(chip, 0, OXYGEN_EEPROM_ID);
+
+		oxygen_set_bits8(chip, OXYGEN_MISC,
+				 OXYGEN_MISC_WRITE_PCI_SUBID);
+		pci_write_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID,
+				      id->subvendor);
+		pci_write_config_word(chip->pci, PCI_SUBSYSTEM_ID,
+				      id->subdevice);
+		oxygen_clear_bits8(chip, OXYGEN_MISC,
+				   OXYGEN_MISC_WRITE_PCI_SUBID);
+
+		snd_printk(KERN_INFO "EEPROM ID restored\n");
+	}
+}
+
 static void oxygen_init(struct oxygen *chip)
 {
 	unsigned int i;
@@ -446,30 +503,33 @@
 		free_irq(chip->irq, chip);
 	flush_scheduled_work();
 	chip->model.cleanup(chip);
+	kfree(chip->model_data);
 	mutex_destroy(&chip->mutex);
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 }
 
 int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
-		     const struct oxygen_model *model,
-		     unsigned long driver_data)
+		     struct module *owner,
+		     const struct pci_device_id *ids,
+		     int (*get_model)(struct oxygen *chip,
+				      const struct pci_device_id *id
+				     )
+		    )
 {
 	struct snd_card *card;
 	struct oxygen *chip;
+	const struct pci_device_id *pci_id;
 	int err;
 
-	card = snd_card_new(index, id, model->owner,
-			    sizeof *chip + model->model_data_size);
-	if (!card)
-		return -ENOMEM;
+	err = snd_card_create(index, id, owner, sizeof(*chip), &card);
+	if (err < 0)
+		return err;
 
 	chip = card->private_data;
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	chip->model = *model;
-	chip->model_data = chip + 1;
 	spin_lock_init(&chip->reg_lock);
 	mutex_init(&chip->mutex);
 	INIT_WORK(&chip->spdif_input_bits_work,
@@ -481,7 +541,7 @@
 	if (err < 0)
 		goto err_card;
 
-	err = pci_request_regions(pci, model->chip);
+	err = pci_request_regions(pci, DRIVER);
 	if (err < 0) {
 		snd_printk(KERN_ERR "cannot reserve PCI resources\n");
 		goto err_pci_enable;
@@ -495,20 +555,34 @@
 	}
 	chip->addr = pci_resource_start(pci, 0);
 
+	pci_id = oxygen_search_pci_id(chip, ids);
+	if (!pci_id) {
+		err = -ENODEV;
+		goto err_pci_regions;
+	}
+	oxygen_restore_eeprom(chip, pci_id);
+	err = get_model(chip, pci_id);
+	if (err < 0)
+		goto err_pci_regions;
+
+	if (chip->model.model_data_size) {
+		chip->model_data = kzalloc(chip->model.model_data_size,
+					   GFP_KERNEL);
+		if (!chip->model_data) {
+			err = -ENOMEM;
+			goto err_pci_regions;
+		}
+	}
+
 	pci_set_master(pci);
 	snd_card_set_dev(card, &pci->dev);
 	card->private_free = oxygen_card_free;
 
-	if (chip->model.probe) {
-		err = chip->model.probe(chip, driver_data);
-		if (err < 0)
-			goto err_card;
-	}
 	oxygen_init(chip);
 	chip->model.init(chip);
 
 	err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED,
-			  chip->model.chip, chip);
+			  DRIVER, chip);
 	if (err < 0) {
 		snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq);
 		goto err_card;
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 6c870c1..bc5ce11 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -112,6 +112,34 @@
  * CS4362A: AD0 <- 0
  */
 
+/*
+ * Xonar Essence STX
+ * -----------------
+ *
+ * CMI8788:
+ *
+ * I²C <-> PCM1792A
+ *
+ * GPI 0 <- external power present
+ *
+ * GPIO 0 -> enable output to speakers
+ * GPIO 1 -> route HP to front panel (0) or rear jack (1)
+ * GPIO 2 -> M0 of CS5381
+ * GPIO 3 -> M1 of CS5381
+ * GPIO 7 -> route output to speaker jacks (0) or HP (1)
+ * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
+ *
+ * PCM1792A:
+ *
+ * AD0 <- 0
+ *
+ * H6 daughterboard
+ * ----------------
+ *
+ * GPIO 4 <- 0
+ * GPIO 5 <- 0
+ */
+
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
@@ -152,6 +180,7 @@
 	MODEL_DX,
 	MODEL_HDAV,	/* without daughterboard */
 	MODEL_HDAV_H6,	/* with H6 daughterboard */
+	MODEL_STX,
 };
 
 static struct pci_device_id xonar_ids[] __devinitdata = {
@@ -160,6 +189,8 @@
 	{ OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 },
+	{ OXYGEN_PCI_SUBID(0x1043, 0x835c), .driver_data = MODEL_STX },
+	{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, xonar_ids);
@@ -183,12 +214,14 @@
 #define GPIO_HDAV_DB_H6		0x0000
 #define GPIO_HDAV_DB_XX		0x0020
 
+#define GPIO_ST_HP_REAR		0x0002
+#define GPIO_ST_HP		0x0080
+
 #define I2C_DEVICE_PCM1796(i)	(0x98 + ((i) << 1))	/* 10011, ADx=i, /W=0 */
 #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 {
-	unsigned int model;
 	unsigned int anti_pop_delay;
 	unsigned int dacs;
 	u16 output_enable_bit;
@@ -334,15 +367,9 @@
 	struct xonar_data *data = chip->model_data;
 
 	data->anti_pop_delay = 300;
+	data->dacs = 4;
 	data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
 	data->pcm1796_oversampling = PCM1796_OS_64;
-	if (data->model == MODEL_D2X) {
-		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);
-	}
 
 	pcm1796_init(chip);
 
@@ -355,6 +382,18 @@
 	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 update_cs4362a_volumes(struct oxygen *chip)
 {
 	u8 mute;
@@ -422,11 +461,6 @@
 	data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST;
 	data->cs4362a_fm = CS4362A_FM_SINGLE |
 		CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
-	if (data->model == MODEL_DX) {
-		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 |
@@ -447,6 +481,17 @@
 	snd_component_add(chip->card, "CS5361");
 }
 
+static void xonar_dx_init(struct oxygen *chip)
+{
+	struct xonar_data *data = chip->model_data;
+
+	data->ext_power_reg = OXYGEN_GPI_DATA;
+	data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
+	data->ext_power_bit = GPI_DX_EXT_POWER;
+
+	xonar_d1_init(chip);
+}
+
 static void xonar_hdav_init(struct oxygen *chip)
 {
 	struct xonar_data *data = chip->model_data;
@@ -458,6 +503,7 @@
 		       OXYGEN_2WIRE_SPEED_FAST);
 
 	data->anti_pop_delay = 100;
+	data->dacs = chip->model.private_data == MODEL_HDAV_H6 ? 4 : 1;
 	data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
 	data->ext_power_reg = OXYGEN_GPI_DATA;
 	data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
@@ -484,6 +530,36 @@
 	snd_component_add(chip->card, "CS5381");
 }
 
+static void xonar_stx_init(struct oxygen *chip)
+{
+	struct xonar_data *data = chip->model_data;
+
+	oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
+		       OXYGEN_2WIRE_LENGTH_8 |
+		       OXYGEN_2WIRE_INTERRUPT_MASK |
+		       OXYGEN_2WIRE_SPEED_FAST);
+
+	data->anti_pop_delay = 100;
+	data->dacs = 1;
+	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;
+	data->pcm1796_oversampling = PCM1796_OS_64;
+
+	pcm1796_init(chip);
+
+	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+			  GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
+	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
+			    GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
+
+	xonar_common_init(chip);
+
+	snd_component_add(chip->card, "PCM1792A");
+	snd_component_add(chip->card, "CS5381");
+}
+
 static void xonar_disable_output(struct oxygen *chip)
 {
 	struct xonar_data *data = chip->model_data;
@@ -511,6 +587,11 @@
 	xonar_disable_output(chip);
 }
 
+static void xonar_st_cleanup(struct oxygen *chip)
+{
+	xonar_disable_output(chip);
+}
+
 static void xonar_d2_suspend(struct oxygen *chip)
 {
 	xonar_d2_cleanup(chip);
@@ -527,6 +608,11 @@
 	msleep(2);
 }
 
+static void xonar_st_suspend(struct oxygen *chip)
+{
+	xonar_st_cleanup(chip);
+}
+
 static void xonar_d2_resume(struct oxygen *chip)
 {
 	pcm1796_init(chip);
@@ -554,6 +640,12 @@
 	xonar_enable_output(chip);
 }
 
+static void xonar_st_resume(struct oxygen *chip)
+{
+	pcm1796_init(chip);
+	xonar_enable_output(chip);
+}
+
 static void xonar_hdav_pcm_hardware_filter(unsigned int channel,
 					   struct snd_pcm_hardware *hardware)
 {
@@ -733,6 +825,72 @@
 	.private_value = GPIO_DX_FRONT_PANEL,
 };
 
+static int st_output_switch_info(struct snd_kcontrol *ctl,
+				 struct snd_ctl_elem_info *info)
+{
+	static const char *const names[3] = {
+		"Speakers", "Headphones", "FP Headphones"
+	};
+
+	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	info->count = 1;
+	info->value.enumerated.items = 3;
+	if (info->value.enumerated.item >= 3)
+		info->value.enumerated.item = 2;
+	strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
+	return 0;
+}
+
+static int st_output_switch_get(struct snd_kcontrol *ctl,
+				struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+	u16 gpio;
+
+	gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+	if (!(gpio & GPIO_ST_HP))
+		value->value.enumerated.item[0] = 0;
+	else if (gpio & GPIO_ST_HP_REAR)
+		value->value.enumerated.item[0] = 1;
+	else
+		value->value.enumerated.item[0] = 2;
+	return 0;
+}
+
+
+static int st_output_switch_put(struct snd_kcontrol *ctl,
+				struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+	u16 gpio_old, gpio;
+
+	mutex_lock(&chip->mutex);
+	gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+	gpio = gpio_old;
+	switch (value->value.enumerated.item[0]) {
+	case 0:
+		gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR);
+		break;
+	case 1:
+		gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR;
+		break;
+	case 2:
+		gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR;
+		break;
+	}
+	oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio);
+	mutex_unlock(&chip->mutex);
+	return gpio != gpio_old;
+}
+
+static const struct snd_kcontrol_new st_output_switch = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Analog Output",
+	.info = st_output_switch_info,
+	.get = st_output_switch_get,
+	.put = st_output_switch_put,
+};
+
 static void xonar_line_mic_ac97_switch(struct oxygen *chip,
 				       unsigned int reg, unsigned int mute)
 {
@@ -745,8 +903,8 @@
 	}
 }
 
-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 const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -6000, 50, 0);
+static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0);
 
 static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
 {
@@ -763,6 +921,15 @@
 	return 0;
 }
 
+static int xonar_st_control_filter(struct snd_kcontrol_new *template)
+{
+	if (!strncmp(template->name, "CD Capture ", 11))
+		return 1; /* no CD input */
+	if (!strcmp(template->name, "Stereo Upmixing"))
+		return 1; /* stereo only - we don't need upmixing */
+	return 0;
+}
+
 static int xonar_d2_mixer_init(struct oxygen *chip)
 {
 	return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
@@ -773,51 +940,14 @@
 	return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
 }
 
-static int xonar_model_probe(struct oxygen *chip, unsigned long driver_data)
+static int xonar_st_mixer_init(struct oxygen *chip)
 {
-	static const char *const names[] = {
-		[MODEL_D1]	= "Xonar D1",
-		[MODEL_DX]	= "Xonar DX",
-		[MODEL_D2]	= "Xonar D2",
-		[MODEL_D2X]	= "Xonar D2X",
-		[MODEL_HDAV]	= "Xonar HDAV1.3",
-		[MODEL_HDAV_H6]	= "Xonar HDAV1.3+H6",
-	};
-	static const u8 dacs[] = {
-		[MODEL_D1]	= 2,
-		[MODEL_DX]	= 2,
-		[MODEL_D2]	= 4,
-		[MODEL_D2X]	= 4,
-		[MODEL_HDAV]	= 1,
-		[MODEL_HDAV_H6]	= 4,
-	};
-	struct xonar_data *data = chip->model_data;
-
-	data->model = driver_data;
-	if (data->model == MODEL_HDAV) {
-		oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
-				    GPIO_HDAV_DB_MASK);
-		switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) &
-			GPIO_HDAV_DB_MASK) {
-		case GPIO_HDAV_DB_H6:
-			data->model = MODEL_HDAV_H6;
-			break;
-		case GPIO_HDAV_DB_XX:
-			snd_printk(KERN_ERR "unknown daughterboard\n");
-			return -ENODEV;
-		}
-	}
-
-	data->dacs = dacs[data->model];
-	chip->model.shortname = names[data->model];
-	return 0;
+	return snd_ctl_add(chip->card, snd_ctl_new1(&st_output_switch, chip));
 }
 
 static const struct oxygen_model model_xonar_d2 = {
 	.longname = "Asus Virtuoso 200",
 	.chip = "AV200",
-	.owner = THIS_MODULE,
-	.probe = xonar_model_probe,
 	.init = xonar_d2_init,
 	.control_filter = xonar_d2_control_filter,
 	.mixer_init = xonar_d2_mixer_init,
@@ -837,8 +967,8 @@
 			 MIDI_OUTPUT |
 			 MIDI_INPUT,
 	.dac_channels = 8,
-	.dac_volume_min = 0x0f,
-	.dac_volume_max = 0xff,
+	.dac_volume_min = 255 - 2*60,
+	.dac_volume_max = 255,
 	.misc_flags = OXYGEN_MISC_MIDI,
 	.function_flags = OXYGEN_FUNCTION_SPI |
 			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
@@ -849,8 +979,6 @@
 static const struct oxygen_model model_xonar_d1 = {
 	.longname = "Asus Virtuoso 100",
 	.chip = "AV200",
-	.owner = THIS_MODULE,
-	.probe = xonar_model_probe,
 	.init = xonar_d1_init,
 	.control_filter = xonar_d1_control_filter,
 	.mixer_init = xonar_d1_mixer_init,
@@ -868,7 +996,7 @@
 			 PLAYBACK_1_TO_SPDIF |
 			 CAPTURE_0_FROM_I2S_2,
 	.dac_channels = 8,
-	.dac_volume_min = 0,
+	.dac_volume_min = 127 - 60,
 	.dac_volume_max = 127,
 	.function_flags = OXYGEN_FUNCTION_2WIRE,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
@@ -878,8 +1006,6 @@
 static const struct oxygen_model model_xonar_hdav = {
 	.longname = "Asus Virtuoso 200",
 	.chip = "AV200",
-	.owner = THIS_MODULE,
-	.probe = xonar_model_probe,
 	.init = xonar_hdav_init,
 	.cleanup = xonar_hdav_cleanup,
 	.suspend = xonar_hdav_suspend,
@@ -897,16 +1023,43 @@
 			 PLAYBACK_1_TO_SPDIF |
 			 CAPTURE_0_FROM_I2S_2,
 	.dac_channels = 8,
-	.dac_volume_min = 0x0f,
-	.dac_volume_max = 0xff,
+	.dac_volume_min = 255 - 2*60,
+	.dac_volume_max = 255,
 	.misc_flags = OXYGEN_MISC_MIDI,
 	.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,
-				 const struct pci_device_id *pci_id)
+static const struct oxygen_model model_xonar_st = {
+	.longname = "Asus Virtuoso 100",
+	.chip = "AV200",
+	.init = xonar_stx_init,
+	.control_filter = xonar_st_control_filter,
+	.mixer_init = xonar_st_mixer_init,
+	.cleanup = xonar_st_cleanup,
+	.suspend = xonar_st_suspend,
+	.resume = xonar_st_resume,
+	.set_dac_params = set_pcm1796_params,
+	.set_adc_params = set_cs53x1_params,
+	.update_dac_volume = update_pcm1796_volume,
+	.update_dac_mute = update_pcm1796_mute,
+	.ac97_switch = xonar_line_mic_ac97_switch,
+	.dac_tlv = pcm1796_db_scale,
+	.model_data_size = sizeof(struct xonar_data),
+	.device_config = PLAYBACK_0_TO_I2S |
+			 PLAYBACK_1_TO_SPDIF |
+			 CAPTURE_0_FROM_I2S_2,
+	.dac_channels = 2,
+	.dac_volume_min = 255 - 2*60,
+	.dac_volume_max = 255,
+	.function_flags = OXYGEN_FUNCTION_2WIRE,
+	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+};
+
+static int __devinit get_xonar_model(struct oxygen *chip,
+				     const struct pci_device_id *id)
 {
 	static const struct oxygen_model *const models[] = {
 		[MODEL_D1]	= &model_xonar_d1,
@@ -914,7 +1067,57 @@
 		[MODEL_D2]	= &model_xonar_d2,
 		[MODEL_D2X]	= &model_xonar_d2,
 		[MODEL_HDAV]	= &model_xonar_hdav,
+		[MODEL_STX]	= &model_xonar_st,
 	};
+	static const char *const names[] = {
+		[MODEL_D1]	= "Xonar D1",
+		[MODEL_DX]	= "Xonar DX",
+		[MODEL_D2]	= "Xonar D2",
+		[MODEL_D2X]	= "Xonar D2X",
+		[MODEL_HDAV]	= "Xonar HDAV1.3",
+		[MODEL_HDAV_H6]	= "Xonar HDAV1.3+H6",
+		[MODEL_STX]	= "Xonar Essence STX",
+	};
+	unsigned int model = id->driver_data;
+
+	if (model >= ARRAY_SIZE(models) || !models[model])
+		return -EINVAL;
+	chip->model = *models[model];
+
+	switch (model) {
+	case MODEL_D2X:
+		chip->model.init = xonar_d2x_init;
+		break;
+	case MODEL_DX:
+		chip->model.init = xonar_dx_init;
+		break;
+	case MODEL_HDAV:
+		oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
+				    GPIO_HDAV_DB_MASK);
+		switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) &
+			GPIO_HDAV_DB_MASK) {
+		case GPIO_HDAV_DB_H6:
+			model = MODEL_HDAV_H6;
+			break;
+		case GPIO_HDAV_DB_XX:
+			snd_printk(KERN_ERR "unknown daughterboard\n");
+			return -ENODEV;
+		}
+		break;
+	case MODEL_STX:
+		oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
+				    GPIO_HDAV_DB_MASK);
+		break;
+	}
+
+	chip->model.shortname = names[model];
+	chip->model.private_data = model;
+	return 0;
+}
+
+static int __devinit xonar_probe(struct pci_dev *pci,
+				 const struct pci_device_id *pci_id)
+{
 	static int dev;
 	int err;
 
@@ -924,10 +1127,8 @@
 		++dev;
 		return -ENOENT;
 	}
-	BUG_ON(pci_id->driver_data >= ARRAY_SIZE(models));
-	err = oxygen_pci_probe(pci, index[dev], id[dev],
-			       models[pci_id->driver_data],
-			       pci_id->driver_data);
+	err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
+			       xonar_ids, get_xonar_model);
 	if (err >= 0)
 		++dev;
 	return err;
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 27cf2c2..80e064a 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1334,6 +1334,40 @@
 	snd_iprintf(buffer, "\n");
 }
 
+static void pcxhr_proc_gpio_read(struct snd_info_entry *entry,
+				 struct snd_info_buffer *buffer)
+{
+	struct snd_pcxhr *chip = entry->private_data;
+	struct pcxhr_mgr *mgr = chip->mgr;
+	/* commands available when embedded DSP is running */
+	if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
+		/* gpio ports on stereo boards only available */
+		int value = 0;
+		hr222_read_gpio(mgr, 1, &value);	/* GPI */
+		snd_iprintf(buffer, "GPI: 0x%x\n", value);
+		hr222_read_gpio(mgr, 0, &value);	/* GP0 */
+		snd_iprintf(buffer, "GPO: 0x%x\n", value);
+	} else
+		snd_iprintf(buffer, "no firmware loaded\n");
+	snd_iprintf(buffer, "\n");
+}
+static void pcxhr_proc_gpo_write(struct snd_info_entry *entry,
+				 struct snd_info_buffer *buffer)
+{
+	struct snd_pcxhr *chip = entry->private_data;
+	struct pcxhr_mgr *mgr = chip->mgr;
+	char line[64];
+	int value;
+	/* commands available when embedded DSP is running */
+	if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)))
+		return;
+	while (!snd_info_get_line(buffer, line, sizeof(line))) {
+		if (sscanf(line, "GPO: 0x%x", &value) != 1)
+			continue;
+		hr222_write_gpo(mgr, value);	/* GP0 */
+	}
+}
+
 static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip)
 {
 	struct snd_info_entry *entry;
@@ -1342,6 +1376,13 @@
 		snd_info_set_text_ops(entry, chip, pcxhr_proc_info);
 	if (! snd_card_proc_new(chip->card, "sync", &entry))
 		snd_info_set_text_ops(entry, chip, pcxhr_proc_sync);
+	/* gpio available on stereo sound cards only */
+	if (chip->mgr->is_hr_stereo &&
+	    !snd_card_proc_new(chip->card, "gpio", &entry)) {
+		snd_info_set_text_ops(entry, chip, pcxhr_proc_gpio_read);
+		entry->c.text.write = pcxhr_proc_gpo_write;
+		entry->mode |= S_IWUSR;
+	}
 }
 /* end of proc interface */
 
@@ -1510,12 +1551,12 @@
 
 		snprintf(tmpid, sizeof(tmpid), "%s-%d",
 			 id[dev] ? id[dev] : card_name, i);
-		card = snd_card_new(idx, tmpid, THIS_MODULE, 0);
+		err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card);
 
-		if (! card) {
+		if (err < 0) {
 			snd_printk(KERN_ERR "cannot allocate the card %d\n", i);
 			pcxhr_free(mgr);
-			return -ENOMEM;
+			return err;
 		}
 
 		strcpy(card->driver, DRIVER_NAME);
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h
index 69d87de..bda776c 100644
--- a/sound/pci/pcxhr/pcxhr.h
+++ b/sound/pci/pcxhr/pcxhr.h
@@ -27,8 +27,8 @@
 #include <linux/mutex.h>
 #include <sound/pcm.h>
 
-#define PCXHR_DRIVER_VERSION		0x000905	/* 0.9.5 */
-#define PCXHR_DRIVER_VERSION_STRING	"0.9.5"		/* 0.9.5 */
+#define PCXHR_DRIVER_VERSION		0x000906	/* 0.9.6 */
+#define PCXHR_DRIVER_VERSION_STRING	"0.9.6"		/* 0.9.6 */
 
 
 #define PCXHR_MAX_CARDS		6
@@ -124,6 +124,7 @@
 
 	unsigned char xlx_cfg;		/* copy of PCXHR_XLX_CFG register */
 	unsigned char xlx_selmic;	/* copy of PCXHR_XLX_SELMIC register */
+	unsigned char dsp_reset;	/* copy of PCXHR_DSP_RESET register */
 };
 
 
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h
index bbbd66d..be01737 100644
--- a/sound/pci/pcxhr/pcxhr_core.h
+++ b/sound/pci/pcxhr/pcxhr_core.h
@@ -1,7 +1,7 @@
 /*
  * Driver for Digigram pcxhr compatible soundcards
  *
- * low level interface with interrupt ans message handling
+ * low level interface with interrupt and message handling
  *
  * Copyright (c) 2004 by Digigram <alsa@digigram.com>
  *
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
index 592743a..17cb123 100644
--- a/sound/pci/pcxhr/pcxhr_hwdep.c
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -471,16 +471,6 @@
 	return 0;
 }
 
-static int pcxhr_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
-static int pcxhr_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
 int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
 {
 	int err;
@@ -495,8 +485,6 @@
 
 	hw->iface = SNDRV_HWDEP_IFACE_PCXHR;
 	hw->private_data = mgr;
-	hw->ops.open = pcxhr_hwdep_open;
-	hw->ops.release = pcxhr_hwdep_release;
 	hw->ops.dsp_status = pcxhr_hwdep_dsp_status;
 	hw->ops.dsp_load = pcxhr_hwdep_dsp_load;
 	hw->exclusive = 1;
diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c
index ff01912..1cb82c0 100644
--- a/sound/pci/pcxhr/pcxhr_mix22.c
+++ b/sound/pci/pcxhr/pcxhr_mix22.c
@@ -53,6 +53,8 @@
 #define PCXHR_DSP_RESET_DSP	0x01
 #define PCXHR_DSP_RESET_MUTE	0x02
 #define PCXHR_DSP_RESET_CODEC	0x08
+#define PCXHR_DSP_RESET_GPO_OFFSET	5
+#define PCXHR_DSP_RESET_GPO_MASK	0x60
 
 /* values for PCHR_XLX_CFG register */
 #define PCXHR_CFG_SYNCDSP_MASK		0x80
@@ -81,6 +83,8 @@
 /* values for PCHR_XLX_STATUS register - READ */
 #define PCXHR_STAT_SRC_LOCK		0x01
 #define PCXHR_STAT_LEVEL_IN		0x02
+#define PCXHR_STAT_GPI_OFFSET		2
+#define PCXHR_STAT_GPI_MASK		0x0C
 #define PCXHR_STAT_MIC_CAPS		0x10
 /* values for PCHR_XLX_STATUS register - WRITE */
 #define PCXHR_STAT_FREQ_SYNC_MASK	0x01
@@ -291,10 +295,11 @@
 	PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
 		    PCXHR_DSP_RESET_DSP);
 	msleep(5);
-	PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
-		    PCXHR_DSP_RESET_DSP  |
-		    PCXHR_DSP_RESET_MUTE |
-		    PCXHR_DSP_RESET_CODEC);
+	mgr->dsp_reset = PCXHR_DSP_RESET_DSP  |
+			 PCXHR_DSP_RESET_MUTE |
+			 PCXHR_DSP_RESET_CODEC;
+	PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset);
+	/* hr222_write_gpo(mgr, 0); does the same */
 	msleep(5);
 
 	/* config AKM */
@@ -496,6 +501,33 @@
 }
 
 
+int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value)
+{
+	if (is_gpi) {
+		unsigned char reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
+		*value = (int)(reg & PCXHR_STAT_GPI_MASK) >>
+			      PCXHR_STAT_GPI_OFFSET;
+	} else {
+		*value = (int)(mgr->dsp_reset & PCXHR_DSP_RESET_GPO_MASK) >>
+			 PCXHR_DSP_RESET_GPO_OFFSET;
+	}
+	return 0;
+}
+
+
+int hr222_write_gpo(struct pcxhr_mgr *mgr, int value)
+{
+	unsigned char reg = mgr->dsp_reset & ~PCXHR_DSP_RESET_GPO_MASK;
+
+	reg |= (unsigned char)(value << PCXHR_DSP_RESET_GPO_OFFSET) &
+	       PCXHR_DSP_RESET_GPO_MASK;
+
+	PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, reg);
+	mgr->dsp_reset = reg;
+	return 0;
+}
+
+
 int hr222_update_analog_audio_level(struct snd_pcxhr *chip,
 				    int is_capture, int channel)
 {
diff --git a/sound/pci/pcxhr/pcxhr_mix22.h b/sound/pci/pcxhr/pcxhr_mix22.h
index 6b318b2..5a37a00 100644
--- a/sound/pci/pcxhr/pcxhr_mix22.h
+++ b/sound/pci/pcxhr/pcxhr_mix22.h
@@ -32,6 +32,9 @@
 			     enum pcxhr_clock_type clock_type,
 			     int *sample_rate);
 
+int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value);
+int hr222_write_gpo(struct pcxhr_mgr *mgr, int value);
+
 #define HR222_LINE_PLAYBACK_LEVEL_MIN		0	/* -25.5 dB */
 #define HR222_LINE_PLAYBACK_ZERO_LEVEL		51	/* 0.0 dB */
 #define HR222_LINE_PLAYBACK_LEVEL_MAX		99	/* +24.0 dB */
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c
index 2436e37..fec0493 100644
--- a/sound/pci/pcxhr/pcxhr_mixer.c
+++ b/sound/pci/pcxhr/pcxhr_mixer.c
@@ -789,11 +789,15 @@
 	if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) {
 		mutex_lock(&mgr->setup_mutex);
 		mgr->use_clock_type = ucontrol->value.enumerated.item[0];
-		if (mgr->use_clock_type)
+		rate = 0;
+		if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) {
 			pcxhr_get_external_clock(mgr, mgr->use_clock_type,
 						 &rate);
-		else
+		} else {
 			rate = mgr->sample_rate;
+			if (!rate)
+				rate = 48000;
+		}
 		if (rate) {
 			pcxhr_set_clock(mgr, rate);
 			if (mgr->sample_rate)
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 3caacfb..6f10344 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -2102,9 +2102,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	if ((err = snd_riptide_create(card, pci, &chip)) < 0) {
 		snd_card_free(card);
 		return err;
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index e7ef3a1..d7b966e 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1941,9 +1941,10 @@
 		return -ENOENT;
 	}
 
-	if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-				 sizeof(struct rme32))) == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct rme32), &card);
+	if (err < 0)
+		return err;
 	card->private_free = snd_rme32_card_free;
 	rme32 = (struct rme32 *) card->private_data;
 	rme32->card = card;
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 3fdd488..55fb1c1 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -2348,9 +2348,10 @@
 		dev++;
 		return -ENOENT;
 	}
-	if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-				 sizeof(struct rme96))) == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct rme96), &card);
+	if (err < 0)
+		return err;
 	card->private_free = snd_rme96_card_free;
 	rme96 = (struct rme96 *)card->private_data;	
 	rme96->card = card;
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 44d0c15..314e735 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -113,7 +113,7 @@
 
 /* the meters are regular i/o-mapped registers, but offset
    considerably from the rest. the peak registers are reset
-   when read; the least-significant 4 bits are full-scale counters; 
+   when read; the least-significant 4 bits are full-scale counters;
    the actual peak value is in the most-significant 24 bits.
 */
 
@@ -131,7 +131,7 @@
    26*3 values are read in ss mode
    14*3 in ds mode, with no gap between values
 */
-#define HDSP_9652_peakBase	7164	
+#define HDSP_9652_peakBase	7164
 #define HDSP_9652_rmsBase	4096
 
 /* c.f. the hdsp_9632_meters_t struct */
@@ -173,12 +173,12 @@
 #define HDSP_SPDIFEmphasis        (1<<10) /* 0=none, 1=on */
 #define HDSP_SPDIFNonAudio        (1<<11) /* 0=off, 1=on */
 #define HDSP_SPDIFOpticalOut      (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */
-#define HDSP_SyncRef2             (1<<13) 
-#define HDSP_SPDIFInputSelect0    (1<<14) 
-#define HDSP_SPDIFInputSelect1    (1<<15) 
-#define HDSP_SyncRef0             (1<<16) 
+#define HDSP_SyncRef2             (1<<13)
+#define HDSP_SPDIFInputSelect0    (1<<14)
+#define HDSP_SPDIFInputSelect1    (1<<15)
+#define HDSP_SyncRef0             (1<<16)
 #define HDSP_SyncRef1             (1<<17)
-#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */ 
+#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */
 #define HDSP_XLRBreakoutCable     (1<<20) /* For H9632 cards */
 #define HDSP_Midi0InterruptEnable (1<<22)
 #define HDSP_Midi1InterruptEnable (1<<23)
@@ -314,7 +314,7 @@
 #define HDSP_TimecodeSync       (1<<27)
 #define HDSP_AEBO          	(1<<28) /* H9632 specific Analog Extension Boards */
 #define HDSP_AEBI		(1<<29) /* 0 = present, 1 = absent */
-#define HDSP_midi0IRQPending    (1<<30) 
+#define HDSP_midi0IRQPending    (1<<30)
 #define HDSP_midi1IRQPending    (1<<31)
 
 #define HDSP_spdifFrequencyMask    (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
@@ -391,7 +391,7 @@
 #define HDSP_CHANNEL_BUFFER_BYTES    (4*HDSP_CHANNEL_BUFFER_SAMPLES)
 
 /* the size of the area we need to allocate for DMA transfers. the
-   size is the same regardless of the number of channels - the 
+   size is the same regardless of the number of channels - the
    Multiface still uses the same memory area.
 
    Note that we allocate 1 more channel than is apparently needed
@@ -460,7 +460,7 @@
 	unsigned char	      qs_in_channels;	     /* quad speed mode for H9632 */
 	unsigned char         ds_in_channels;
 	unsigned char         ss_in_channels;	    /* different for multiface/digiface */
-	unsigned char	      qs_out_channels;	    
+	unsigned char	      qs_out_channels;
 	unsigned char         ds_out_channels;
 	unsigned char         ss_out_channels;
 
@@ -502,9 +502,9 @@
 
 static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
 	/* Analog */
-	0, 1, 2, 3, 4, 5, 6, 7, 
+	0, 1, 2, 3, 4, 5, 6, 7,
 	/* ADAT 2 */
-	16, 17, 18, 19, 20, 21, 22, 23, 
+	16, 17, 18, 19, 20, 21, 22, 23,
 	/* SPDIF */
 	24, 25,
 	-1, -1, -1, -1, -1, -1, -1, -1
@@ -525,11 +525,11 @@
 	/* SPDIF */
 	8, 9,
 	/* Analog */
-	10, 11, 
+	10, 11,
 	/* AO4S-192 and AI4S-192 extension boards */
 	12, 13, 14, 15,
 	/* others don't exist */
-	-1, -1, -1, -1, -1, -1, -1, -1, 
+	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1
 };
 
@@ -539,7 +539,7 @@
 	/* SPDIF */
 	8, 9,
 	/* Analog */
-	10, 11, 
+	10, 11,
 	/* AO4S-192 and AI4S-192 extension boards */
 	12, 13, 14, 15,
 	/* others don't exist */
@@ -587,7 +587,7 @@
 static struct pci_device_id snd_hdsp_ids[] = {
 	{
 		.vendor = PCI_VENDOR_ID_XILINX,
-		.device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, 
+		.device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
 		.subvendor = PCI_ANY_ID,
 		.subdevice = PCI_ANY_ID,
 	}, /* RME Hammerfall-DSP */
@@ -653,7 +653,6 @@
 
 static int hdsp_check_for_iobox (struct hdsp *hdsp)
 {
-
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
 	if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) {
 		snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n");
@@ -661,7 +660,29 @@
 		return -EIO;
 	}
 	return 0;
+}
 
+static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops,
+			       unsigned int delay)
+{
+	unsigned int i;
+
+	if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
+		return 0;
+
+	for (i = 0; i != loops; ++i) {
+		if (hdsp_read(hdsp, HDSP_statusRegister) & HDSP_ConfigError)
+			msleep(delay);
+		else {
+			snd_printd("Hammerfall-DSP: iobox found after %ums!\n",
+				   i * delay);
+			return 0;
+		}
+	}
+
+	snd_printk("Hammerfall-DSP: no Digiface or Multiface connected!\n");
+	hdsp->state &= ~HDSP_FirmwareLoaded;
+	return -EIO;
 }
 
 static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
@@ -670,19 +691,19 @@
 	unsigned long flags;
 
 	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
-		
+
 		snd_printk ("Hammerfall-DSP: loading firmware\n");
 
 		hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
 		hdsp_write (hdsp, HDSP_fifoData, 0);
-		
+
 		if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
 			snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
 			return -EIO;
 		}
-		
+
 		hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
-		
+
 		for (i = 0; i < 24413; ++i) {
 			hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
 			if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
@@ -692,7 +713,7 @@
 		}
 
 		ssleep(3);
-		
+
 		if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
 			snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
 		    	return -EIO;
@@ -705,15 +726,15 @@
 #endif
 		hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
 		snd_printk ("Hammerfall-DSP: finished firmware loading\n");
-		
+
 	}
 	if (hdsp->state & HDSP_InitializationComplete) {
 		snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");
 		spin_lock_irqsave(&hdsp->lock, flags);
 		snd_hdsp_set_defaults(hdsp);
-		spin_unlock_irqrestore(&hdsp->lock, flags); 
+		spin_unlock_irqrestore(&hdsp->lock, flags);
 	}
-	
+
 	hdsp->state |= HDSP_FirmwareLoaded;
 
 	return 0;
@@ -722,7 +743,7 @@
 static int hdsp_get_iobox_version (struct hdsp *hdsp)
 {
 	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
-	
+
 		hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
 		hdsp_write (hdsp, HDSP_fifoData, 0);
 		if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0)
@@ -738,7 +759,7 @@
 			hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
 		} else {
 			hdsp->io_type = Digiface;
-		} 
+		}
 	} else {
 		/* firmware was already loaded, get iobox type */
 		if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
@@ -786,13 +807,13 @@
 
 
 static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout)
-{    
+{
 	int i;
 
 	/* the fifoStatus registers reports on how many words
 	   are available in the command FIFO.
 	*/
-	
+
 	for (i = 0; i < timeout; i++) {
 
 		if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
@@ -824,11 +845,11 @@
 
 	if (addr >= HDSP_MATRIX_MIXER_SIZE)
 		return -1;
-	
+
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
 
 		/* from martin bjornsen:
-		   
+
 		   "You can only write dwords to the
 		   mixer memory which contain two
 		   mixer values in the low and high
@@ -847,7 +868,7 @@
 
 		hdsp->mixer_matrix[addr] = data;
 
-		
+
 		/* `addr' addresses a 16-bit wide address, but
 		   the address space accessed via hdsp_write
 		   uses byte offsets. put another way, addr
@@ -856,17 +877,17 @@
 		   to access 0 to 2703 ...
 		*/
 		ad = addr/2;
-	
-		hdsp_write (hdsp, 4096 + (ad*4), 
-			    (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) + 
+
+		hdsp_write (hdsp, 4096 + (ad*4),
+			    (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
 			    hdsp->mixer_matrix[addr&0x7fe]);
-		
+
 		return 0;
 
 	} else {
 
 		ad = (addr << 16) + data;
-		
+
 		if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT))
 			return -1;
 
@@ -902,7 +923,7 @@
 
 	if (status & HDSP_SPDIFErrorFlag)
 		return 0;
-	
+
 	switch (rate_bits) {
 	case HDSP_spdifFrequency32KHz: return 32000;
 	case HDSP_spdifFrequency44_1KHz: return 44100;
@@ -910,13 +931,13 @@
 	case HDSP_spdifFrequency64KHz: return 64000;
 	case HDSP_spdifFrequency88_2KHz: return 88200;
 	case HDSP_spdifFrequency96KHz: return 96000;
-	case HDSP_spdifFrequency128KHz: 
+	case HDSP_spdifFrequency128KHz:
 		if (hdsp->io_type == H9632) return 128000;
 		break;
-	case HDSP_spdifFrequency176_4KHz: 
+	case HDSP_spdifFrequency176_4KHz:
 		if (hdsp->io_type == H9632) return 176400;
 		break;
-	case HDSP_spdifFrequency192KHz: 
+	case HDSP_spdifFrequency192KHz:
 		if (hdsp->io_type == H9632) return 192000;
 		break;
 	default:
@@ -1027,7 +1048,7 @@
 {
 	u64 n;
 	u32 r;
-	
+
 	if (rate >= 112000)
 		rate /= 4;
 	else if (rate >= 56000)
@@ -1053,35 +1074,35 @@
 	   there is no need for it (e.g. during module
 	   initialization).
 	*/
-	
-	if (!(hdsp->control_register & HDSP_ClockModeMaster)) {	
+
+	if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
 		if (called_internally) {
 			/* request from ctl or card initialization */
 			snd_printk(KERN_ERR "Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n");
 			return -1;
-		} else {		
+		} else {
 			/* hw_param request while in AutoSync mode */
 			int external_freq = hdsp_external_sample_rate(hdsp);
 			int spdif_freq = hdsp_spdif_sample_rate(hdsp);
-		
+
 			if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
 				snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n");
 			else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
-				snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n");			
+				snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n");
 			else if (rate != external_freq) {
 				snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n");
 				return -1;
-			}		
-		}	
+			}
+		}
 	}
 
 	current_rate = hdsp->system_sample_rate;
 
 	/* Changing from a "single speed" to a "double speed" rate is
 	   not allowed if any substreams are open. This is because
-	   such a change causes a shift in the location of 
+	   such a change causes a shift in the location of
 	   the DMA buffers and a reduction in the number of available
-	   buffers. 
+	   buffers.
 
 	   Note that a similar but essentially insoluble problem
 	   exists for externally-driven rate changes. All we can do
@@ -1089,7 +1110,7 @@
 
 	if (rate > 96000 && hdsp->io_type != H9632)
 		return -EINVAL;
-	
+
 	switch (rate) {
 	case 32000:
 		if (current_rate > 48000)
@@ -1179,7 +1200,7 @@
 			break;
 		}
 	}
-	
+
 	hdsp->system_sample_rate = rate;
 
 	return 0;
@@ -1245,16 +1266,16 @@
 	unsigned char buf[128];
 
 	/* Output is not interrupt driven */
-		
+
 	spin_lock_irqsave (&hmidi->lock, flags);
 	if (hmidi->output) {
 		if (!snd_rawmidi_transmit_empty (hmidi->output)) {
 			if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) {
 				if (n_pending > (int)sizeof (buf))
 					n_pending = sizeof (buf);
-				
+
 				if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
-					for (i = 0; i < to_write; ++i) 
+					for (i = 0; i < to_write; ++i)
 						snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]);
 				}
 			}
@@ -1325,14 +1346,14 @@
 {
 	struct hdsp_midi *hmidi = (struct hdsp_midi *) data;
 	unsigned long flags;
-	
+
 	snd_hdsp_midi_output_write(hmidi);
 	spin_lock_irqsave (&hmidi->lock, flags);
 
 	/* this does not bump hmidi->istimer, because the
 	   kernel automatically removed the timer when it
 	   expired, and we are now adding it back, thus
-	   leaving istimer wherever it was set before.  
+	   leaving istimer wherever it was set before.
 	*/
 
 	if (hmidi->istimer) {
@@ -1501,7 +1522,7 @@
 static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
 	return 0;
 }
@@ -1511,7 +1532,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
-	
+
 	val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
 	spin_lock_irq(&hdsp->lock);
 	change = val != hdsp->creg_spdif;
@@ -1530,7 +1551,7 @@
 static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
 	return 0;
 }
@@ -1540,7 +1561,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
-	
+
 	val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
 	spin_lock_irq(&hdsp->lock);
 	change = val != hdsp->creg_spdif_stream;
@@ -1602,7 +1623,7 @@
 static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
 	return 0;
 }
@@ -1612,7 +1633,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
@@ -1649,7 +1670,7 @@
 static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
 	return 0;
 }
@@ -1659,7 +1680,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
@@ -1693,7 +1714,7 @@
 static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
 	return 0;
 }
@@ -1703,7 +1724,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
@@ -1737,7 +1758,7 @@
 static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
 	return 0;
 }
@@ -1747,7 +1768,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
@@ -1781,7 +1802,7 @@
 static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
 	return 0;
 }
@@ -1791,7 +1812,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
@@ -1828,7 +1849,7 @@
 static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	switch (hdsp_spdif_sample_rate(hdsp)) {
 	case 32000:
 		ucontrol->value.enumerated.item[0] = 0;
@@ -1858,7 +1879,7 @@
 		ucontrol->value.enumerated.item[0] = 9;
 		break;
 	default:
-		ucontrol->value.enumerated.item[0] = 6;		
+		ucontrol->value.enumerated.item[0] = 6;
 	}
 	return 0;
 }
@@ -1882,7 +1903,7 @@
 static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
 	return 0;
 }
@@ -1899,7 +1920,7 @@
 static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};	
+	static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ;
@@ -1912,7 +1933,7 @@
 static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	switch (hdsp_external_sample_rate(hdsp)) {
 	case 32000:
 		ucontrol->value.enumerated.item[0] = 0;
@@ -1940,9 +1961,9 @@
 		break;
 	case 192000:
 		ucontrol->value.enumerated.item[0] = 9;
-		break;	
+		break;
 	default:
-		ucontrol->value.enumerated.item[0] = 6;		
+		ucontrol->value.enumerated.item[0] = 6;
 	}
 	return 0;
 }
@@ -1968,7 +1989,7 @@
 static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = {"Master", "Slave" };
-	
+
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	uinfo->value.enumerated.items = 2;
@@ -1981,7 +2002,7 @@
 static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
 	return 0;
 }
@@ -2018,7 +2039,7 @@
 		case 192000:
 			return 9;
 		default:
-			return 3;	
+			return 3;
 		}
 	} else {
 		return 0;
@@ -2032,7 +2053,7 @@
 	case HDSP_CLOCK_SOURCE_AUTOSYNC:
 		if (hdsp_external_sample_rate(hdsp) != 0) {
 		    if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) {
-			hdsp->control_register &= ~HDSP_ClockModeMaster;		
+			hdsp->control_register &= ~HDSP_ClockModeMaster;
 			hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
 			return 0;
 		    }
@@ -2043,7 +2064,7 @@
 		break;
 	case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
 		rate = 44100;
-		break;	    
+		break;
 	case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
 		rate = 48000;
 		break;
@@ -2078,13 +2099,13 @@
 {
 	static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" };
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	if (hdsp->io_type == H9632)
 	    uinfo->value.enumerated.items = 10;
 	else
-	    uinfo->value.enumerated.items = 7;	
+	    uinfo->value.enumerated.items = 7;
 	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]);
@@ -2094,7 +2115,7 @@
 static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
 	return 0;
 }
@@ -2104,7 +2125,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0];
@@ -2130,7 +2151,7 @@
 static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
 	return 0;
 }
@@ -2165,7 +2186,7 @@
 	case HDSP_DAGainMinus10dBV:
 		return 2;
 	default:
-		return 1;	
+		return 1;
 	}
 }
 
@@ -2180,8 +2201,8 @@
 		hdsp->control_register |= HDSP_DAGainPlus4dBu;
 		break;
 	case 2:
-		hdsp->control_register |= HDSP_DAGainMinus10dBV;		
-		break;	    
+		hdsp->control_register |= HDSP_DAGainMinus10dBV;
+		break;
 	default:
 		return -1;
 
@@ -2193,7 +2214,7 @@
 static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"};
-	
+
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	uinfo->value.enumerated.items = 3;
@@ -2206,7 +2227,7 @@
 static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
 	return 0;
 }
@@ -2216,7 +2237,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0];
@@ -2250,7 +2271,7 @@
 	case HDSP_ADGainLowGain:
 		return 2;
 	default:
-		return 1;	
+		return 1;
 	}
 }
 
@@ -2262,11 +2283,11 @@
 		hdsp->control_register |= HDSP_ADGainMinus10dBV;
 		break;
 	case 1:
-		hdsp->control_register |= HDSP_ADGainPlus4dBu;		
+		hdsp->control_register |= HDSP_ADGainPlus4dBu;
 		break;
 	case 2:
-		hdsp->control_register |= HDSP_ADGainLowGain;		
-		break;	    
+		hdsp->control_register |= HDSP_ADGainLowGain;
+		break;
 	default:
 		return -1;
 
@@ -2278,7 +2299,7 @@
 static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"};
-	
+
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	uinfo->value.enumerated.items = 3;
@@ -2291,7 +2312,7 @@
 static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
 	return 0;
 }
@@ -2301,7 +2322,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0];
@@ -2335,7 +2356,7 @@
 	case HDSP_PhoneGainMinus12dB:
 		return 2;
 	default:
-		return 0;	
+		return 0;
 	}
 }
 
@@ -2347,11 +2368,11 @@
 		hdsp->control_register |= HDSP_PhoneGain0dB;
 		break;
 	case 1:
-		hdsp->control_register |= HDSP_PhoneGainMinus6dB;		
+		hdsp->control_register |= HDSP_PhoneGainMinus6dB;
 		break;
 	case 2:
-		hdsp->control_register |= HDSP_PhoneGainMinus12dB;		
-		break;	    
+		hdsp->control_register |= HDSP_PhoneGainMinus12dB;
+		break;
 	default:
 		return -1;
 
@@ -2363,7 +2384,7 @@
 static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = {"0 dB", "-6 dB", "-12 dB"};
-	
+
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	uinfo->value.enumerated.items = 3;
@@ -2376,7 +2397,7 @@
 static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
 	return 0;
 }
@@ -2386,7 +2407,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0];
@@ -2432,7 +2453,7 @@
 static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
 	return 0;
 }
@@ -2442,7 +2463,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
@@ -2488,7 +2509,7 @@
 static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
 	return 0;
 }
@@ -2498,7 +2519,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
@@ -2576,7 +2597,7 @@
 {
 	static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 
@@ -2595,7 +2616,7 @@
 		uinfo->value.enumerated.items = 0;
 		break;
 	}
-		
+
 	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]);
@@ -2605,7 +2626,7 @@
 static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
 	return 0;
 }
@@ -2615,7 +2636,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change, max;
 	unsigned int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 
@@ -2664,7 +2685,7 @@
 	case HDSP_SelSyncRef_SPDIF:
 		return HDSP_AUTOSYNC_FROM_SPDIF;
 	case HDSP_SelSyncRefMask:
-		return HDSP_AUTOSYNC_FROM_NONE;	
+		return HDSP_AUTOSYNC_FROM_NONE;
 	case HDSP_SelSyncRef_ADAT1:
 		return HDSP_AUTOSYNC_FROM_ADAT1;
 	case HDSP_SelSyncRef_ADAT2:
@@ -2680,7 +2701,7 @@
 static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" };
-	
+
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	uinfo->value.enumerated.items = 7;
@@ -2693,7 +2714,7 @@
 static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
 	return 0;
 }
@@ -2727,7 +2748,7 @@
 static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
 	spin_unlock_irq(&hdsp->lock);
@@ -2739,7 +2760,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
@@ -2773,7 +2794,7 @@
 static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[0] = hdsp->precise_ptr;
 	spin_unlock_irq(&hdsp->lock);
@@ -2785,7 +2806,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
@@ -2819,7 +2840,7 @@
 static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
 	spin_unlock_irq(&hdsp->lock);
@@ -2831,7 +2852,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
@@ -2873,12 +2894,12 @@
 
 	source = ucontrol->value.integer.value[0];
 	destination = ucontrol->value.integer.value[1];
-	
+
 	if (source >= hdsp->max_channels)
 		addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination);
 	else
 		addr = hdsp_input_to_output_key(hdsp,source, destination);
-	
+
 	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
 	spin_unlock_irq(&hdsp->lock);
@@ -2926,7 +2947,7 @@
 
 static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = {"No Lock", "Lock", "Sync" };	
+	static char *texts[] = {"No Lock", "Lock", "Sync" };
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	uinfo->value.enumerated.items = 3;
@@ -2971,7 +2992,7 @@
 	int status = hdsp_read(hdsp, HDSP_statusRegister);
 	if (status & HDSP_SPDIFErrorFlag)
 		return 0;
-	else {	
+	else {
 		if (status & HDSP_SPDIFSync)
 			return 2;
 		else
@@ -3007,7 +3028,7 @@
 			return 1;
 	} else
 		return 0;
-}	
+}
 
 static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
@@ -3025,17 +3046,17 @@
 }
 
 static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx)
-{	
+{
 	int status = hdsp_read(hdsp, HDSP_statusRegister);
-	
+
 	if (status & (HDSP_Lock0>>idx)) {
 		if (status & (HDSP_Sync0>>idx))
 			return 2;
 		else
-			return 1;		
+			return 1;
 	} else
 		return 0;
-} 
+}
 
 static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
@@ -3053,7 +3074,7 @@
 		break;
 	case Multiface:
 	case H9632:
-		if (offset >= 1) 
+		if (offset >= 1)
 			return -EINVAL;
 		break;
 	default:
@@ -3115,7 +3136,7 @@
 static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
-	
+
 	ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
 	return 0;
 }
@@ -3125,7 +3146,7 @@
 	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
-	
+
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0];
@@ -3170,7 +3191,7 @@
 	.get =		snd_hdsp_control_spdif_mask_get,
 	.private_value = IEC958_AES0_NONAUDIO |
   			 IEC958_AES0_PROFESSIONAL |
-			 IEC958_AES0_CON_EMPHASIS,	                                                                                      
+			 IEC958_AES0_CON_EMPHASIS,
 },
 {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
@@ -3188,7 +3209,7 @@
 HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0),
 HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0),
 HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0),
-/* 'Sample Clock Source' complies with the alsa control naming scheme */ 
+/* 'Sample Clock Source' complies with the alsa control naming scheme */
 HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
 {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -3240,7 +3261,7 @@
 				return err;
 		}
 	}
-	
+
 	/* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
 	if (hdsp->io_type == H9632) {
 		for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
@@ -3259,7 +3280,7 @@
 }
 
 /*------------------------------------------------------------
-   /proc interface 
+   /proc interface
  ------------------------------------------------------------*/
 
 static void
@@ -3298,7 +3319,7 @@
 			}
 		}
 	}
-	
+
 	status = hdsp_read(hdsp, HDSP_statusRegister);
 	status2 = hdsp_read(hdsp, HDSP_status2Register);
 
@@ -3362,17 +3383,17 @@
 		break;
 		case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
 		clock_source = "Internal 192 kHz";
-		break;	
+		break;
 	default:
-		clock_source = "Error";		
+		clock_source = "Error";
 	}
 	snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source);
-			
+
 	if (hdsp_system_clock_mode(hdsp))
 		system_clock_mode = "Slave";
 	else
 		system_clock_mode = "Master";
-	
+
 	switch (hdsp_pref_sync_ref (hdsp)) {
 	case HDSP_SYNC_FROM_WORD:
 		pref_sync_ref = "Word Clock";
@@ -3397,7 +3418,7 @@
 		break;
 	}
 	snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref);
-	
+
 	switch (hdsp_autosync_ref (hdsp)) {
 	case HDSP_AUTOSYNC_FROM_WORD:
 		autosync_ref = "Word Clock";
@@ -3410,7 +3431,7 @@
 		break;
 	case HDSP_AUTOSYNC_FROM_NONE:
 		autosync_ref = "None";
-		break;	
+		break;
 	case HDSP_AUTOSYNC_FROM_ADAT1:
 		autosync_ref = "ADAT1";
 		break;
@@ -3425,14 +3446,14 @@
 		break;
 	}
 	snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref);
-	
+
 	snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp));
-	
+
 	snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode);
 
 	snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate);
 	snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No");
-		
+
 	snd_iprintf(buffer, "\n");
 
 	switch (hdsp_spdif_in(hdsp)) {
@@ -3452,7 +3473,7 @@
 		snd_iprintf(buffer, "IEC958 input: ???\n");
 		break;
 	}
-	
+
 	if (hdsp->control_register & HDSP_SPDIFOpticalOut)
 		snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n");
 	else
@@ -3510,13 +3531,13 @@
 		snd_iprintf (buffer, "SPDIF: No Lock\n");
 	else
 		snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock");
-	
+
 	x = status2 & HDSP_wc_sync;
 	if (status2 & HDSP_wc_lock)
 		snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock");
 	else
 		snd_iprintf (buffer, "Word Clock: No Lock\n");
-	
+
 	x = status & HDSP_TimecodeSync;
 	if (status & HDSP_TimecodeLock)
 		snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock");
@@ -3524,11 +3545,11 @@
 		snd_iprintf(buffer, "ADAT Sync: No Lock\n");
 
 	snd_iprintf(buffer, "\n");
-	
+
 	/* Informations about H9632 specific controls */
 	if (hdsp->io_type == H9632) {
 		char *tmp;
-	
+
 		switch (hdsp_ad_gain(hdsp)) {
 		case 0:
 			tmp = "-10 dBV";
@@ -3554,7 +3575,7 @@
 			break;
 		}
 		snd_iprintf(buffer, "DA Gain : %s\n", tmp);
-		
+
 		switch (hdsp_phone_gain(hdsp)) {
 		case 0:
 			tmp = "0 dB";
@@ -3568,8 +3589,8 @@
 		}
 		snd_iprintf(buffer, "Phones Gain : %s\n", tmp);
 
-		snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no");	
-		
+		snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no");
+
 		if (hdsp->control_register & HDSP_AnalogExtensionBoard)
 			snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n");
 		else
@@ -3632,18 +3653,18 @@
 
 	/* set defaults:
 
-	   SPDIF Input via Coax 
+	   SPDIF Input via Coax
 	   Master clock mode
 	   maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer,
 	                    which implies 2 4096 sample, 32Kbyte periods).
-           Enable line out.			    
+           Enable line out.
 	 */
 
-	hdsp->control_register = HDSP_ClockModeMaster | 
-		                 HDSP_SPDIFInputCoaxial | 
-		                 hdsp_encode_latency(7) | 
+	hdsp->control_register = HDSP_ClockModeMaster |
+		                 HDSP_SPDIFInputCoaxial |
+		                 hdsp_encode_latency(7) |
 		                 HDSP_LineOut;
-	
+
 
 	hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
 
@@ -3661,7 +3682,7 @@
 	hdsp_compute_period_size(hdsp);
 
 	/* silence everything */
-	
+
 	for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i)
 		hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN;
 
@@ -3669,7 +3690,7 @@
 		if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN))
 			return -EIO;
 	}
-	
+
 	/* H9632 specific defaults */
 	if (hdsp->io_type == H9632) {
 		hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
@@ -3687,12 +3708,12 @@
 static void hdsp_midi_tasklet(unsigned long arg)
 {
 	struct hdsp *hdsp = (struct hdsp *)arg;
-	
+
 	if (hdsp->midi[0].pending)
 		snd_hdsp_midi_input_read (&hdsp->midi[0]);
 	if (hdsp->midi[1].pending)
 		snd_hdsp_midi_input_read (&hdsp->midi[1]);
-} 
+}
 
 static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
 {
@@ -3704,7 +3725,7 @@
 	unsigned int midi0status;
 	unsigned int midi1status;
 	int schedule = 0;
-	
+
 	status = hdsp_read(hdsp, HDSP_statusRegister);
 
 	audio = status & HDSP_audioIRQPending;
@@ -3718,15 +3739,18 @@
 
 	midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff;
 	midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff;
-	
+
+	if (!(hdsp->state & HDSP_InitializationComplete))
+		return IRQ_HANDLED;
+
 	if (audio) {
 		if (hdsp->capture_substream)
 			snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
-		
+
 		if (hdsp->playback_substream)
 			snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
 	}
-	
+
 	if (midi0 && midi0status) {
 		if (hdsp->use_midi_tasklet) {
 			/* we disable interrupts for this input until processing is done */
@@ -3769,10 +3793,10 @@
 
         if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels))
 		return NULL;
-        
+
 	if ((mapped_channel = hdsp->channel_map[channel]) < 0)
 		return NULL;
-	
+
 	if (stream == SNDRV_PCM_STREAM_CAPTURE)
 		return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
 	else
@@ -3965,7 +3989,7 @@
 	struct hdsp *hdsp = snd_pcm_substream_chip(substream);
 	struct snd_pcm_substream *other;
 	int running;
-	
+
 	if (hdsp_check_for_iobox (hdsp))
 		return -EIO;
 
@@ -4059,10 +4083,10 @@
 	.formats =		SNDRV_PCM_FMTBIT_S32_LE,
 #endif
 	.rates =		(SNDRV_PCM_RATE_32000 |
-				 SNDRV_PCM_RATE_44100 | 
-				 SNDRV_PCM_RATE_48000 | 
-				 SNDRV_PCM_RATE_64000 | 
-				 SNDRV_PCM_RATE_88200 | 
+				 SNDRV_PCM_RATE_44100 |
+				 SNDRV_PCM_RATE_48000 |
+				 SNDRV_PCM_RATE_64000 |
+				 SNDRV_PCM_RATE_88200 |
 				 SNDRV_PCM_RATE_96000),
 	.rate_min =		32000,
 	.rate_max =		96000,
@@ -4088,10 +4112,10 @@
 	.formats =		SNDRV_PCM_FMTBIT_S32_LE,
 #endif
 	.rates =		(SNDRV_PCM_RATE_32000 |
-				 SNDRV_PCM_RATE_44100 | 
-				 SNDRV_PCM_RATE_48000 | 
-				 SNDRV_PCM_RATE_64000 | 
-				 SNDRV_PCM_RATE_88200 | 
+				 SNDRV_PCM_RATE_44100 |
+				 SNDRV_PCM_RATE_48000 |
+				 SNDRV_PCM_RATE_64000 |
+				 SNDRV_PCM_RATE_88200 |
 				 SNDRV_PCM_RATE_96000),
 	.rate_min =		32000,
 	.rate_max =		96000,
@@ -4170,7 +4194,7 @@
 			.max = hdsp->qs_in_channels,
 			.integer = 1,
 		};
-		return snd_interval_refine(c, &t);	
+		return snd_interval_refine(c, &t);
 	} else if (r->min > 48000 && r->max <= 96000) {
 		struct snd_interval t = {
 			.min = hdsp->ds_in_channels,
@@ -4201,7 +4225,7 @@
 			.max = hdsp->qs_out_channels,
 			.integer = 1,
 		};
-		return snd_interval_refine(c, &t);	
+		return snd_interval_refine(c, &t);
 	} else if (r->min > 48000 && r->max <= 96000) {
 		struct snd_interval t = {
 			.min = hdsp->ds_out_channels,
@@ -4318,8 +4342,8 @@
 	if (hdsp->io_type == H9632) {
 		runtime->hw.channels_min = hdsp->qs_out_channels;
 		runtime->hw.channels_max = hdsp->ss_out_channels;
-	}	
-	
+	}
+
 	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 			     snd_hdsp_hw_rule_out_channels, hdsp,
 			     SNDRV_PCM_HW_PARAM_CHANNELS, -1);
@@ -4413,13 +4437,6 @@
 	return 0;
 }
 
-static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
-{
-	/* we have nothing to initialize but the call is required */
-	return 0;
-}
-
-
 /* helper functions for copying meter values */
 static inline int copy_u32_le(void __user *dest, void __iomem *src)
 {
@@ -4536,7 +4553,7 @@
 				hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
 				hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
 			return -EFAULT;
-		if (copy_u64_le(&peak_rms->input_rms[i], 
+		if (copy_u64_le(&peak_rms->input_rms[i],
 				hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
 				hdsp->iobase + HDSP_inputRmsLevel + i * 8))
 			return -EFAULT;
@@ -4546,7 +4563,7 @@
 
 static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct hdsp *hdsp = (struct hdsp *)hw->private_data;	
+	struct hdsp *hdsp = (struct hdsp *)hw->private_data;
 	void __user *argp = (void __user *)arg;
 	int err;
 
@@ -4580,7 +4597,7 @@
 		struct hdsp_config_info info;
 		unsigned long flags;
 		int i;
-		
+
 		err = hdsp_check_for_iobox(hdsp);
 		if (err < 0)
 			return err;
@@ -4614,7 +4631,7 @@
 			info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
 			info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp);
 			info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp);
-		
+
 		}
 		if (hdsp->io_type == H9632 || hdsp->io_type == H9652)
 			info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp);
@@ -4625,7 +4642,7 @@
 	}
 	case SNDRV_HDSP_IOCTL_GET_9632_AEB: {
 		struct hdsp_9632_aeb h9632_aeb;
-		
+
 		if (hdsp->io_type != H9632) return -EINVAL;
 		h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS;
 		h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS;
@@ -4636,7 +4653,7 @@
 	case SNDRV_HDSP_IOCTL_GET_VERSION: {
 		struct hdsp_version hdsp_version;
 		int err;
-		
+
 		if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
 		if (hdsp->io_type == Undefined) {
 			if ((err = hdsp_get_iobox_version(hdsp)) < 0)
@@ -4652,7 +4669,7 @@
 		struct hdsp_firmware __user *firmware;
 		u32 __user *firmware_data;
 		int err;
-		
+
 		if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
 		/* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
 		if (hdsp->io_type == Undefined) return -EINVAL;
@@ -4665,25 +4682,25 @@
 
 		if (get_user(firmware_data, &firmware->firmware_data))
 			return -EFAULT;
-		
+
 		if (hdsp_check_for_iobox (hdsp))
 			return -EIO;
 
 		if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0)
 			return -EFAULT;
-		
+
 		hdsp->state |= HDSP_FirmwareCached;
 
 		if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
 			return err;
-		
+
 		if (!(hdsp->state & HDSP_InitializationComplete)) {
 			if ((err = snd_hdsp_enable_io(hdsp)) < 0)
 				return err;
-			
-			snd_hdsp_initialize_channels(hdsp);		
+
+			snd_hdsp_initialize_channels(hdsp);
 			snd_hdsp_initialize_midi_flush(hdsp);
-	    
+
 			if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
 				snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
 				return err;
@@ -4730,18 +4747,16 @@
 {
 	struct snd_hwdep *hw;
 	int err;
-	
+
 	if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0)
 		return err;
-		
+
 	hdsp->hwdep = hw;
 	hw->private_data = hdsp;
 	strcpy(hw->name, "HDSP hwdep interface");
 
-	hw->ops.open = snd_hdsp_hwdep_dummy_op;
 	hw->ops.ioctl = snd_hdsp_hwdep_ioctl;
-	hw->ops.release = snd_hdsp_hwdep_dummy_op;
-		
+
 	return 0;
 }
 
@@ -4774,24 +4789,24 @@
 static int snd_hdsp_enable_io (struct hdsp *hdsp)
 {
 	int i;
-	
+
 	if (hdsp_fifo_wait (hdsp, 0, 100)) {
 		snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n");
 		return -EIO;
 	}
-	
+
 	for (i = 0; i < hdsp->max_channels; ++i) {
 		hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1);
 		hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
 	}
-	
+
 	return 0;
 }
 
 static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
 {
 	int status, aebi_channels, aebo_channels;
-	
+
 	switch (hdsp->io_type) {
 	case Digiface:
 		hdsp->card_name = "RME Hammerfall DSP + Digiface";
@@ -4804,7 +4819,7 @@
 		hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS;
 		hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS;
 		break;
-	
+
 	case H9632:
 		status = hdsp_read(hdsp, HDSP_statusRegister);
 		/* HDSP_AEBx bits are low when AEB are connected */
@@ -4824,7 +4839,7 @@
 		hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS;
 		hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS;
 		break;
-		
+
 	default:
  		/* should never get here */
 		break;
@@ -4840,12 +4855,12 @@
 static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp)
 {
 	int err;
-	
+
 	if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
 		snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n");
 		return err;
 	}
-	
+
 
 	if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
 		snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n");
@@ -4876,19 +4891,19 @@
 		snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n");
 		return err;
 	}
-	
+
 	if (!(hdsp->state & HDSP_InitializationComplete)) {
 		strcpy(card->shortname, "Hammerfall DSP");
-		sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, 
+		sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
 			hdsp->port, hdsp->irq);
-	    
+
 		if ((err = snd_card_register(card)) < 0) {
 			snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n");
 			return err;
 		}
 		hdsp->state |= HDSP_InitializationComplete;
 	}
-	
+
 	return 0;
 }
 
@@ -4899,7 +4914,7 @@
 	const char *fwfile;
 	const struct firmware *fw;
 	int err;
-		
+
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
 		return 0;
 	if (hdsp->io_type == Undefined) {
@@ -4908,7 +4923,7 @@
 		if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
 			return 0;
 	}
-	
+
 	/* caution: max length of firmware filename is 30! */
 	switch (hdsp->io_type) {
 	case Multiface:
@@ -4942,12 +4957,12 @@
 	memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
 
 	release_firmware(fw);
-		
+
 	hdsp->state |= HDSP_FirmwareCached;
 
 	if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
 		return err;
-		
+
 	if (!(hdsp->state & HDSP_InitializationComplete)) {
 		if ((err = snd_hdsp_enable_io(hdsp)) < 0)
 			return err;
@@ -4994,14 +5009,14 @@
 	hdsp->max_channels = 26;
 
 	hdsp->card = card;
-	
+
 	spin_lock_init(&hdsp->lock);
 
 	tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
-	
+
 	pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
 	hdsp->firmware_rev &= 0xff;
-	
+
 	/* From Martin Bjoernsen :
 	    "It is important that the card's latency timer register in
 	    the PCI configuration space is set to a value much larger
@@ -5010,7 +5025,7 @@
 	    to its maximum 255 to avoid problems with some computers."
 	*/
 	pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF);
-	
+
 	strcpy(card->driver, "H-DSP");
 	strcpy(card->mixername, "Xilinx FPGA");
 
@@ -5024,7 +5039,7 @@
 	} else {
 		hdsp->card_name = "RME HDSP 9632";
 		hdsp->max_channels = 16;
-		is_9632 = 1;	
+		is_9632 = 1;
 	}
 
 	if ((err = pci_enable_device(pci)) < 0)
@@ -5053,12 +5068,12 @@
 
 	if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
 		return err;
-	
-	if (!is_9652 && !is_9632) {
-		/* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
-		ssleep(2);
 
-		err = hdsp_check_for_iobox(hdsp);
+	if (!is_9652 && !is_9632) {
+		/* we wait a maximum of 10 seconds to let freshly
+		 * inserted cardbus cards do their hardware init */
+		err = hdsp_wait_for_iobox(hdsp, 1000, 10);
+
 		if (err < 0)
 			return err;
 
@@ -5080,35 +5095,35 @@
 				return err;
 			return 0;
 		} else {
-			snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n");	    
+			snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n");
 			if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
 				hdsp->io_type = Multiface;
-			else 
+			else
 				hdsp->io_type = Digiface;
 		}
 	}
-	
+
 	if ((err = snd_hdsp_enable_io(hdsp)) != 0)
 		return err;
-	
+
 	if (is_9652)
 	        hdsp->io_type = H9652;
-	
+
 	if (is_9632)
 		hdsp->io_type = H9632;
 
 	if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
 		return err;
-	
+
 	snd_hdsp_initialize_channels(hdsp);
 	snd_hdsp_initialize_midi_flush(hdsp);
 
-	hdsp->state |= HDSP_FirmwareLoaded;	
+	hdsp->state |= HDSP_FirmwareLoaded;
 
 	if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0)
 		return err;
 
-	return 0;	
+	return 0;
 }
 
 static int snd_hdsp_free(struct hdsp *hdsp)
@@ -5124,13 +5139,13 @@
 		free_irq(hdsp->irq, (void *)hdsp);
 
 	snd_hdsp_free_buffers(hdsp);
-	
+
 	if (hdsp->iobase)
 		iounmap(hdsp->iobase);
 
 	if (hdsp->port)
 		pci_release_regions(hdsp->pci);
-		
+
 	pci_disable_device(hdsp->pci);
 	return 0;
 }
@@ -5158,8 +5173,10 @@
 		return -ENOENT;
 	}
 
-	if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp))))
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct hdsp), &card);
+	if (err < 0)
+		return err;
 
 	hdsp = (struct hdsp *) card->private_data;
 	card->private_free = snd_hdsp_card_free;
@@ -5173,7 +5190,7 @@
 	}
 
 	strcpy(card->shortname, "Hammerfall DSP");
-	sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, 
+	sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
 		hdsp->port, hdsp->irq);
 
 	if ((err = snd_card_register(card)) < 0) {
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 71231cf..bac2dc0 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -4100,13 +4100,6 @@
 	return 0;
 }
 
-static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file)
-{
-	/* we have nothing to initialize but the call is required */
-	return 0;
-}
-
-
 static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
 				 unsigned int cmd, unsigned long arg)
 {
@@ -4213,9 +4206,7 @@
 	hw->private_data = hdspm;
 	strcpy(hw->name, "HDSPM hwdep interface");
 
-	hw->ops.open = snd_hdspm_hwdep_dummy_op;
 	hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
-	hw->ops.release = snd_hdspm_hwdep_dummy_op;
 
 	return 0;
 }
@@ -4503,10 +4494,10 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev],
-			    THIS_MODULE, sizeof(struct hdspm));
-	if (!card)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev],
+			      THIS_MODULE, sizeof(struct hdspm), &card);
+	if (err < 0)
+		return err;
 
 	hdspm = card->private_data;
 	card->private_free = snd_hdspm_card_free;
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 2570907..bc539ab 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -2594,11 +2594,11 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_rme9652));
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_rme9652), &card);
 
-	if (!card)
-		return -ENOMEM;
+	if (err < 0)
+		return err;
 
 	rme9652 = (struct snd_rme9652 *) card->private_data;
 	card->private_free = snd_rme9652_card_free;
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index df2007e..baf6d8e 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -1387,9 +1387,8 @@
 	if (!enable)
 		goto error_out;
 
-	rc = -ENOMEM;
-	card = snd_card_new(index, id, THIS_MODULE, sizeof(*sis));
-	if (!card)
+	rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card);
+	if (rc < 0)
 		goto error_out;
 
 	strcpy(card->driver, "SiS7019");
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index cd408b8..d989215 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -273,7 +273,8 @@
 	outl(count, sonic->dmaa_port + SV_DMA_COUNT0);
 	outb(0x18, sonic->dmaa_port + SV_DMA_MODE);
 #if 0
-	printk("program dmaa: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmaa_port + SV_DMA_ADDR0));
+	printk(KERN_DEBUG "program dmaa: addr = 0x%x, paddr = 0x%x\n",
+	       addr, inl(sonic->dmaa_port + SV_DMA_ADDR0));
 #endif
 }
 
@@ -288,7 +289,8 @@
 	outl(count, sonic->dmac_port + SV_DMA_COUNT0);
 	outb(0x14, sonic->dmac_port + SV_DMA_MODE);
 #if 0
-	printk("program dmac: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmac_port + SV_DMA_ADDR0));
+	printk(KERN_DEBUG "program dmac: addr = 0x%x, paddr = 0x%x\n",
+	       addr, inl(sonic->dmac_port + SV_DMA_ADDR0));
 #endif
 }
 
@@ -355,71 +357,104 @@
 #if 0
 static void snd_sonicvibes_debug(struct sonicvibes * sonic)
 {
-	printk("SV REGS:          INDEX = 0x%02x  ", inb(SV_REG(sonic, INDEX)));
+	printk(KERN_DEBUG
+	       "SV REGS:          INDEX = 0x%02x  ", inb(SV_REG(sonic, INDEX)));
 	printk("                 STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS)));
-	printk("  0x00: left input      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x00));
+	printk(KERN_DEBUG
+	       "  0x00: left input      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x00));
 	printk("  0x20: synth rate low  = 0x%02x\n", snd_sonicvibes_in(sonic, 0x20));
-	printk("  0x01: right input     = 0x%02x  ", snd_sonicvibes_in(sonic, 0x01));
+	printk(KERN_DEBUG
+	       "  0x01: right input     = 0x%02x  ", snd_sonicvibes_in(sonic, 0x01));
 	printk("  0x21: synth rate high = 0x%02x\n", snd_sonicvibes_in(sonic, 0x21));
-	printk("  0x02: left AUX1       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x02));
+	printk(KERN_DEBUG
+	       "  0x02: left AUX1       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x02));
 	printk("  0x22: ADC clock       = 0x%02x\n", snd_sonicvibes_in(sonic, 0x22));
-	printk("  0x03: right AUX1      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x03));
+	printk(KERN_DEBUG
+	       "  0x03: right AUX1      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x03));
 	printk("  0x23: ADC alt rate    = 0x%02x\n", snd_sonicvibes_in(sonic, 0x23));
-	printk("  0x04: left CD         = 0x%02x  ", snd_sonicvibes_in(sonic, 0x04));
+	printk(KERN_DEBUG
+	       "  0x04: left CD         = 0x%02x  ", snd_sonicvibes_in(sonic, 0x04));
 	printk("  0x24: ADC pll M       = 0x%02x\n", snd_sonicvibes_in(sonic, 0x24));
-	printk("  0x05: right CD        = 0x%02x  ", snd_sonicvibes_in(sonic, 0x05));
+	printk(KERN_DEBUG
+	       "  0x05: right CD        = 0x%02x  ", snd_sonicvibes_in(sonic, 0x05));
 	printk("  0x25: ADC pll N       = 0x%02x\n", snd_sonicvibes_in(sonic, 0x25));
-	printk("  0x06: left line       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x06));
+	printk(KERN_DEBUG
+	       "  0x06: left line       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x06));
 	printk("  0x26: Synth pll M     = 0x%02x\n", snd_sonicvibes_in(sonic, 0x26));
-	printk("  0x07: right line      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x07));
+	printk(KERN_DEBUG
+	       "  0x07: right line      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x07));
 	printk("  0x27: Synth pll N     = 0x%02x\n", snd_sonicvibes_in(sonic, 0x27));
-	printk("  0x08: MIC             = 0x%02x  ", snd_sonicvibes_in(sonic, 0x08));
+	printk(KERN_DEBUG
+	       "  0x08: MIC             = 0x%02x  ", snd_sonicvibes_in(sonic, 0x08));
 	printk("  0x28: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x28));
-	printk("  0x09: Game port       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x09));
+	printk(KERN_DEBUG
+	       "  0x09: Game port       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x09));
 	printk("  0x29: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x29));
-	printk("  0x0a: left synth      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0a));
+	printk(KERN_DEBUG
+	       "  0x0a: left synth      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0a));
 	printk("  0x2a: MPU401          = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2a));
-	printk("  0x0b: right synth     = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0b));
+	printk(KERN_DEBUG
+	       "  0x0b: right synth     = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0b));
 	printk("  0x2b: drive ctrl      = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2b));
-	printk("  0x0c: left AUX2       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0c));
+	printk(KERN_DEBUG
+	       "  0x0c: left AUX2       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0c));
 	printk("  0x2c: SRS space       = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2c));
-	printk("  0x0d: right AUX2      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0d));
+	printk(KERN_DEBUG
+	       "  0x0d: right AUX2      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0d));
 	printk("  0x2d: SRS center      = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2d));
-	printk("  0x0e: left analog     = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0e));
+	printk(KERN_DEBUG
+	       "  0x0e: left analog     = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0e));
 	printk("  0x2e: wave source     = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2e));
-	printk("  0x0f: right analog    = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0f));
+	printk(KERN_DEBUG
+	       "  0x0f: right analog    = 0x%02x  ", snd_sonicvibes_in(sonic, 0x0f));
 	printk("  0x2f: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2f));
-	printk("  0x10: left PCM        = 0x%02x  ", snd_sonicvibes_in(sonic, 0x10));
+	printk(KERN_DEBUG
+	       "  0x10: left PCM        = 0x%02x  ", snd_sonicvibes_in(sonic, 0x10));
 	printk("  0x30: analog power    = 0x%02x\n", snd_sonicvibes_in(sonic, 0x30));
-	printk("  0x11: right PCM       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x11));
+	printk(KERN_DEBUG
+	       "  0x11: right PCM       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x11));
 	printk("  0x31: analog power    = 0x%02x\n", snd_sonicvibes_in(sonic, 0x31));
-	printk("  0x12: DMA data format = 0x%02x  ", snd_sonicvibes_in(sonic, 0x12));
+	printk(KERN_DEBUG
+	       "  0x12: DMA data format = 0x%02x  ", snd_sonicvibes_in(sonic, 0x12));
 	printk("  0x32: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x32));
-	printk("  0x13: P/C enable      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x13));
+	printk(KERN_DEBUG
+	       "  0x13: P/C enable      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x13));
 	printk("  0x33: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x33));
-	printk("  0x14: U/D button      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x14));
+	printk(KERN_DEBUG
+	       "  0x14: U/D button      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x14));
 	printk("  0x34: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x34));
-	printk("  0x15: revision        = 0x%02x  ", snd_sonicvibes_in(sonic, 0x15));
+	printk(KERN_DEBUG
+	       "  0x15: revision        = 0x%02x  ", snd_sonicvibes_in(sonic, 0x15));
 	printk("  0x35: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x35));
-	printk("  0x16: ADC output ctrl = 0x%02x  ", snd_sonicvibes_in(sonic, 0x16));
+	printk(KERN_DEBUG
+	       "  0x16: ADC output ctrl = 0x%02x  ", snd_sonicvibes_in(sonic, 0x16));
 	printk("  0x36: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x36));
-	printk("  0x17: ---             = 0x%02x  ", snd_sonicvibes_in(sonic, 0x17));
+	printk(KERN_DEBUG
+	       "  0x17: ---             = 0x%02x  ", snd_sonicvibes_in(sonic, 0x17));
 	printk("  0x37: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x37));
-	printk("  0x18: DMA A upper cnt = 0x%02x  ", snd_sonicvibes_in(sonic, 0x18));
+	printk(KERN_DEBUG
+	       "  0x18: DMA A upper cnt = 0x%02x  ", snd_sonicvibes_in(sonic, 0x18));
 	printk("  0x38: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x38));
-	printk("  0x19: DMA A lower cnt = 0x%02x  ", snd_sonicvibes_in(sonic, 0x19));
+	printk(KERN_DEBUG
+	       "  0x19: DMA A lower cnt = 0x%02x  ", snd_sonicvibes_in(sonic, 0x19));
 	printk("  0x39: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x39));
-	printk("  0x1a: ---             = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1a));
+	printk(KERN_DEBUG
+	       "  0x1a: ---             = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1a));
 	printk("  0x3a: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3a));
-	printk("  0x1b: ---             = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1b));
+	printk(KERN_DEBUG
+	       "  0x1b: ---             = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1b));
 	printk("  0x3b: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3b));
-	printk("  0x1c: DMA C upper cnt = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1c));
+	printk(KERN_DEBUG
+	       "  0x1c: DMA C upper cnt = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1c));
 	printk("  0x3c: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3c));
-	printk("  0x1d: DMA C upper cnt = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1d));
+	printk(KERN_DEBUG
+	       "  0x1d: DMA C upper cnt = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1d));
 	printk("  0x3d: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3d));
-	printk("  0x1e: PCM rate low    = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1e));
+	printk(KERN_DEBUG
+	       "  0x1e: PCM rate low    = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1e));
 	printk("  0x3e: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3e));
-	printk("  0x1f: PCM rate high   = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1f));
+	printk(KERN_DEBUG
+	       "  0x1f: PCM rate high   = 0x%02x  ", snd_sonicvibes_in(sonic, 0x1f));
 	printk("  0x3f: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3f));
 }
 
@@ -476,8 +511,8 @@
 	*res_m = m;
 	*res_n = n;
 #if 0
-	printk("metric = %i, xm = %i, xn = %i\n", metric, xm, xn);
-	printk("pll: m = 0x%x, r = 0x%x, n = 0x%x\n", reg, m, r, n);
+	printk(KERN_DEBUG "metric = %i, xm = %i, xn = %i\n", metric, xm, xn);
+	printk(KERN_DEBUG "pll: m = 0x%x, r = 0x%x, n = 0x%x\n", reg, m, r, n);
 #endif
 }
 
@@ -1423,9 +1458,9 @@
 		return -ENOENT;
 	}
  
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	for (idx = 0; idx < 5; idx++) {
 		if (pci_resource_start(pci, idx) == 0 ||
 		    !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index d94b16f..21cef97 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -89,9 +89,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	if ((err = snd_trident_create(card, pci,
 				      pcm_channels[dev],
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index c612b43..a9da9c1 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -68,40 +68,40 @@
 {
 	unsigned int val, tmp;
 
-	printk("Trident voice %i:\n", voice);
+	printk(KERN_DEBUG "Trident voice %i:\n", voice);
 	outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR));
 	val = inl(TRID_REG(trident, CH_LBA));
-	printk("LBA: 0x%x\n", val);
+	printk(KERN_DEBUG "LBA: 0x%x\n", val);
 	val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
-	printk("GVSel: %i\n", val >> 31);
-	printk("Pan: 0x%x\n", (val >> 24) & 0x7f);
-	printk("Vol: 0x%x\n", (val >> 16) & 0xff);
-	printk("CTRL: 0x%x\n", (val >> 12) & 0x0f);
-	printk("EC: 0x%x\n", val & 0x0fff);
+	printk(KERN_DEBUG "GVSel: %i\n", val >> 31);
+	printk(KERN_DEBUG "Pan: 0x%x\n", (val >> 24) & 0x7f);
+	printk(KERN_DEBUG "Vol: 0x%x\n", (val >> 16) & 0xff);
+	printk(KERN_DEBUG "CTRL: 0x%x\n", (val >> 12) & 0x0f);
+	printk(KERN_DEBUG "EC: 0x%x\n", val & 0x0fff);
 	if (trident->device != TRIDENT_DEVICE_ID_NX) {
 		val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS));
-		printk("CSO: 0x%x\n", val >> 16);
+		printk(KERN_DEBUG "CSO: 0x%x\n", val >> 16);
 		printk("Alpha: 0x%x\n", (val >> 4) & 0x0fff);
-		printk("FMS: 0x%x\n", val & 0x0f);
+		printk(KERN_DEBUG "FMS: 0x%x\n", val & 0x0f);
 		val = inl(TRID_REG(trident, CH_DX_ESO_DELTA));
-		printk("ESO: 0x%x\n", val >> 16);
-		printk("Delta: 0x%x\n", val & 0xffff);
+		printk(KERN_DEBUG "ESO: 0x%x\n", val >> 16);
+		printk(KERN_DEBUG "Delta: 0x%x\n", val & 0xffff);
 		val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL));
 	} else {		// TRIDENT_DEVICE_ID_NX
 		val = inl(TRID_REG(trident, CH_NX_DELTA_CSO));
 		tmp = (val >> 24) & 0xff;
-		printk("CSO: 0x%x\n", val & 0x00ffffff);
+		printk(KERN_DEBUG "CSO: 0x%x\n", val & 0x00ffffff);
 		val = inl(TRID_REG(trident, CH_NX_DELTA_ESO));
 		tmp |= (val >> 16) & 0xff00;
-		printk("Delta: 0x%x\n", tmp);
-		printk("ESO: 0x%x\n", val & 0x00ffffff);
+		printk(KERN_DEBUG "Delta: 0x%x\n", tmp);
+		printk(KERN_DEBUG "ESO: 0x%x\n", val & 0x00ffffff);
 		val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL));
-		printk("Alpha: 0x%x\n", val >> 20);
-		printk("FMS: 0x%x\n", (val >> 16) & 0x0f);
+		printk(KERN_DEBUG "Alpha: 0x%x\n", val >> 20);
+		printk(KERN_DEBUG "FMS: 0x%x\n", (val >> 16) & 0x0f);
 	}
-	printk("FMC: 0x%x\n", (val >> 14) & 3);
-	printk("RVol: 0x%x\n", (val >> 7) & 0x7f);
-	printk("CVol: 0x%x\n", val & 0x7f);
+	printk(KERN_DEBUG "FMC: 0x%x\n", (val >> 14) & 3);
+	printk(KERN_DEBUG "RVol: 0x%x\n", (val >> 7) & 0x7f);
+	printk(KERN_DEBUG "CVol: 0x%x\n", val & 0x7f);
 }
 #endif
 
@@ -496,12 +496,17 @@
 	outl(regs[4], TRID_REG(trident, CH_START + 16));
 
 #if 0
-	printk("written %i channel:\n", voice->number);
-	printk("  regs[0] = 0x%x/0x%x\n", regs[0], inl(TRID_REG(trident, CH_START + 0)));
-	printk("  regs[1] = 0x%x/0x%x\n", regs[1], inl(TRID_REG(trident, CH_START + 4)));
-	printk("  regs[2] = 0x%x/0x%x\n", regs[2], inl(TRID_REG(trident, CH_START + 8)));
-	printk("  regs[3] = 0x%x/0x%x\n", regs[3], inl(TRID_REG(trident, CH_START + 12)));
-	printk("  regs[4] = 0x%x/0x%x\n", regs[4], inl(TRID_REG(trident, CH_START + 16)));
+	printk(KERN_DEBUG "written %i channel:\n", voice->number);
+	printk(KERN_DEBUG "  regs[0] = 0x%x/0x%x\n",
+	       regs[0], inl(TRID_REG(trident, CH_START + 0)));
+	printk(KERN_DEBUG "  regs[1] = 0x%x/0x%x\n",
+	       regs[1], inl(TRID_REG(trident, CH_START + 4)));
+	printk(KERN_DEBUG "  regs[2] = 0x%x/0x%x\n",
+	       regs[2], inl(TRID_REG(trident, CH_START + 8)));
+	printk(KERN_DEBUG "  regs[3] = 0x%x/0x%x\n",
+	       regs[3], inl(TRID_REG(trident, CH_START + 12)));
+	printk(KERN_DEBUG "  regs[4] = 0x%x/0x%x\n",
+	       regs[4], inl(TRID_REG(trident, CH_START + 16)));
 #endif
 }
 
@@ -583,7 +588,7 @@
 		outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2));
 		break;
 	case TRIDENT_DEVICE_ID_SI7018:
-		// printk("voice->Vol = 0x%x\n", voice->Vol);
+		/* printk(KERN_DEBUG "voice->Vol = 0x%x\n", voice->Vol); */
 		outw((voice->CTRL << 12) | voice->Vol,
 		     TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
 		break;
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 1aafe95..809b233 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -466,7 +466,10 @@
 					flag = VIA_TBL_BIT_FLAG; /* period boundary */
 			} else
 				flag = 0; /* period continues to the next */
-			// printk("via: tbl %d: at %d  size %d (rest %d)\n", idx, ofs, r, rest);
+			/*
+			printk(KERN_DEBUG "via: tbl %d: at %d  size %d "
+			       "(rest %d)\n", idx, ofs, r, rest);
+			*/
 			((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag);
 			dev->idx_table[idx].offset = ofs;
 			dev->idx_table[idx].size = r;
@@ -2360,14 +2363,14 @@
 	SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K),
 	SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA),
 	SND_PCI_QUIRK(0x1019, 0x0a85, "ECS L7VMM2", VIA_DXS_NO_VRA),
-	SND_PCI_QUIRK(0x1019, 0, "ESC K8", VIA_DXS_SRC),
+	SND_PCI_QUIRK_VENDOR(0x1019, "ESC K8", VIA_DXS_SRC),
 	SND_PCI_QUIRK(0x1019, 0xaa01, "ESC K8T890-A", VIA_DXS_SRC),
 	SND_PCI_QUIRK(0x1025, 0x0033, "Acer Inspire 1353LM", VIA_DXS_NO_VRA),
 	SND_PCI_QUIRK(0x1025, 0x0046, "Acer Aspire 1524 WLMi", VIA_DXS_SRC),
-	SND_PCI_QUIRK(0x1043, 0, "ASUS A7/A8", VIA_DXS_NO_VRA),
-	SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS A7/A8", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK_VENDOR(0x1071, "Diverse Notebook", VIA_DXS_NO_VRA),
 	SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE),
-	SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC),
+	SND_PCI_QUIRK_VENDOR(0x1106, "ASRock", VIA_DXS_SRC),
 	SND_PCI_QUIRK(0x1297, 0xa231, "Shuttle AK31v2", VIA_DXS_SRC),
 	SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_SRC),
 	SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_SRC),
@@ -2375,7 +2378,7 @@
 	SND_PCI_QUIRK(0x1462, 0x3800, "MSI KT266", VIA_DXS_ENABLE),
 	SND_PCI_QUIRK(0x1462, 0x7120, "MSI KT4V", VIA_DXS_ENABLE),
 	SND_PCI_QUIRK(0x1462, 0x7142, "MSI K8MM-V", VIA_DXS_ENABLE),
-	SND_PCI_QUIRK(0x1462, 0, "MSI Mobo", VIA_DXS_SRC),
+	SND_PCI_QUIRK_VENDOR(0x1462, "MSI Mobo", VIA_DXS_SRC),
 	SND_PCI_QUIRK(0x147b, 0x1401, "ABIT KD7(-RAID)", VIA_DXS_ENABLE),
 	SND_PCI_QUIRK(0x147b, 0x1411, "ABIT VA-20", VIA_DXS_ENABLE),
 	SND_PCI_QUIRK(0x147b, 0x1413, "ABIT KV8 Pro", VIA_DXS_ENABLE),
@@ -2389,11 +2392,11 @@
 	SND_PCI_QUIRK(0x161f, 0x2032, "m680x machines", VIA_DXS_48K),
 	SND_PCI_QUIRK(0x1631, 0xe004, "PB EasyNote 3174", VIA_DXS_ENABLE),
 	SND_PCI_QUIRK(0x1695, 0x3005, "EPoX EP-8K9A", VIA_DXS_ENABLE),
-	SND_PCI_QUIRK(0x1695, 0, "EPoX mobo", VIA_DXS_SRC),
-	SND_PCI_QUIRK(0x16f3, 0, "Jetway K8", VIA_DXS_SRC),
-	SND_PCI_QUIRK(0x1734, 0, "FSC Laptop", VIA_DXS_SRC),
+	SND_PCI_QUIRK_VENDOR(0x1695, "EPoX mobo", VIA_DXS_SRC),
+	SND_PCI_QUIRK_VENDOR(0x16f3, "Jetway K8", VIA_DXS_SRC),
+	SND_PCI_QUIRK_VENDOR(0x1734, "FSC Laptop", VIA_DXS_SRC),
 	SND_PCI_QUIRK(0x1849, 0x3059, "ASRock K7VM2", VIA_DXS_NO_VRA),
-	SND_PCI_QUIRK(0x1849, 0, "ASRock mobo", VIA_DXS_SRC),
+	SND_PCI_QUIRK_VENDOR(0x1849, "ASRock mobo", VIA_DXS_SRC),
 	SND_PCI_QUIRK(0x1919, 0x200a, "Soltek SL-K8",  VIA_DXS_NO_VRA),
 	SND_PCI_QUIRK(0x4005, 0x4710, "MSI K7T266", VIA_DXS_SRC),
 	{ } /* terminator */
@@ -2433,9 +2436,9 @@
 	unsigned int i;
 	int err;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	card_type = pci_id->driver_data;
 	switch (card_type) {
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 5bd79d2..0d54e35 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -328,7 +328,10 @@
 					flag = VIA_TBL_BIT_FLAG; /* period boundary */
 			} else
 				flag = 0; /* period continues to the next */
-			// printk("via: tbl %d: at %d  size %d (rest %d)\n", idx, ofs, r, rest);
+			/*
+			printk(KERN_DEBUG "via: tbl %d: at %d  size %d "
+			       "(rest %d)\n", idx, ofs, r, rest);
+			*/
 			((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag);
 			dev->idx_table[idx].offset = ofs;
 			dev->idx_table[idx].size = r;
@@ -1167,9 +1170,9 @@
 	unsigned int i;
 	int err;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	card_type = pci_id->driver_data;
 	switch (card_type) {
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index acc352f..fc9136c 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -204,9 +204,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	switch ((int)pci_id->driver_data) {
 	case VX_PCI_VX222_OLD:
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index 7e87f39..c0efe44 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -107,7 +107,9 @@
 static void vx2_outb(struct vx_core *chip, int offset, unsigned char val)
 {
 	outb(val, vx2_reg_addr(chip, offset));
-	//printk("outb: %x -> %x\n", val, vx2_reg_addr(chip, offset));
+	/*
+	printk(KERN_DEBUG "outb: %x -> %x\n", val, vx2_reg_addr(chip, offset));
+	*/
 }
 
 /**
@@ -126,7 +128,9 @@
  */
 static void vx2_outl(struct vx_core *chip, int offset, unsigned int val)
 {
-	// printk("outl: %x -> %x\n", val, vx2_reg_addr(chip, offset));
+	/*
+	printk(KERN_DEBUG "outl: %x -> %x\n", val, vx2_reg_addr(chip, offset));
+	*/
 	outl(val, vx2_reg_addr(chip, offset));
 }
 
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 2631a55..4af6666 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -187,9 +187,9 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	switch (pci_id->device) {
 	case 0x0004: str = "YMF724";  model = "DS-1"; break;
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 90d0d62..2f09252 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -318,7 +318,12 @@
 		ypcm->period_pos += delta;
 		ypcm->last_pos = pos;
 		if (ypcm->period_pos >= ypcm->period_size) {
-			// printk("done - active_bank = 0x%x, start = 0x%x\n", chip->active_bank, voice->bank[chip->active_bank].start);
+			/*
+			printk(KERN_DEBUG
+			       "done - active_bank = 0x%x, start = 0x%x\n",
+			       chip->active_bank,
+			       voice->bank[chip->active_bank].start);
+			*/
 			ypcm->period_pos %= ypcm->period_size;
 			spin_unlock(&chip->reg_lock);
 			snd_pcm_period_elapsed(ypcm->substream);
@@ -366,7 +371,12 @@
 		ypcm->last_pos = pos;
 		if (ypcm->period_pos >= ypcm->period_size) {
 			ypcm->period_pos %= ypcm->period_size;
-			// printk("done - active_bank = 0x%x, start = 0x%x\n", chip->active_bank, voice->bank[chip->active_bank].start);
+			/*
+			printk(KERN_DEBUG
+			       "done - active_bank = 0x%x, start = 0x%x\n",
+			       chip->active_bank,
+			       voice->bank[chip->active_bank].start);
+			*/
 			spin_unlock(&chip->reg_lock);
 			snd_pcm_period_elapsed(substream);
 			spin_lock(&chip->reg_lock);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 819aaaa..7dea74b 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -91,7 +91,7 @@
  */
 static int snd_pdacf_probe(struct pcmcia_device *link)
 {
-	int i;
+	int i, err;
 	struct snd_pdacf *pdacf;
 	struct snd_card *card;
 	static struct snd_device_ops ops = {
@@ -112,20 +112,23 @@
 		return -ENODEV; /* disabled explicitly */
 
 	/* ok, create a card instance */
-	card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
-	if (card == NULL) {
+	err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card);
+	if (err < 0) {
 		snd_printk(KERN_ERR "pdacf: cannot create a card instance\n");
-		return -ENOMEM;
+		return err;
 	}
 
 	pdacf = snd_pdacf_create(card);
-	if (! pdacf)
-		return -EIO;
+	if (!pdacf) {
+		snd_card_free(card);
+		return -ENOMEM;
+	}
 
-	if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) {
+	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops);
+	if (err < 0) {
 		kfree(pdacf);
 		snd_card_free(card);
-		return -ENODEV;
+		return err;
 	}
 
 	snd_card_set_dev(card, &handle_to_dev(link));
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index dfa40b0..5d2afa0 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -82,14 +82,21 @@
 #if 0
 void pdacf_dump(struct snd_pdacf *chip)
 {
-	printk("PDAUDIOCF DUMP (0x%lx):\n", chip->port);
-	printk("WPD         : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_WDP));
-	printk("RDP         : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_RDP));
-	printk("TCR         : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_TCR));
-	printk("SCR         : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_SCR));
-	printk("ISR         : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_ISR));
-	printk("IER         : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_IER));
-	printk("AK_IFR      : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_AK_IFR));
+	printk(KERN_DEBUG "PDAUDIOCF DUMP (0x%lx):\n", chip->port);
+	printk(KERN_DEBUG "WPD         : 0x%x\n",
+	       inw(chip->port + PDAUDIOCF_REG_WDP));
+	printk(KERN_DEBUG "RDP         : 0x%x\n",
+	       inw(chip->port + PDAUDIOCF_REG_RDP));
+	printk(KERN_DEBUG "TCR         : 0x%x\n",
+	       inw(chip->port + PDAUDIOCF_REG_TCR));
+	printk(KERN_DEBUG "SCR         : 0x%x\n",
+	       inw(chip->port + PDAUDIOCF_REG_SCR));
+	printk(KERN_DEBUG "ISR         : 0x%x\n",
+	       inw(chip->port + PDAUDIOCF_REG_ISR));
+	printk(KERN_DEBUG "IER         : 0x%x\n",
+	       inw(chip->port + PDAUDIOCF_REG_IER));
+	printk(KERN_DEBUG "AK_IFR      : 0x%x\n",
+	       inw(chip->port + PDAUDIOCF_REG_AK_IFR));
 }
 #endif
 
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
index ea903c8..dcd3220 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
@@ -269,7 +269,7 @@
 
 	rdp = inw(chip->port + PDAUDIOCF_REG_RDP);
 	wdp = inw(chip->port + PDAUDIOCF_REG_WDP);
-	// printk("TASKLET: rdp = %x, wdp = %x\n", rdp, wdp);
+	/* printk(KERN_DEBUG "TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); */
 	size = wdp - rdp;
 	if (size < 0)
 		size += 0x10000;
@@ -321,5 +321,5 @@
 		spin_lock(&chip->reg_lock);
 	}
 	spin_unlock(&chip->reg_lock);
-	// printk("TASKLET: end\n");
+	/* printk(KERN_DEBUG "TASKLET: end\n"); */
 }
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 706602a..7445cc8 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -130,23 +130,26 @@
 /*
  * create vxpocket instance
  */
-static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl,
-					     struct pcmcia_device *link)
+static int snd_vxpocket_new(struct snd_card *card, int ibl,
+			    struct pcmcia_device *link,
+			    struct snd_vxpocket **chip_ret)
 {
 	struct vx_core *chip;
 	struct snd_vxpocket *vxp;
 	static struct snd_device_ops ops = {
 		.dev_free =	snd_vxpocket_dev_free,
 	};
+	int err;
 
 	chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops,
 			     sizeof(struct snd_vxpocket) - sizeof(struct vx_core));
-	if (! chip)
-		return NULL;
+	if (!chip)
+		return -ENOMEM;
 
-	if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) {
+	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+	if (err < 0) {
 		kfree(chip);
-		return NULL;
+		return err;
 	}
 	chip->ibl.size = ibl;
 
@@ -169,7 +172,8 @@
 	link->conf.ConfigIndex = 1;
 	link->conf.Present = PRESENT_OPTION;
 
-	return vxp;
+	*chip_ret = vxp;
+	return 0;
 }
 
 
@@ -292,7 +296,7 @@
 {
 	struct snd_card *card;
 	struct snd_vxpocket *vxp;
-	int i;
+	int i, err;
 
 	/* find an empty slot from the card list */
 	for (i = 0; i < SNDRV_CARDS; i++) {
@@ -307,16 +311,16 @@
 		return -ENODEV; /* disabled explicitly */
 
 	/* ok, create a card instance */
-	card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
-	if (card == NULL) {
+	err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card);
+	if (err < 0) {
 		snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n");
-		return -ENOMEM;
+		return err;
 	}
 
-	vxp = snd_vxpocket_new(card, ibl[i], p_dev);
-	if (! vxp) {
+	err = snd_vxpocket_new(card, ibl[i], p_dev, &vxp);
+	if (err < 0) {
 		snd_card_free(card);
-		return -ENODEV;
+		return err;
 	}
 	card->private_data = vxp;
 
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig
index 777de2b..bd2338a 100644
--- a/sound/ppc/Kconfig
+++ b/sound/ppc/Kconfig
@@ -13,6 +13,7 @@
 	tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
 	depends on I2C && INPUT && PPC_PMAC
 	select SND_PCM
+	select SND_VMASTER
 	help
 	  Say Y here to include support for the integrated sound device.
 
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 7bd33e6..80df9b1 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -608,9 +608,12 @@
 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] __initdata = {
 	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
-	AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
+	AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
 
@@ -627,6 +630,10 @@
 	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] __initdata = {
+	AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1),
+};
+
 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),
@@ -645,12 +652,19 @@
 	AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
 };
 
+static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] __initdata = {
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+};
+
 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_master_sw_pmac5500 __initdata =
+AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1);
+
 static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
 	AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };
@@ -766,12 +780,16 @@
 }
 #endif /* CONFIG_PM */
 
-#define IS_PM7500 (machine_is_compatible("AAPL,7500"))
+#define IS_PM7500 (machine_is_compatible("AAPL,7500") \
+		|| machine_is_compatible("AAPL,8500") \
+		|| machine_is_compatible("AAPL,9500"))
+#define IS_PM5500 (machine_is_compatible("AAPL,e411"))
 #define IS_BEIGE (machine_is_compatible("AAPL,Gossamer"))
 #define IS_IMAC1 (machine_is_compatible("PowerMac2,1"))
 #define IS_IMAC2 (machine_is_compatible("PowerMac2,2") \
 		|| machine_is_compatible("PowerMac4,1"))
 #define IS_G4AGP (machine_is_compatible("PowerMac3,1"))
+#define IS_LOMBARD (machine_is_compatible("PowerBook1,1"))
 
 static int imac1, imac2;
 
@@ -858,10 +876,14 @@
 snd_pmac_awacs_init(struct snd_pmac *chip)
 {
 	int pm7500 = IS_PM7500;
+	int pm5500 = IS_PM5500;
 	int beige = IS_BEIGE;
 	int g4agp = IS_G4AGP;
+	int lombard = IS_LOMBARD;
 	int imac;
 	int err, vol;
+	struct snd_kcontrol *vmaster_sw, *vmaster_vol;
+	struct snd_kcontrol *master_vol, *speaker_vol;
 
 	imac1 = IS_IMAC1;
 	imac2 = IS_IMAC2;
@@ -915,7 +937,7 @@
 		/* set headphone-jack detection bit */
 		switch (chip->model) {
 		case PMAC_AWACS:
-			chip->hp_stat_mask = pm7500 ? MASK_HDPCONN
+			chip->hp_stat_mask = pm7500 || pm5500 ? MASK_HDPCONN
 				: MASK_LOCONN;
 			break;
 		case PMAC_SCREAMER:
@@ -954,7 +976,7 @@
 		return err;
 	if (beige || g4agp)
 		;
-	else if (chip->model == PMAC_SCREAMER)
+	else if (chip->model == PMAC_SCREAMER || pm5500)
 		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
 				   snd_pmac_screamer_mixers2);
 	else if (!pm7500)
@@ -962,19 +984,35 @@
 				   snd_pmac_awacs_mixers2);
 	if (err < 0)
 		return err;
+	if (pm5500) {
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_awacs_mixers2_pmac5500),
+				   snd_pmac_awacs_mixers2_pmac5500);
+		if (err < 0)
+			return err;
+	}
 	if (pm7500)
 		err = build_mixers(chip,
 				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
 				   snd_pmac_awacs_mixers_pmac7500);
+	else if (pm5500)
+		err = snd_ctl_add(chip->card,
+		    (master_vol = snd_ctl_new1(snd_pmac_awacs_mixers_pmac5500,
+						chip)));
 	else if (beige)
 		err = build_mixers(chip,
 				   ARRAY_SIZE(snd_pmac_screamer_mixers_beige),
 				   snd_pmac_screamer_mixers_beige);
-	else if (imac)
+	else if (imac || lombard) {
+		err = snd_ctl_add(chip->card,
+		    (master_vol = snd_ctl_new1(snd_pmac_screamer_mixers_lo,
+						chip)));
+		if (err < 0)
+			return err;
 		err = build_mixers(chip,
 				   ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
 				   snd_pmac_screamer_mixers_imac);
-	else if (g4agp)
+	} else if (g4agp)
 		err = build_mixers(chip,
 				   ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp),
 				   snd_pmac_screamer_mixers_g4agp);
@@ -984,8 +1022,10 @@
 				   snd_pmac_awacs_mixers_pmac);
 	if (err < 0)
 		return err;
-	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp)
+	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp || lombard)
 			? &snd_pmac_awacs_master_sw_imac
+			: pm5500
+			? &snd_pmac_awacs_master_sw_pmac5500
 			: &snd_pmac_awacs_master_sw, chip);
 	err = snd_ctl_add(chip->card, chip->master_sw_ctl);
 	if (err < 0)
@@ -1017,8 +1057,9 @@
 #endif /* PMAC_AMP_AVAIL */
 	{
 		/* route A = headphone, route C = speaker */
-		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
-					snd_pmac_awacs_speaker_vol);
+		err = snd_ctl_add(chip->card,
+		    (speaker_vol = snd_ctl_new1(snd_pmac_awacs_speaker_vol,
+						chip)));
 		if (err < 0)
 			return err;
 		chip->speaker_sw_ctl = snd_ctl_new1(imac1
@@ -1031,6 +1072,33 @@
 			return err;
 	}
 
+	if (pm5500 || imac || lombard) {
+		vmaster_sw = snd_ctl_make_virtual_master(
+			"Master Playback Switch", (unsigned int *) NULL);
+		err = snd_ctl_add_slave_uncached(vmaster_sw,
+						 chip->master_sw_ctl);
+		if (err < 0)
+			return err;
+		err = snd_ctl_add_slave_uncached(vmaster_sw,
+						  chip->speaker_sw_ctl);
+		if (err < 0)
+			return err;
+		err = snd_ctl_add(chip->card, vmaster_sw);
+		if (err < 0)
+			return err;
+		vmaster_vol = snd_ctl_make_virtual_master(
+			"Master Playback Volume", (unsigned int *) NULL);
+		err = snd_ctl_add_slave(vmaster_vol, master_vol);
+		if (err < 0)
+			return err;
+		err = snd_ctl_add_slave(vmaster_vol, speaker_vol);
+		if (err < 0)
+			return err;
+		err = snd_ctl_add(chip->card, vmaster_vol);
+		if (err < 0)
+			return err;
+	}
+
 	if (beige || g4agp)
 		err = build_mixers(chip,
 				ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
index f860d39..45a7629 100644
--- a/sound/ppc/burgundy.c
+++ b/sound/ppc/burgundy.c
@@ -35,7 +35,7 @@
 	int timeout = 50;
 	while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--)
 		udelay(1);
-	if (! timeout)
+	if (timeout < 0)
 		printk(KERN_DEBUG "burgundy_busy_wait: timeout\n");
 }
 
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index 8a5b290..f8d478c 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -82,7 +82,7 @@
 	data[1] |= mix->deemphasis ? 0x40 : 0;
 	if (i2c_smbus_write_block_data(mix->i2c.client, DACA_REG_AVOL,
 				       2, data) < 0) {
-		snd_printk("failed to set volume \n");
+		snd_printk(KERN_ERR "failed to set volume \n");
 		return -EINVAL;
 	}
 	return 0;
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index af76ee8..9b4e9c3 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -299,7 +299,7 @@
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 		spin_lock(&chip->reg_lock);
 		rec->running = 0;
-		/*printk("stopped!!\n");*/
+		/*printk(KERN_DEBUG "stopped!!\n");*/
 		snd_pmac_dma_stop(rec);
 		for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++)
 			out_le16(&cp->command, DBDMA_STOP);
@@ -334,7 +334,7 @@
 	}
 #endif
 	count += rec->cur_period * rec->period_size;
-	/*printk("pointer=%d\n", count);*/
+	/*printk(KERN_DEBUG "pointer=%d\n", count);*/
 	return bytes_to_frames(subs->runtime, count);
 }
 
@@ -486,7 +486,7 @@
 			if (! (stat & ACTIVE))
 				break;
 
-			/*printk("update frag %d\n", rec->cur_period);*/
+			/*printk(KERN_DEBUG "update frag %d\n", rec->cur_period);*/
 			st_le16(&cp->xfer_status, 0);
 			st_le16(&cp->req_count, rec->period_size);
 			/*st_le16(&cp->res_count, 0);*/
@@ -806,7 +806,7 @@
 	struct snd_pmac *chip = devid;
 	int ctrl = in_le32(&chip->awacs->control);
 
-	/*printk("pmac: control interrupt.. 0x%x\n", ctrl);*/
+	/*printk(KERN_DEBUG "pmac: control interrupt.. 0x%x\n", ctrl);*/
 	if (ctrl & MASK_PORTCHG) {
 		/* do something when headphone is plugged/unplugged? */
 		if (chip->update_automute)
@@ -1033,7 +1033,8 @@
 	}
 	if (of_device_is_compatible(sound, "tumbler")) {
 		chip->model = PMAC_TUMBLER;
-		chip->can_capture = machine_is_compatible("PowerMac4,2");
+		chip->can_capture = machine_is_compatible("PowerMac4,2")
+				|| machine_is_compatible("PowerBook4,1");
 		chip->can_duplex = 0;
 		// chip->can_byte_swap = 0; /* FIXME: check this */
 		chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index c936225..5a92906 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -58,9 +58,9 @@
 	char *name_ext;
 	int err;
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 	if ((err = snd_pmac_new(card, &chip)) < 0)
 		goto __error;
@@ -110,7 +110,7 @@
 			goto __error;
 		break;
 	default:
-		snd_printk("unsupported hardware %d\n", chip->model);
+		snd_printk(KERN_ERR "unsupported hardware %d\n", chip->model);
 		err = -EINVAL;
 		goto __error;
 	}
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
index ff32111..f361c26 100644
--- a/sound/ppc/snd_ps3.c
+++ b/sound/ppc/snd_ps3.c
@@ -969,11 +969,9 @@
 	}
 
 	/* create card instance */
-	the_card.card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (!the_card.card) {
-		ret = -ENXIO;
+	ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card);
+	if (ret < 0)
 		goto clean_irq;
-	}
 
 	strcpy(the_card.card->driver, "PS3");
 	strcpy(the_card.card->shortname, "PS3");
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 3eb2233..40222fc 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -41,7 +41,7 @@
 #undef DEBUG
 
 #ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
 #else
 #define DBG(fmt...)
 #endif
@@ -240,7 +240,7 @@
   
 	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6,
 					   block) < 0) {
-		snd_printk("failed to set volume \n");
+		snd_printk(KERN_ERR "failed to set volume \n");
 		return -EINVAL;
 	}
 	return 0;
@@ -350,7 +350,7 @@
 
 	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
 					   2, val) < 0) {
-		snd_printk("failed to set DRC\n");
+		snd_printk(KERN_ERR "failed to set DRC\n");
 		return -EINVAL;
 	}
 	return 0;
@@ -386,7 +386,7 @@
 
 	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
 					   6, val) < 0) {
-		snd_printk("failed to set DRC\n");
+		snd_printk(KERN_ERR "failed to set DRC\n");
 		return -EINVAL;
 	}
 	return 0;
@@ -506,7 +506,8 @@
 		block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff;
 	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg,
 					   info->bytes, block) < 0) {
-		snd_printk("failed to set mono volume %d\n", info->index);
+		snd_printk(KERN_ERR "failed to set mono volume %d\n",
+			   info->index);
 		return -EINVAL;
 	}
 	return 0;
@@ -643,7 +644,7 @@
 	}
 	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg,
 					   9, block) < 0) {
-		snd_printk("failed to set mono volume %d\n", reg);
+		snd_printk(KERN_ERR "failed to set mono volume %d\n", reg);
 		return -EINVAL;
 	}
 	return 0;
diff --git a/sound/sh/Kconfig b/sound/sh/Kconfig
index cfc1439..aed0f90 100644
--- a/sound/sh/Kconfig
+++ b/sound/sh/Kconfig
@@ -15,6 +15,7 @@
 	tristate "Dreamcast Yamaha AICA sound"
 	depends on SH_DREAMCAST
 	select SND_PCM
+	select G2_DMA
 	help
 	  ALSA Sound driver for the SEGA Dreamcast console.
 
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index 7c920f3..f551233 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -609,11 +609,11 @@
 	dreamcastcard = kmalloc(sizeof(struct snd_card_aica), GFP_KERNEL);
 	if (unlikely(!dreamcastcard))
 		return -ENOMEM;
-	dreamcastcard->card =
-	    snd_card_new(index, SND_AICA_DRIVER, THIS_MODULE, 0);
-	if (unlikely(!dreamcastcard->card)) {
+	err = snd_card_create(index, SND_AICA_DRIVER, THIS_MODULE, 0,
+			      &dreamcastcard->card);
+	if (unlikely(err < 0)) {
 		kfree(dreamcastcard);
-		return -ENODEV;
+		return err;
 	}
 	strcpy(dreamcastcard->card->driver, "snd_aica");
 	strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index ef025c6..3d2bb6f 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -6,6 +6,7 @@
 	tristate "ALSA for SoC audio support"
 	select SND_PCM
 	select AC97_BUS if SND_SOC_AC97_BUS
+	select SND_JACK if INPUT=y || INPUT=SND
 	---help---
 
 	  If you want ASoC support, you should say Y here and also to the
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 86a9b1f..0237879 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
-snd-soc-core-objs := soc-core.o soc-dapm.o
+snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o
 
 obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
 obj-$(CONFIG_SND_SOC)	+= codecs/
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index 3dcdc4e..9ef6b96 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -347,7 +347,7 @@
 		       vma->vm_end - vma->vm_start, vma->vm_page_prot);
 }
 
-struct snd_pcm_ops atmel_pcm_ops = {
+static struct snd_pcm_ops atmel_pcm_ops = {
 	.open		= atmel_pcm_open,
 	.close		= atmel_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index ff0054b..e588e63 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -697,6 +697,15 @@
 #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_LE |\
 			  SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
+static struct snd_soc_dai_ops atmel_ssc_dai_ops = {
+	.startup	= atmel_ssc_startup,
+	.shutdown	= atmel_ssc_shutdown,
+	.prepare	= atmel_ssc_prepare,
+	.hw_params	= atmel_ssc_hw_params,
+	.set_fmt	= atmel_ssc_set_dai_fmt,
+	.set_clkdiv	= atmel_ssc_set_dai_clkdiv,
+};
+
 struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
 	{	.name = "atmel-ssc0",
 		.id = 0,
@@ -712,13 +721,7 @@
 			.channels_max = 2,
 			.rates = ATMEL_SSC_RATES,
 			.formats = ATMEL_SSC_FORMATS,},
-		.ops = {
-			.startup = atmel_ssc_startup,
-			.shutdown = atmel_ssc_shutdown,
-			.prepare = atmel_ssc_prepare,
-			.hw_params = atmel_ssc_hw_params,
-			.set_fmt = atmel_ssc_set_dai_fmt,
-			.set_clkdiv = atmel_ssc_set_dai_clkdiv,},
+		.ops = &atmel_ssc_dai_ops,
 		.private_data = &ssc_info[0],
 	},
 #if NUM_SSC_DEVICES == 3
@@ -736,13 +739,7 @@
 			.channels_max = 2,
 			.rates = ATMEL_SSC_RATES,
 			.formats = ATMEL_SSC_FORMATS,},
-		.ops = {
-			.startup = atmel_ssc_startup,
-			.shutdown = atmel_ssc_shutdown,
-			.prepare = atmel_ssc_prepare,
-			.hw_params = atmel_ssc_hw_params,
-			.set_fmt = atmel_ssc_set_dai_fmt,
-			.set_clkdiv = atmel_ssc_set_dai_clkdiv,},
+		.ops = &atmel_ssc_dai_ops,
 		.private_data = &ssc_info[1],
 	},
 	{	.name = "atmel-ssc2",
@@ -759,13 +756,7 @@
 			.channels_max = 2,
 			.rates = ATMEL_SSC_RATES,
 			.formats = ATMEL_SSC_FORMATS,},
-		.ops = {
-			.startup = atmel_ssc_startup,
-			.shutdown = atmel_ssc_shutdown,
-			.prepare = atmel_ssc_prepare,
-			.hw_params = atmel_ssc_hw_params,
-			.set_fmt = atmel_ssc_set_dai_fmt,
-			.set_clkdiv = atmel_ssc_set_dai_clkdiv,},
+		.ops = &atmel_ssc_dai_ops,
 		.private_data = &ssc_info[2],
 	},
 #endif
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index 43dd8ce..7065753 100644
--- a/sound/soc/atmel/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -164,41 +164,41 @@
 	 */
 	switch (params_rate(params)) {
 	case 48000:
-		pll_out = 12288000;
-		mclk_div = WM8510_MCLKDIV_1;
-		bclk = WM8510_BCLKDIV_8;
-		break;
-
-	case 44100:
-		pll_out = 11289600;
-		mclk_div = WM8510_MCLKDIV_1;
-		bclk = WM8510_BCLKDIV_8;
-		break;
-
-	case 22050:
-		pll_out = 11289600;
+		pll_out = 24576000;
 		mclk_div = WM8510_MCLKDIV_2;
 		bclk = WM8510_BCLKDIV_8;
 		break;
 
-	case 16000:
-		pll_out = 12288000;
-		mclk_div = WM8510_MCLKDIV_3;
+	case 44100:
+		pll_out = 22579200;
+		mclk_div = WM8510_MCLKDIV_2;
 		bclk = WM8510_BCLKDIV_8;
 		break;
 
-	case 11025:
-		pll_out = 11289600;
+	case 22050:
+		pll_out = 22579200;
 		mclk_div = WM8510_MCLKDIV_4;
 		bclk = WM8510_BCLKDIV_8;
 		break;
 
-	case 8000:
-		pll_out = 12288000;
+	case 16000:
+		pll_out = 24576000;
 		mclk_div = WM8510_MCLKDIV_6;
 		bclk = WM8510_BCLKDIV_8;
 		break;
 
+	case 11025:
+		pll_out = 22579200;
+		mclk_div = WM8510_MCLKDIV_8;
+		bclk = WM8510_BCLKDIV_8;
+		break;
+
+	case 8000:
+		pll_out = 24576000;
+		mclk_div = WM8510_MCLKDIV_12;
+		bclk = WM8510_BCLKDIV_8;
+		break;
+
 	default:
 		pr_warning("playpaq_wm8510: Unsupported sample rate %d\n",
 			   params_rate(params));
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 6ea04be..173a239 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -36,6 +36,7 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/i2c.h>
 
 #include <linux/atmel-ssc.h>
 
@@ -45,6 +46,7 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 
+#include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <mach/gpio.h>
 
@@ -52,6 +54,9 @@
 #include "atmel-pcm.h"
 #include "atmel_ssc_dai.h"
 
+#define MCLK_RATE 12000000
+
+static struct clk *mclk;
 
 static int at91sam9g20ek_startup(struct snd_pcm_substream *substream)
 {
@@ -59,11 +64,12 @@
 	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 	int ret;
 
-	/* codec system clock is supplied by PCK0, set to 12MHz */
 	ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
-		12000000, SND_SOC_CLOCK_IN);
-	if (ret < 0)
+		MCLK_RATE, SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		clk_disable(mclk);
 		return ret;
+	}
 
 	return 0;
 }
@@ -189,6 +195,31 @@
 	.shutdown = at91sam9g20ek_shutdown,
 };
 
+static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
+					enum snd_soc_bias_level level)
+{
+	static int mclk_on;
+	int ret = 0;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+	case SND_SOC_BIAS_PREPARE:
+		if (!mclk_on)
+			ret = clk_enable(mclk);
+		if (ret == 0)
+			mclk_on = 1;
+		break;
+
+	case SND_SOC_BIAS_OFF:
+	case SND_SOC_BIAS_STANDBY:
+		if (mclk_on)
+			clk_disable(mclk);
+		mclk_on = 0;
+		break;
+	}
+
+	return ret;
+}
 
 static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
 	SND_SOC_DAPM_MIC("Int Mic", NULL),
@@ -243,21 +274,48 @@
 };
 
 static struct snd_soc_card snd_soc_at91sam9g20ek = {
-	.name = "WM8731",
+	.name = "AT91SAMG20-EK",
 	.platform = &atmel_soc_platform,
 	.dai_link = &at91sam9g20ek_dai,
 	.num_links = 1,
+	.set_bias_level = at91sam9g20ek_set_bias_level,
 };
 
-static struct wm8731_setup_data at91sam9g20ek_wm8731_setup = {
-	.i2c_bus = 0,
-	.i2c_address = 0x1b,
-};
+/*
+ * FIXME: This is a temporary bodge to avoid cross-tree merge issues.
+ * New drivers should register the wm8731 I2C device in the machine
+ * setup code (under arch/arm for ARM systems).
+ */
+static int wm8731_i2c_register(void)
+{
+	struct i2c_board_info info;
+	struct i2c_adapter *adapter;
+	struct i2c_client *client;
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	info.addr = 0x1b;
+	strlcpy(info.type, "wm8731", I2C_NAME_SIZE);
+
+	adapter = i2c_get_adapter(0);
+	if (!adapter) {
+		printk(KERN_ERR "can't get i2c adapter 0\n");
+		return -ENODEV;
+	}
+
+	client = i2c_new_device(adapter, &info);
+	i2c_put_adapter(adapter);
+	if (!client) {
+		printk(KERN_ERR "can't add i2c device at 0x%x\n",
+			(unsigned int)info.addr);
+		return -ENODEV;
+	}
+
+	return 0;
+}
 
 static struct snd_soc_device at91sam9g20ek_snd_devdata = {
 	.card = &snd_soc_at91sam9g20ek,
 	.codec_dev = &soc_codec_dev_wm8731,
-	.codec_data = &at91sam9g20ek_wm8731_setup,
 };
 
 static struct platform_device *at91sam9g20ek_snd_device;
@@ -266,23 +324,56 @@
 {
 	struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
 	struct ssc_device *ssc = NULL;
+	struct clk *pllb;
 	int ret;
 
+	if (!machine_is_at91sam9g20ek())
+		return -ENODEV;
+
+	/*
+	 * Codec MCLK is supplied by PCK0 - set it up.
+	 */
+	mclk = clk_get(NULL, "pck0");
+	if (IS_ERR(mclk)) {
+		printk(KERN_ERR "ASoC: Failed to get MCLK\n");
+		ret = PTR_ERR(mclk);
+		goto err;
+	}
+
+	pllb = clk_get(NULL, "pllb");
+	if (IS_ERR(mclk)) {
+		printk(KERN_ERR "ASoC: Failed to get PLLB\n");
+		ret = PTR_ERR(mclk);
+		goto err_mclk;
+	}
+	ret = clk_set_parent(mclk, pllb);
+	clk_put(pllb);
+	if (ret != 0) {
+		printk(KERN_ERR "ASoC: Failed to set MCLK parent\n");
+		goto err_mclk;
+	}
+
+	clk_set_rate(mclk, MCLK_RATE);
+
 	/*
 	 * Request SSC device
 	 */
 	ssc = ssc_request(0);
 	if (IS_ERR(ssc)) {
+		printk(KERN_ERR "ASoC: Failed to request SSC 0\n");
 		ret = PTR_ERR(ssc);
 		ssc = NULL;
 		goto err_ssc;
 	}
 	ssc_p->ssc = ssc;
 
+	ret = wm8731_i2c_register();
+	if (ret != 0)
+		goto err_ssc;
+
 	at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!at91sam9g20ek_snd_device) {
-		printk(KERN_DEBUG
-				"platform device allocation failed\n");
+		printk(KERN_ERR "ASoC: Platform device allocation failed\n");
 		ret = -ENOMEM;
 	}
 
@@ -292,14 +383,19 @@
 
 	ret = platform_device_add(at91sam9g20ek_snd_device);
 	if (ret) {
-		printk(KERN_DEBUG
-				"platform device allocation failed\n");
+		printk(KERN_ERR "ASoC: Platform device allocation failed\n");
 		platform_device_put(at91sam9g20ek_snd_device);
 	}
 
 	return ret;
 
 err_ssc:
+	ssc_free(ssc);
+	ssc_p->ssc = NULL;
+err_mclk:
+	clk_put(mclk);
+	mclk = NULL;
+err:
 	return ret;
 }
 
@@ -317,6 +413,8 @@
 
 	platform_device_unregister(at91sam9g20ek_snd_device);
 	at91sam9g20ek_snd_device = NULL;
+	clk_put(mclk);
+	mclk = NULL;
 }
 
 module_init(at91sam9g20ek_init);
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index bc8d654..30490a2 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -305,7 +305,7 @@
 	return 0;
 }
 
-struct snd_pcm_ops au1xpsc_pcm_ops = {
+static struct snd_pcm_ops au1xpsc_pcm_ops = {
 	.open		= au1xpsc_pcm_open,
 	.close		= au1xpsc_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index f0e30ae..479d7bd 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -342,6 +342,11 @@
 	return 0;
 }
 
+static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
+	.trigger	= au1xpsc_ac97_trigger,
+	.hw_params	= au1xpsc_ac97_hw_params,
+};
+
 struct snd_soc_dai au1xpsc_ac97_dai = {
 	.name			= "au1xpsc_ac97",
 	.ac97_control		= 1,
@@ -361,10 +366,7 @@
 		.channels_min	= 2,
 		.channels_max	= 2,
 	},
-	.ops = {
-		.trigger	= au1xpsc_ac97_trigger,
-		.hw_params	= au1xpsc_ac97_hw_params,
-	},
+	.ops = &au1xpsc_ac97_dai_ops,
 };
 EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
 
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index f916de4..bb58932 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -367,6 +367,12 @@
 	return 0;
 }
 
+static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
+	.trigger	= au1xpsc_i2s_trigger,
+	.hw_params	= au1xpsc_i2s_hw_params,
+	.set_fmt	= au1xpsc_i2s_set_fmt,
+};
+
 struct snd_soc_dai au1xpsc_i2s_dai = {
 	.name			= "au1xpsc_i2s",
 	.probe			= au1xpsc_i2s_probe,
@@ -385,11 +391,7 @@
 		.channels_min	= 2,
 		.channels_max	= 8,	/* 2 without external help */
 	},
-	.ops = {
-		.trigger	= au1xpsc_i2s_trigger,
-		.hw_params	= au1xpsc_i2s_hw_params,
-		.set_fmt	= au1xpsc_i2s_set_fmt,
-	},
+	.ops = &au1xpsc_i2s_dai_ops,
 };
 EXPORT_SYMBOL(au1xpsc_i2s_dai);
 
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 8067cfa..8cfed1a 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -297,7 +297,7 @@
 }
 #endif
 
-struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
+static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
 	.open		= bf5xx_pcm_open,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= bf5xx_pcm_hw_params,
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 3be2be6..8a935f2 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -31,72 +31,46 @@
 #include "bf5xx-sport.h"
 #include "bf5xx-ac97.h"
 
-#if defined(CONFIG_BF54x)
-#define PIN_REQ_SPORT_0 {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, \
-		P_SPORT0_RFS, P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0}
-
-#define PIN_REQ_SPORT_1 {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, \
-		P_SPORT1_RFS, P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0}
-
-#define PIN_REQ_SPORT_2 {P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, \
-		P_SPORT2_RFS, P_SPORT2_DRPRI, P_SPORT2_RSCLK, 0}
-
-#define PIN_REQ_SPORT_3 {P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, \
-		P_SPORT3_RFS, P_SPORT3_DRPRI, P_SPORT3_RSCLK, 0}
-#else
-#define PIN_REQ_SPORT_0 {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \
-		 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0}
-
-#define PIN_REQ_SPORT_1 {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \
-		 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0}
-#endif
-
 static int *cmd_count;
 static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
 
+#define SPORT_REQ(x) \
+	[x] = {P_SPORT##x##_TFS, P_SPORT##x##_DTPRI, P_SPORT##x##_TSCLK, \
+	       P_SPORT##x##_RFS, P_SPORT##x##_DRPRI, P_SPORT##x##_RSCLK, 0}
 static u16 sport_req[][7] = {
-		PIN_REQ_SPORT_0,
-#ifdef PIN_REQ_SPORT_1
-		PIN_REQ_SPORT_1,
+#ifdef SPORT0_TCR1
+	SPORT_REQ(0),
 #endif
-#ifdef PIN_REQ_SPORT_2
-		PIN_REQ_SPORT_2,
+#ifdef SPORT1_TCR1
+	SPORT_REQ(1),
 #endif
-#ifdef PIN_REQ_SPORT_3
-		PIN_REQ_SPORT_3,
+#ifdef SPORT2_TCR1
+	SPORT_REQ(2),
 #endif
-	};
+#ifdef SPORT3_TCR1
+	SPORT_REQ(3),
+#endif
+};
 
-static struct sport_param sport_params[4] = {
-	{
-		.dma_rx_chan	= CH_SPORT0_RX,
-		.dma_tx_chan	= CH_SPORT0_TX,
-		.err_irq	= IRQ_SPORT0_ERROR,
-		.regs		= (struct sport_register *)SPORT0_TCR1,
-	},
-#ifdef PIN_REQ_SPORT_1
-	{
-		.dma_rx_chan	= CH_SPORT1_RX,
-		.dma_tx_chan	= CH_SPORT1_TX,
-		.err_irq	= IRQ_SPORT1_ERROR,
-		.regs		= (struct sport_register *)SPORT1_TCR1,
-	},
-#endif
-#ifdef PIN_REQ_SPORT_2
-	{
-		.dma_rx_chan	= CH_SPORT2_RX,
-		.dma_tx_chan	= CH_SPORT2_TX,
-		.err_irq	= IRQ_SPORT2_ERROR,
-		.regs		= (struct sport_register *)SPORT2_TCR1,
-	},
-#endif
-#ifdef PIN_REQ_SPORT_3
-	{
-		.dma_rx_chan	= CH_SPORT3_RX,
-		.dma_tx_chan	= CH_SPORT3_TX,
-		.err_irq	= IRQ_SPORT3_ERROR,
-		.regs		= (struct sport_register *)SPORT3_TCR1,
+#define SPORT_PARAMS(x) \
+	[x] = { \
+		.dma_rx_chan = CH_SPORT##x##_RX, \
+		.dma_tx_chan = CH_SPORT##x##_TX, \
+		.err_irq     = IRQ_SPORT##x##_ERROR, \
+		.regs        = (struct sport_register *)SPORT##x##_TCR1, \
 	}
+static struct sport_param sport_params[4] = {
+#ifdef SPORT0_TCR1
+	SPORT_PARAMS(0),
+#endif
+#ifdef SPORT1_TCR1
+	SPORT_PARAMS(1),
+#endif
+#ifdef SPORT2_TCR1
+	SPORT_PARAMS(2),
+#endif
+#ifdef SPORT3_TCR1
+	SPORT_PARAMS(3),
 #endif
 };
 
@@ -332,11 +306,11 @@
 	if (cmd_count == NULL)
 		return -ENOMEM;
 
-	if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
+	if (peripheral_request_list(sport_req[sport_num], "soc-audio")) {
 		pr_err("Requesting Peripherals failed\n");
 		ret =  -EFAULT;
 		goto peripheral_err;
-		}
+	}
 
 #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
 	/* Request PB3 as reset pin */
@@ -383,9 +357,9 @@
 sport_err:
 #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
 	gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
-#endif
 gpio_err:
-	peripheral_free_list(&sport_req[sport_num][0]);
+#endif
+	peripheral_free_list(sport_req[sport_num]);
 peripheral_err:
 	free_page((unsigned long)cmd_count);
 	cmd_count = NULL;
@@ -398,7 +372,7 @@
 {
 	free_page((unsigned long)cmd_count);
 	cmd_count = NULL;
-	peripheral_free_list(&sport_req[sport_num][0]);
+	peripheral_free_list(sport_req[sport_num]);
 #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
 	gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
 #endif
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 7f2a5e1..edfbdc0 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -114,7 +114,7 @@
 	SSYNC();
 
 	/* When TUVF is set, the data is already send out */
-	while (!(status & TUVF) && count++ < 10000) {
+	while (!(status & TUVF) && ++count < 10000) {
 		udelay(1);
 		status = bfin_read_SPORT_STAT();
 		SSYNC();
@@ -123,7 +123,7 @@
 	SSYNC();
 	local_irq_enable();
 
-	if (count == 10000) {
+	if (count >= 10000) {
 		printk(KERN_ERR "ad73311: failed to configure codec\n");
 		return -1;
 	}
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 53d290b..1318c4f 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -184,7 +184,7 @@
 	return 0 ;
 }
 
-struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
+static struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
 	.open		= bf5xx_pcm_open,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= bf5xx_pcm_hw_params,
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index d1d95d2..9648244 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -287,6 +287,13 @@
 #define BF5XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
 	SNDRV_PCM_FMTBIT_S32_LE)
 
+static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
+	.startup	= bf5xx_i2s_startup,
+	.shutdown	= bf5xx_i2s_shutdown,
+	.hw_params	= bf5xx_i2s_hw_params,
+	.set_fmt	= bf5xx_i2s_set_dai_fmt,
+};
+
 struct snd_soc_dai bf5xx_i2s_dai = {
 	.name = "bf5xx-i2s",
 	.id = 0,
@@ -304,12 +311,7 @@
 		.channels_max = 2,
 		.rates = BF5XX_I2S_RATES,
 		.formats = BF5XX_I2S_FORMATS,},
-	.ops = {
-		.startup   = bf5xx_i2s_startup,
-		.shutdown  = bf5xx_i2s_shutdown,
-		.hw_params = bf5xx_i2s_hw_params,
-		.set_fmt = bf5xx_i2s_set_dai_fmt,
-	},
+	.ops = &bf5xx_i2s_dai_ops,
 };
 EXPORT_SYMBOL_GPL(bf5xx_i2s_dai);
 
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c
index 3b99e48..b7953c8 100644
--- a/sound/soc/blackfin/bf5xx-sport.c
+++ b/sound/soc/blackfin/bf5xx-sport.c
@@ -133,7 +133,7 @@
 	int i;
 
 	for (i = 0; i < fragcount; ++i) {
-		desc[i].next_desc_addr  = (unsigned long)&(desc[i + 1]);
+		desc[i].next_desc_addr  = &(desc[i + 1]);
 		desc[i].start_addr = (unsigned long)buf + i*fragsize;
 		desc[i].cfg = cfg;
 		desc[i].x_count = x_count;
@@ -143,12 +143,12 @@
 	}
 
 	/* make circular */
-	desc[fragcount-1].next_desc_addr = (unsigned long)desc;
+	desc[fragcount-1].next_desc_addr = desc;
 
-	pr_debug("setup desc: desc0=%p, next0=%lx, desc1=%p,"
-		"next1=%lx\nx_count=%x,y_count=%x,addr=0x%lx,cfs=0x%x\n",
-		&(desc[0]), desc[0].next_desc_addr,
-		&(desc[1]), desc[1].next_desc_addr,
+	pr_debug("setup desc: desc0=%p, next0=%p, desc1=%p,"
+		"next1=%p\nx_count=%x,y_count=%x,addr=0x%lx,cfs=0x%x\n",
+		desc, desc[0].next_desc_addr,
+		desc+1, desc[1].next_desc_addr,
 		desc[0].x_count, desc[0].y_count,
 		desc[0].start_addr, desc[0].cfg);
 }
@@ -184,22 +184,20 @@
 	BUG_ON(sport->curr_rx_desc == sport->dummy_rx_desc);
 
 	/* Maybe the dummy buffer descriptor ring is damaged */
-	sport->dummy_rx_desc->next_desc_addr = \
-			(unsigned long)(sport->dummy_rx_desc+1);
+	sport->dummy_rx_desc->next_desc_addr = sport->dummy_rx_desc + 1;
 
 	local_irq_save(flags);
-	desc = (struct dmasg *)get_dma_next_desc_ptr(sport->dma_rx_chan);
+	desc = get_dma_next_desc_ptr(sport->dma_rx_chan);
 	/* Copy the descriptor which will be damaged to backup */
 	temp_desc = *desc;
 	desc->x_count = 0xa;
 	desc->y_count = 0;
-	desc->next_desc_addr = (unsigned long)(sport->dummy_rx_desc);
+	desc->next_desc_addr = sport->dummy_rx_desc;
 	local_irq_restore(flags);
 	/* Waiting for dummy buffer descriptor is already hooked*/
 	while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) -
-			sizeof(struct dmasg)) !=
-			(unsigned long)sport->dummy_rx_desc)
-		;
+			sizeof(struct dmasg)) != sport->dummy_rx_desc)
+		continue;
 	sport->curr_rx_desc = sport->dummy_rx_desc;
 	/* Restore the damaged descriptor */
 	*desc = temp_desc;
@@ -210,14 +208,12 @@
 static inline int sport_rx_dma_start(struct sport_device *sport, int dummy)
 {
 	if (dummy) {
-		sport->dummy_rx_desc->next_desc_addr = \
-				(unsigned long) sport->dummy_rx_desc;
+		sport->dummy_rx_desc->next_desc_addr = sport->dummy_rx_desc;
 		sport->curr_rx_desc = sport->dummy_rx_desc;
 	} else
 		sport->curr_rx_desc = sport->dma_rx_desc;
 
-	set_dma_next_desc_addr(sport->dma_rx_chan, \
-			(unsigned long)(sport->curr_rx_desc));
+	set_dma_next_desc_addr(sport->dma_rx_chan, sport->curr_rx_desc);
 	set_dma_x_count(sport->dma_rx_chan, 0);
 	set_dma_x_modify(sport->dma_rx_chan, 0);
 	set_dma_config(sport->dma_rx_chan, (DMAFLOW_LARGE | NDSIZE_9 | \
@@ -231,14 +227,12 @@
 static inline int sport_tx_dma_start(struct sport_device *sport, int dummy)
 {
 	if (dummy) {
-		sport->dummy_tx_desc->next_desc_addr = \
-				(unsigned long) sport->dummy_tx_desc;
+		sport->dummy_tx_desc->next_desc_addr = sport->dummy_tx_desc;
 		sport->curr_tx_desc = sport->dummy_tx_desc;
 	} else
 		sport->curr_tx_desc = sport->dma_tx_desc;
 
-	set_dma_next_desc_addr(sport->dma_tx_chan, \
-			(unsigned long)(sport->curr_tx_desc));
+	set_dma_next_desc_addr(sport->dma_tx_chan, sport->curr_tx_desc);
 	set_dma_x_count(sport->dma_tx_chan, 0);
 	set_dma_x_modify(sport->dma_tx_chan, 0);
 	set_dma_config(sport->dma_tx_chan,
@@ -261,11 +255,9 @@
 		BUG_ON(sport->curr_rx_desc != sport->dummy_rx_desc);
 		local_irq_save(flags);
 		while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) -
-			sizeof(struct dmasg)) !=
-			(unsigned long)sport->dummy_rx_desc)
-			;
-		sport->dummy_rx_desc->next_desc_addr =
-				(unsigned long)(sport->dma_rx_desc);
+			sizeof(struct dmasg)) != sport->dummy_rx_desc)
+			continue;
+		sport->dummy_rx_desc->next_desc_addr = sport->dma_rx_desc;
 		local_irq_restore(flags);
 		sport->curr_rx_desc = sport->dma_rx_desc;
 	} else {
@@ -310,23 +302,21 @@
 	BUG_ON(sport->dummy_tx_desc == NULL);
 	BUG_ON(sport->curr_tx_desc == sport->dummy_tx_desc);
 
-	sport->dummy_tx_desc->next_desc_addr = \
-			(unsigned long)(sport->dummy_tx_desc+1);
+	sport->dummy_tx_desc->next_desc_addr = sport->dummy_tx_desc + 1;
 
 	/* Shorten the time on last normal descriptor */
 	local_irq_save(flags);
-	desc = (struct dmasg *)get_dma_next_desc_ptr(sport->dma_tx_chan);
+	desc = get_dma_next_desc_ptr(sport->dma_tx_chan);
 	/* Store the descriptor which will be damaged */
 	temp_desc = *desc;
 	desc->x_count = 0xa;
 	desc->y_count = 0;
-	desc->next_desc_addr = (unsigned long)(sport->dummy_tx_desc);
+	desc->next_desc_addr = sport->dummy_tx_desc;
 	local_irq_restore(flags);
 	/* Waiting for dummy buffer descriptor is already hooked*/
 	while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - \
-			sizeof(struct dmasg)) != \
-			(unsigned long)sport->dummy_tx_desc)
-		;
+			sizeof(struct dmasg)) != sport->dummy_tx_desc)
+		continue;
 	sport->curr_tx_desc = sport->dummy_tx_desc;
 	/* Restore the damaged descriptor */
 	*desc = temp_desc;
@@ -347,11 +337,9 @@
 		/* Hook the normal buffer descriptor */
 		local_irq_save(flags);
 		while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) -
-			sizeof(struct dmasg)) !=
-			(unsigned long)sport->dummy_tx_desc)
-			;
-		sport->dummy_tx_desc->next_desc_addr =
-				(unsigned long)(sport->dma_tx_desc);
+			sizeof(struct dmasg)) != sport->dummy_tx_desc)
+			continue;
+		sport->dummy_tx_desc->next_desc_addr = sport->dma_tx_desc;
 		local_irq_restore(flags);
 		sport->curr_tx_desc = sport->dma_tx_desc;
 	} else {
@@ -536,19 +524,17 @@
 	unsigned config;
 
 	pr_debug("%s entered\n", __func__);
-#if L1_DATA_A_LENGTH != 0
-	desc = (struct dmasg *) l1_data_sram_alloc(2 * sizeof(*desc));
-#else
-	{
+	if (L1_DATA_A_LENGTH)
+		desc = l1_data_sram_zalloc(2 * sizeof(*desc));
+	else {
 		dma_addr_t addr;
 		desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0);
+		memset(desc, 0, 2 * sizeof(*desc));
 	}
-#endif
 	if (desc == NULL) {
 		pr_err("Failed to allocate memory for dummy rx desc\n");
 		return -ENOMEM;
 	}
-	memset(desc, 0, 2 * sizeof(*desc));
 	sport->dummy_rx_desc = desc;
 	desc->start_addr = (unsigned long)sport->dummy_buf;
 	config = DMAFLOW_LARGE | NDSIZE_9 | compute_wdsize(sport->wdsize)
@@ -559,8 +545,8 @@
 	desc->y_count = 0;
 	desc->y_modify = 0;
 	memcpy(desc+1, desc, sizeof(*desc));
-	desc->next_desc_addr = (unsigned long)(desc+1);
-	desc[1].next_desc_addr = (unsigned long)desc;
+	desc->next_desc_addr = desc + 1;
+	desc[1].next_desc_addr = desc;
 	return 0;
 }
 
@@ -571,19 +557,17 @@
 
 	pr_debug("%s entered\n", __func__);
 
-#if L1_DATA_A_LENGTH != 0
-	desc = (struct dmasg *) l1_data_sram_alloc(2 * sizeof(*desc));
-#else
-	{
+	if (L1_DATA_A_LENGTH)
+		desc = l1_data_sram_zalloc(2 * sizeof(*desc));
+	else {
 		dma_addr_t addr;
 		desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0);
+		memset(desc, 0, 2 * sizeof(*desc));
 	}
-#endif
 	if (!desc) {
 		pr_err("Failed to allocate memory for dummy tx desc\n");
 		return -ENOMEM;
 	}
-	memset(desc, 0, 2 * sizeof(*desc));
 	sport->dummy_tx_desc = desc;
 	desc->start_addr = (unsigned long)sport->dummy_buf + \
 		sport->dummy_count;
@@ -595,8 +579,8 @@
 	desc->y_count = 0;
 	desc->y_modify = 0;
 	memcpy(desc+1, desc, sizeof(*desc));
-	desc->next_desc_addr = (unsigned long)(desc+1);
-	desc[1].next_desc_addr = (unsigned long)desc;
+	desc->next_desc_addr = desc + 1;
+	desc[1].next_desc_addr = desc;
 	return 0;
 }
 
@@ -872,17 +856,15 @@
 	sport->wdsize = wdsize;
 	sport->dummy_count = dummy_count;
 
-#if L1_DATA_A_LENGTH != 0
-	sport->dummy_buf = l1_data_sram_alloc(dummy_count * 2);
-#else
-	sport->dummy_buf = kmalloc(dummy_count * 2, GFP_KERNEL);
-#endif
+	if (L1_DATA_A_LENGTH)
+		sport->dummy_buf = l1_data_sram_zalloc(dummy_count * 2);
+	else
+		sport->dummy_buf = kzalloc(dummy_count * 2, GFP_KERNEL);
 	if (sport->dummy_buf == NULL) {
 		pr_err("Failed to allocate dummy buffer\n");
 		goto __error;
 	}
 
-	memset(sport->dummy_buf, 0, dummy_count * 2);
 	ret = sport_config_rx_dummy(sport);
 	if (ret) {
 		pr_err("Failed to config rx dummy ring\n");
@@ -939,6 +921,7 @@
 		sport = NULL;
 }
 EXPORT_SYMBOL(sport_done);
+
 /*
 * It is only used to send several bytes when dma is not enabled
  * sport controller is configured but not enabled.
@@ -1029,4 +1012,3 @@
 MODULE_AUTHOR("Roy Huang");
 MODULE_DESCRIPTION("SPORT driver for ADI Blackfin");
 MODULE_LICENSE("GPL");
-
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index d0e0d69..b6c7f7a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -10,9 +10,11 @@
 
 config SND_SOC_ALL_CODECS
 	tristate "Build all ASoC CODEC drivers"
+	select SND_SOC_L3
 	select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
 	select SND_SOC_AD1980 if SND_SOC_AC97_BUS
 	select SND_SOC_AD73311 if I2C
+	select SND_SOC_AK4104 if SPI_MASTER
 	select SND_SOC_AK4535 if I2C
 	select SND_SOC_CS4270 if I2C
 	select SND_SOC_PCM3008
@@ -24,6 +26,7 @@
 	select SND_SOC_UDA134X
 	select SND_SOC_UDA1380 if I2C
 	select SND_SOC_WM8350 if MFD_WM8350
+	select SND_SOC_WM8400 if MFD_WM8400
 	select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8580 if I2C
 	select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
@@ -34,6 +37,7 @@
 	select SND_SOC_WM8903 if I2C
 	select SND_SOC_WM8971 if I2C
 	select SND_SOC_WM8990 if I2C
+	select SND_SOC_WM9705 if SND_SOC_AC97_BUS
 	select SND_SOC_WM9712 if SND_SOC_AC97_BUS
 	select SND_SOC_WM9713 if SND_SOC_AC97_BUS
         help
@@ -58,6 +62,9 @@
 config SND_SOC_AD73311
 	tristate
 
+config SND_SOC_AK4104
+	tristate
+
 config SND_SOC_AK4535
 	tristate
 
@@ -65,12 +72,6 @@
 config SND_SOC_CS4270
 	tristate
 
-# Cirrus Logic CS4270 Codec Hardware Mute Support
-# Select if you have external muting circuitry attached to your CS4270.
-config SND_SOC_CS4270_HWMUTE
-	bool
-	depends on SND_SOC_CS4270
-
 # Cirrus Logic CS4270 Codec VD = 3.3V Errata
 # Select if you are affected by the errata where the part will not function
 # if MCLK divide-by-1.5 is selected and VD is set to 3.3V.  The driver will
@@ -90,7 +91,6 @@
 
 config SND_SOC_TLV320AIC23
 	tristate
-	depends on I2C
 
 config SND_SOC_TLV320AIC26
 	tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
@@ -98,15 +98,12 @@
 
 config SND_SOC_TLV320AIC3X
 	tristate
-	depends on I2C
 
 config SND_SOC_TWL4030
 	tristate
-	depends on TWL4030_CORE
 
 config SND_SOC_UDA134X
        tristate
-       select SND_SOC_L3
 
 config SND_SOC_UDA1380
         tristate
@@ -114,6 +111,9 @@
 config SND_SOC_WM8350
 	tristate
 
+config SND_SOC_WM8400
+	tristate
+
 config SND_SOC_WM8510
 	tristate
 
@@ -144,6 +144,9 @@
 config SND_SOC_WM8990
 	tristate
 
+config SND_SOC_WM9705
+	tristate
+
 config SND_SOC_WM9712
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index c4ddc9a..030d245 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,6 +1,7 @@
 snd-soc-ac97-objs := ac97.o
 snd-soc-ad1980-objs := ad1980.o
 snd-soc-ad73311-objs := ad73311.o
+snd-soc-ak4104-objs := ak4104.o
 snd-soc-ak4535-objs := ak4535.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-l3-objs := l3.o
@@ -13,6 +14,7 @@
 snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
 snd-soc-wm8350-objs := wm8350.o
+snd-soc-wm8400-objs := wm8400.o
 snd-soc-wm8510-objs := wm8510.o
 snd-soc-wm8580-objs := wm8580.o
 snd-soc-wm8728-objs := wm8728.o
@@ -23,12 +25,14 @@
 snd-soc-wm8903-objs := wm8903.o
 snd-soc-wm8971-objs := wm8971.o
 snd-soc-wm8990-objs := wm8990.o
+snd-soc-wm9705-objs := wm9705.o
 snd-soc-wm9712-objs := wm9712.o
 snd-soc-wm9713-objs := wm9713.o
 
 obj-$(CONFIG_SND_SOC_AC97_CODEC)	+= snd-soc-ac97.o
 obj-$(CONFIG_SND_SOC_AD1980)	+= snd-soc-ad1980.o
 obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
+obj-$(CONFIG_SND_SOC_AK4104)	+= snd-soc-ak4104.o
 obj-$(CONFIG_SND_SOC_AK4535)	+= snd-soc-ak4535.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_L3)	+= snd-soc-l3.o
@@ -41,6 +45,7 @@
 obj-$(CONFIG_SND_SOC_UDA134X)	+= snd-soc-uda134x.o
 obj-$(CONFIG_SND_SOC_UDA1380)	+= snd-soc-uda1380.o
 obj-$(CONFIG_SND_SOC_WM8350)	+= snd-soc-wm8350.o
+obj-$(CONFIG_SND_SOC_WM8400)	+= snd-soc-wm8400.o
 obj-$(CONFIG_SND_SOC_WM8510)	+= snd-soc-wm8510.o
 obj-$(CONFIG_SND_SOC_WM8580)	+= snd-soc-wm8580.o
 obj-$(CONFIG_SND_SOC_WM8728)	+= snd-soc-wm8728.o
@@ -51,5 +56,7 @@
 obj-$(CONFIG_SND_SOC_WM8903)	+= snd-soc-wm8903.o
 obj-$(CONFIG_SND_SOC_WM8971)	+= snd-soc-wm8971.o
 obj-$(CONFIG_SND_SOC_WM8990)	+= snd-soc-wm8990.o
+obj-$(CONFIG_SND_SOC_WM8991)	+= snd-soc-wm8991.o
+obj-$(CONFIG_SND_SOC_WM9705)	+= snd-soc-wm9705.o
 obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index fb53e65..b0d4af1 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -30,7 +30,7 @@
 	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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
 		  AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
@@ -41,6 +41,10 @@
 		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
 		SNDRV_PCM_RATE_48000)
 
+static struct snd_soc_dai_ops ac97_dai_ops = {
+	.prepare	= ac97_prepare,
+};
+
 struct snd_soc_dai ac97_dai = {
 	.name = "AC97 HiFi",
 	.ac97_control = 1,
@@ -56,8 +60,7 @@
 		.channels_max = 2,
 		.rates = STD_AC97_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.prepare = ac97_prepare,},
+	.ops = &ac97_dai_ops,
 };
 EXPORT_SYMBOL_GPL(ac97_dai);
 
@@ -84,10 +87,10 @@
 
 	printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
 
-	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-	if (!socdev->codec)
+	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (!socdev->card->codec)
 		return -ENOMEM;
-	codec = socdev->codec;
+	codec = socdev->card->codec;
 	mutex_init(&codec->mutex);
 
 	codec->name = "AC97";
@@ -123,23 +126,21 @@
 	snd_soc_free_pcms(socdev);
 
 err:
-	kfree(socdev->codec->reg_cache);
-	kfree(socdev->codec);
-	socdev->codec = NULL;
+	kfree(socdev->card->codec);
+	socdev->card->codec = NULL;
 	return ret;
 }
 
 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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (!codec)
 		return 0;
 
 	snd_soc_free_pcms(socdev);
-	kfree(socdev->codec->reg_cache);
-	kfree(socdev->codec);
+	kfree(socdev->card->codec);
 
 	return 0;
 }
@@ -149,7 +150,7 @@
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 
-	snd_ac97_suspend(socdev->codec->ac97);
+	snd_ac97_suspend(socdev->card->codec->ac97);
 
 	return 0;
 }
@@ -158,7 +159,7 @@
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 
-	snd_ac97_resume(socdev->codec->ac97);
+	snd_ac97_resume(socdev->card->codec->ac97);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 73fdbb4..ddb3b08 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -93,20 +93,6 @@
 SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
 };
 
-/* add non dapm controls */
-static int ad1980_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(ad1980_snd_ac97_controls); i++) {
-		err = snd_ctl_add(codec->card, snd_soc_cnew(
-				&ad1980_snd_ac97_controls[i], codec, NULL));
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
 static unsigned int ac97_read(struct snd_soc_codec *codec,
 	unsigned int reg)
 {
@@ -123,7 +109,7 @@
 	default:
 		reg = reg >> 1;
 
-		if (reg >= (ARRAY_SIZE(ad1980_reg)))
+		if (reg >= ARRAY_SIZE(ad1980_reg))
 			return -EINVAL;
 
 		return cache[reg];
@@ -137,7 +123,7 @@
 
 	soc_ac97_ops.write(codec->ac97, reg, val);
 	reg = reg >> 1;
-	if (reg < (ARRAY_SIZE(ad1980_reg)))
+	if (reg < ARRAY_SIZE(ad1980_reg))
 		cache[reg] = val;
 
 	return 0;
@@ -200,10 +186,10 @@
 
 	printk(KERN_INFO "AD1980 SoC Audio Codec\n");
 
-	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-	if (socdev->codec == NULL)
+	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (socdev->card->codec == NULL)
 		return -ENOMEM;
-	codec = socdev->codec;
+	codec = socdev->card->codec;
 	mutex_init(&codec->mutex);
 
 	codec->reg_cache =
@@ -269,7 +255,8 @@
 	ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
 	ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
 
-	ad1980_add_controls(codec);
+	snd_soc_add_controls(codec, ad1980_snd_ac97_controls,
+				ARRAY_SIZE(ad1980_snd_ac97_controls));
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
 		printk(KERN_ERR "ad1980: failed to register card\n");
@@ -288,15 +275,15 @@
 	kfree(codec->reg_cache);
 
 cache_err:
-	kfree(socdev->codec);
-	socdev->codec = NULL;
+	kfree(socdev->card->codec);
+	socdev->card->codec = NULL;
 	return ret;
 }
 
 static int ad1980_soc_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec == NULL)
 		return 0;
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index b09289a..e61dac5 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -53,7 +53,7 @@
 	codec->owner = THIS_MODULE;
 	codec->dai = &ad73311_dai;
 	codec->num_dai = 1;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
 
@@ -75,15 +75,15 @@
 register_err:
 	snd_soc_free_pcms(socdev);
 pcm_err:
-	kfree(socdev->codec);
-	socdev->codec = NULL;
+	kfree(socdev->card->codec);
+	socdev->card->codec = NULL;
 	return ret;
 }
 
 static int ad73311_soc_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec == NULL)
 		return 0;
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h
index 507ce0c..569573d 100644
--- a/sound/soc/codecs/ad73311.h
+++ b/sound/soc/codecs/ad73311.h
@@ -70,7 +70,7 @@
 #define REGD_IGS(x)		(x & 0x7)
 #define REGD_RMOD		(1 << 3)
 #define REGD_OGS(x)		((x & 0x7) << 4)
-#define REGD_MUTE		(x << 7)
+#define REGD_MUTE		(1 << 7)
 
 /* Control register E */
 #define CTRL_REG_E	(4 << 8)
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
new file mode 100644
index 0000000..4d47bc4
--- /dev/null
+++ b/sound/soc/codecs/ak4104.c
@@ -0,0 +1,365 @@
+/*
+ * AK4104 ALSA SoC (ASoC) driver
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under the terms of  the GNU General  Public License 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 <sound/core.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <linux/spi/spi.h>
+#include <sound/asoundef.h>
+
+#include "ak4104.h"
+
+/* AK4104 registers addresses */
+#define AK4104_REG_CONTROL1		0x00
+#define AK4104_REG_RESERVED		0x01
+#define AK4104_REG_CONTROL2		0x02
+#define AK4104_REG_TX			0x03
+#define AK4104_REG_CHN_STATUS(x)	((x) + 0x04)
+#define AK4104_NUM_REGS			10
+
+#define AK4104_REG_MASK			0x1f
+#define AK4104_READ			0xc0
+#define AK4104_WRITE			0xe0
+#define AK4104_RESERVED_VAL		0x5b
+
+/* Bit masks for AK4104 registers */
+#define AK4104_CONTROL1_RSTN		(1 << 0)
+#define AK4104_CONTROL1_PW		(1 << 1)
+#define AK4104_CONTROL1_DIF0		(1 << 2)
+#define AK4104_CONTROL1_DIF1		(1 << 3)
+
+#define AK4104_CONTROL2_SEL0		(1 << 0)
+#define AK4104_CONTROL2_SEL1		(1 << 1)
+#define AK4104_CONTROL2_MODE		(1 << 2)
+
+#define AK4104_TX_TXE			(1 << 0)
+#define AK4104_TX_V			(1 << 1)
+
+#define DRV_NAME "ak4104"
+
+struct ak4104_private {
+	struct snd_soc_codec codec;
+	u8 reg_cache[AK4104_NUM_REGS];
+};
+
+static int ak4104_fill_cache(struct snd_soc_codec *codec)
+{
+	int i;
+	u8 *reg_cache = codec->reg_cache;
+	struct spi_device *spi = codec->control_data;
+
+	for (i = 0; i < codec->reg_cache_size; i++) {
+		int ret = spi_w8r8(spi, i | AK4104_READ);
+		if (ret < 0) {
+			dev_err(&spi->dev, "SPI write failure\n");
+			return ret;
+		}
+
+		reg_cache[i] = ret;
+	}
+
+	return 0;
+}
+
+static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,
+					  unsigned int reg)
+{
+	u8 *reg_cache = codec->reg_cache;
+
+	if (reg >= codec->reg_cache_size)
+		return -EINVAL;
+
+	return reg_cache[reg];
+}
+
+static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
+			    unsigned int value)
+{
+	u8 *cache = codec->reg_cache;
+	struct spi_device *spi = codec->control_data;
+
+	if (reg >= codec->reg_cache_size)
+		return -EINVAL;
+
+	reg &= AK4104_REG_MASK;
+	reg |= AK4104_WRITE;
+
+	/* only write to the hardware if value has changed */
+	if (cache[reg] != value) {
+		u8 tmp[2] = { reg, value };
+		if (spi_write(spi, tmp, sizeof(tmp))) {
+			dev_err(&spi->dev, "SPI write failed\n");
+			return -EIO;
+		}
+
+		cache[reg] = value;
+	}
+
+	return 0;
+}
+
+static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			      unsigned int format)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	int val = 0;
+
+	val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
+	if (val < 0)
+		return val;
+
+	val &= ~(AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1);
+
+	/* set DAI format */
+	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_RIGHT_J:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		val |= AK4104_CONTROL1_DIF0;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		val |= AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1;
+		break;
+	default:
+		dev_err(codec->dev, "invalid dai format\n");
+		return -EINVAL;
+	}
+
+	/* This device can only be slave */
+	if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+		return -EINVAL;
+
+	return ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+}
+
+static int ak4104_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->card->codec;
+	int val = 0;
+
+	/* set the IEC958 bits: consumer mode, no copyright bit */
+	val |= IEC958_AES0_CON_NOT_COPYRIGHT;
+	ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(0), val);
+
+	val = 0;
+
+	switch (params_rate(params)) {
+	case 44100:
+		val |= IEC958_AES3_CON_FS_44100;
+		break;
+	case 48000:
+		val |= IEC958_AES3_CON_FS_48000;
+		break;
+	case 32000:
+		val |= IEC958_AES3_CON_FS_32000;
+		break;
+	default:
+		dev_err(codec->dev, "unsupported sampling rate\n");
+		return -EINVAL;
+	}
+
+	return ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(3), val);
+}
+
+static struct snd_soc_dai_ops ak4101_dai_ops = {
+	.hw_params = ak4104_hw_params,
+	.set_fmt = ak4104_set_dai_fmt,
+};
+
+struct snd_soc_dai ak4104_dai = {
+	.name = DRV_NAME,
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_44100 |
+			 SNDRV_PCM_RATE_48000 |
+			 SNDRV_PCM_RATE_32000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE  |
+			   SNDRV_PCM_FMTBIT_S24_3LE |
+			   SNDRV_PCM_FMTBIT_S24_LE
+	},
+	.ops = &ak4101_dai_ops,
+};
+
+static struct snd_soc_codec *ak4104_codec;
+
+static int ak4104_spi_probe(struct spi_device *spi)
+{
+	struct snd_soc_codec *codec;
+	struct ak4104_private *ak4104;
+	int ret, val;
+
+	spi->bits_per_word = 8;
+	spi->mode = SPI_MODE_0;
+	ret = spi_setup(spi);
+	if (ret < 0)
+		return ret;
+
+	ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
+	if (!ak4104) {
+		dev_err(&spi->dev, "could not allocate codec\n");
+		return -ENOMEM;
+	}
+
+	codec = &ak4104->codec;
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	codec->dev = &spi->dev;
+	codec->name = DRV_NAME;
+	codec->owner = THIS_MODULE;
+	codec->dai = &ak4104_dai;
+	codec->num_dai = 1;
+	codec->private_data = ak4104;
+	codec->control_data = spi;
+	codec->reg_cache = ak4104->reg_cache;
+	codec->reg_cache_size = AK4104_NUM_REGS;
+
+	/* read all regs and fill the cache */
+	ret = ak4104_fill_cache(codec);
+	if (ret < 0) {
+		dev_err(&spi->dev, "failed to fill register cache\n");
+		return ret;
+	}
+
+	/* read the 'reserved' register - according to the datasheet, it
+	 * should contain 0x5b. Not a good way to verify the presence of
+	 * the device, but there is no hardware ID register. */
+	if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) !=
+					 AK4104_RESERVED_VAL) {
+		ret = -ENODEV;
+		goto error_free_codec;
+	}
+
+	/* set power-up and non-reset bits */
+	val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
+	val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN;
+	ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+	if (ret < 0)
+		goto error_free_codec;
+
+	/* enable transmitter */
+	val = ak4104_read_reg_cache(codec, AK4104_REG_TX);
+	val |= AK4104_TX_TXE;
+	ret = ak4104_spi_write(codec, AK4104_REG_TX, val);
+	if (ret < 0)
+		goto error_free_codec;
+
+	ak4104_codec = codec;
+	ret = snd_soc_register_dai(&ak4104_dai);
+	if (ret < 0) {
+		dev_err(&spi->dev, "failed to register DAI\n");
+		goto error_free_codec;
+	}
+
+	spi_set_drvdata(spi, ak4104);
+	dev_info(&spi->dev, "SPI device initialized\n");
+	return 0;
+
+error_free_codec:
+	kfree(ak4104);
+	ak4104_dai.dev = NULL;
+	return ret;
+}
+
+static int __devexit ak4104_spi_remove(struct spi_device *spi)
+{
+	int ret, val;
+	struct ak4104_private *ak4104 = spi_get_drvdata(spi);
+
+	val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1);
+	if (val < 0)
+		return val;
+
+	/* clear power-up and non-reset bits */
+	val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
+	ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val);
+	if (ret < 0)
+		return ret;
+
+	ak4104_codec = NULL;
+	kfree(ak4104);
+	return 0;
+}
+
+static int ak4104_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = ak4104_codec;
+	int ret;
+
+	/* Connect the codec to the socdev.  snd_soc_new_pcms() needs this. */
+	socdev->card->codec = codec;
+
+	/* Register PCMs */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0) {
+		dev_err(codec->dev, "failed to create pcms\n");
+		return ret;
+	}
+
+	/* Register the socdev */
+	ret = snd_soc_init_card(socdev);
+	if (ret < 0) {
+		dev_err(codec->dev, "failed to register card\n");
+		snd_soc_free_pcms(socdev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ak4104_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	snd_soc_free_pcms(socdev);
+	return 0;
+};
+
+struct snd_soc_codec_device soc_codec_device_ak4104 = {
+	.probe = 	ak4104_probe,
+	.remove = 	ak4104_remove
+};
+EXPORT_SYMBOL_GPL(soc_codec_device_ak4104);
+
+static struct spi_driver ak4104_spi_driver = {
+	.driver  = {
+		.name   = DRV_NAME,
+		.owner  = THIS_MODULE,
+	},
+	.probe  = ak4104_spi_probe,
+	.remove = __devexit_p(ak4104_spi_remove),
+};
+
+static int __init ak4104_init(void)
+{
+	pr_info("Asahi Kasei AK4104 ALSA SoC Codec Driver\n");
+	return spi_register_driver(&ak4104_spi_driver);
+}
+module_init(ak4104_init);
+
+static void __exit ak4104_exit(void)
+{
+	spi_unregister_driver(&ak4104_spi_driver);
+}
+module_exit(ak4104_exit);
+
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
+MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/codecs/ak4104.h b/sound/soc/codecs/ak4104.h
new file mode 100644
index 0000000..eb88fe7
--- /dev/null
+++ b/sound/soc/codecs/ak4104.h
@@ -0,0 +1,7 @@
+#ifndef _AK4104_H
+#define _AK4104_H
+
+extern struct snd_soc_dai ak4104_dai;
+extern struct snd_soc_codec_device soc_codec_device_ak4104;
+
+#endif
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 81300d8d..1f63d38 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -155,21 +155,6 @@
 	SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0),
 };
 
-/* add non dapm controls */
-static int ak4535_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(ak4535_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&ak4535_snd_controls[i], codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 /* Mono 1 Mixer */
 static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = {
 	SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0),
@@ -344,7 +329,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct ak4535_priv *ak4535 = codec->private_data;
 	u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
 	int rate = params_rate(params), fs = 256;
@@ -436,6 +421,13 @@
 		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
 		SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
 
+static struct snd_soc_dai_ops ak4535_dai_ops = {
+	.hw_params	= ak4535_hw_params,
+	.set_fmt	= ak4535_set_dai_fmt,
+	.digital_mute	= ak4535_mute,
+	.set_sysclk	= ak4535_set_dai_sysclk,
+};
+
 struct snd_soc_dai ak4535_dai = {
 	.name = "AK4535",
 	.playback = {
@@ -450,19 +442,14 @@
 		.channels_max = 2,
 		.rates = AK4535_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.hw_params = ak4535_hw_params,
-		.set_fmt = ak4535_set_dai_fmt,
-		.digital_mute = ak4535_mute,
-		.set_sysclk = ak4535_set_dai_sysclk,
-	},
+	.ops = &ak4535_dai_ops,
 };
 EXPORT_SYMBOL_GPL(ak4535_dai);
 
 static int ak4535_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -471,7 +458,7 @@
 static int ak4535_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	ak4535_sync(codec);
 	ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	ak4535_set_bias_level(codec, codec->suspend_bias_level);
@@ -484,7 +471,7 @@
  */
 static int ak4535_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret = 0;
 
 	codec->name = "AK4535";
@@ -510,7 +497,8 @@
 	/* power on device */
 	ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	ak4535_add_controls(codec);
+	snd_soc_add_controls(codec, ak4535_snd_controls,
+				ARRAY_SIZE(ak4535_snd_controls));
 	ak4535_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -537,7 +525,7 @@
 			    const struct i2c_device_id *id)
 {
 	struct snd_soc_device *socdev = ak4535_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	i2c_set_clientdata(i2c, codec);
@@ -636,7 +624,7 @@
 	}
 
 	codec->private_data = ak4535;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -663,7 +651,7 @@
 static int ak4535_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec->control_data)
 		ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index f1aa0c3..7fa09a3 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -3,27 +3,22 @@
  *
  * Author: Timur Tabi <timur@freescale.com>
  *
- * Copyright 2007 Freescale Semiconductor, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.  This file is licensed
+ * under the terms of the GNU General Public License version 2.  This
+ * program is licensed "as is" without any warranty of any kind, whether
+ * express or implied.
  *
  * This is an ASoC device driver for the Cirrus Logic CS4270 codec.
  *
  * Current features/limitations:
  *
- * 1) Software mode is supported.  Stand-alone mode is automatically
- *    selected if I2C is disabled or if a CS4270 is not found on the I2C
- *    bus.  However, stand-alone mode is only partially implemented because
- *    there is no mechanism yet for this driver and the machine driver to
- *    communicate the values of the M0, M1, MCLK1, and MCLK2 pins.
- * 2) Only I2C is supported, not SPI
- * 3) Only Master mode is supported, not Slave.
- * 4) The machine driver's 'startup' function must call
- *    cs4270_set_dai_sysclk() with the value of MCLK.
- * 5) Only I2S and left-justified modes are supported
- * 6) Power management is not supported
- * 7) The only supported control is volume and hardware mute (if enabled)
+ * - Software mode is supported.  Stand-alone mode is not supported.
+ * - Only I2C is supported, not SPI
+ * - Support for master and slave mode
+ * - The machine driver's 'startup' function must call
+ *   cs4270_set_dai_sysclk() with the value of MCLK.
+ * - Only I2S and left-justified modes are supported
+ * - Power management is not supported
  */
 
 #include <linux/module.h>
@@ -35,18 +30,6 @@
 
 #include "cs4270.h"
 
-/* If I2C is defined, then we support software mode.  However, if we're
-   not compiled as module but I2C is, then we can't use I2C calls. */
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-#define USE_I2C
-#endif
-
-/* Private data for the CS4270 */
-struct cs4270_private {
-	unsigned int mclk; /* Input frequency of the MCLK pin */
-	unsigned int mode; /* The mode (I2S or left-justified) */
-};
-
 /*
  * The codec isn't really big-endian or little-endian, since the I2S
  * interface requires data to be sent serially with the MSbit first.
@@ -60,8 +43,6 @@
 			SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
 			SNDRV_PCM_FMTBIT_S24_LE  | SNDRV_PCM_FMTBIT_S24_BE)
 
-#ifdef USE_I2C
-
 /* CS4270 registers addresses */
 #define CS4270_CHIPID	0x01	/* Chip ID */
 #define CS4270_PWRCTL	0x02	/* Power Control */
@@ -121,8 +102,22 @@
 #define CS4270_MUTE_DAC_A	0x01
 #define CS4270_MUTE_DAC_B	0x02
 
-/*
- * Clock Ratio Selection for Master Mode with I2C enabled
+/* Private data for the CS4270 */
+struct cs4270_private {
+	struct snd_soc_codec codec;
+	u8 reg_cache[CS4270_NUMREGS];
+	unsigned int mclk; /* Input frequency of the MCLK pin */
+	unsigned int mode; /* The mode (I2S or left-justified) */
+	unsigned int slave_mode;
+};
+
+/**
+ * struct cs4270_mode_ratios - clock ratio tables
+ * @ratio: the ratio of MCLK to the sample rate
+ * @speed_mode: the Speed Mode bits to set in the Mode Control register for
+ *              this ratio
+ * @mclk: the Ratio Select bits to set in the Mode Control register for this
+ *        ratio
  *
  * The data for this chart is taken from Table 5 of the CS4270 reference
  * manual.
@@ -131,31 +126,30 @@
  * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling
  * rates the CS4270 currently supports.
  *
- * Each element in this array corresponds to the ratios in mclk_ratios[].
- * These two arrays need to be in sync.
- *
- * 'speed_mode' is the corresponding bit pattern to be written to the
+ * @speed_mode is the corresponding bit pattern to be written to the
  * MODE bits of the Mode Control Register
  *
- * 'mclk' is the corresponding bit pattern to be wirten to the MCLK bits of
+ * @mclk is the corresponding bit pattern to be wirten to the MCLK bits of
  * the Mode Control Register.
  *
  * In situations where a single ratio is represented by multiple speed
  * modes, we favor the slowest speed.  E.g, for a ratio of 128, we pick
  * double-speed instead of quad-speed.  However, the CS4270 errata states
- * that Divide-By-1.5 can cause failures, so we avoid that mode where
+ * that divide-By-1.5 can cause failures, so we avoid that mode where
  * possible.
  *
- * ERRATA: There is an errata for the CS4270 where divide-by-1.5 does not
- * work if VD = 3.3V.  If this effects you, select the
+ * Errata: There is an errata for the CS4270 where divide-by-1.5 does not
+ * work if Vd is 3.3V.  If this effects you, select the
  * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will
  * never select any sample rates that require divide-by-1.5.
  */
-static struct {
+struct cs4270_mode_ratios {
 	unsigned int ratio;
 	u8 speed_mode;
 	u8 mclk;
-} cs4270_mode_ratios[] = {
+};
+
+static struct cs4270_mode_ratios cs4270_mode_ratios[] = {
 	{64, CS4270_MODE_4X, CS4270_MODE_DIV1},
 #ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA
 	{96, CS4270_MODE_4X, CS4270_MODE_DIV15},
@@ -172,34 +166,27 @@
 /* The number of MCLK/LRCK ratios supported by the CS4270 */
 #define NUM_MCLK_RATIOS		ARRAY_SIZE(cs4270_mode_ratios)
 
-/*
- * Determine the CS4270 samples rates.
+/**
+ * cs4270_set_dai_sysclk - determine the CS4270 samples rates.
+ * @codec_dai: the codec DAI
+ * @clk_id: the clock ID (ignored)
+ * @freq: the MCLK input frequency
+ * @dir: the clock direction (ignored)
  *
- * 'freq' is the input frequency to MCLK.  The other parameters are ignored.
+ * This function is used to tell the codec driver what the input MCLK
+ * frequency is.
  *
  * The value of MCLK is used to determine which sample rates are supported
  * by the CS4270.  The ratio of MCLK / Fs must be equal to one of nine
- * support values: 64, 96, 128, 192, 256, 384, 512, 768, and 1024.
+ * supported values - 64, 96, 128, 192, 256, 384, 512, 768, and 1024.
  *
  * This function calculates the nine ratios and determines which ones match
  * a standard sample rate.  If there's a match, then it is added to the list
- * of support sample rates.
+ * of supported sample rates.
  *
  * This function must be called by the machine driver's 'startup' function,
  * otherwise the list of supported sample rates will not be available in
  * time for ALSA.
- *
- * Note that in stand-alone mode, the sample rate is determined by input
- * pins M0, M1, MDIV1, and MDIV2.  Also in stand-alone mode, divide-by-3
- * is not a programmable option.  However, divide-by-3 is not an available
- * option in stand-alone mode.  This cases two problems: a ratio of 768 is
- * not available (it requires divide-by-3) and B) ratios 192 and 384 can
- * only be selected with divide-by-1.5, but there is an errate that make
- * this selection difficult.
- *
- * In addition, there is no mechanism for communicating with the machine
- * driver what the input settings can be.  This would need to be implemented
- * for stand-alone mode to work.
  */
 static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 				 int clk_id, unsigned int freq, int dir)
@@ -225,7 +212,7 @@
 	rates &= ~SNDRV_PCM_RATE_KNOT;
 
 	if (!rates) {
-		printk(KERN_ERR "cs4270: could not find a valid sample rate\n");
+		dev_err(codec->dev, "could not find a valid sample rate\n");
 		return -EINVAL;
 	}
 
@@ -240,8 +227,10 @@
 	return 0;
 }
 
-/*
- * Configure the codec for the selected audio format
+/**
+ * cs4270_set_dai_fmt - configure the codec for the selected audio format
+ * @codec_dai: the codec DAI
+ * @format: a SND_SOC_DAIFMT_x value indicating the data format
  *
  * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
  * codec accordingly.
@@ -258,32 +247,43 @@
 	struct cs4270_private *cs4270 = codec->private_data;
 	int ret = 0;
 
+	/* set DAI format */
 	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
 	case SND_SOC_DAIFMT_LEFT_J:
 		cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
 		break;
 	default:
-		printk(KERN_ERR "cs4270: invalid DAI format\n");
+		dev_err(codec->dev, "invalid dai format\n");
+		ret = -EINVAL;
+	}
+
+	/* set master/slave audio interface */
+	switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		cs4270->slave_mode = 1;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		cs4270->slave_mode = 0;
+		break;
+	default:
+		/* all other modes are unsupported by the hardware */
 		ret = -EINVAL;
 	}
 
 	return ret;
 }
 
-/*
- * A list of addresses on which this CS4270 could use.  I2C addresses are
- * 7 bits.  For the CS4270, the upper four bits are always 1001, and the
- * lower three bits are determined via the AD2, AD1, and AD0 pins
- * (respectively).
- */
-static const unsigned short normal_i2c[] = {
-	0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, I2C_CLIENT_END
-};
-I2C_CLIENT_INSMOD;
-
-/*
- * Pre-fill the CS4270 register cache.
+/**
+ * cs4270_fill_cache - pre-fill the CS4270 register cache.
+ * @codec: the codec for this CS4270
+ *
+ * This function fills in the CS4270 register cache by reading the register
+ * values from the hardware.
+ *
+ * This CS4270 registers are cached to avoid excessive I2C I/O operations.
+ * After the initial read to pre-fill the cache, the CS4270 never updates
+ * the register values, so we won't have a cache coherency problem.
  *
  * We use the auto-increment feature of the CS4270 to read all registers in
  * one shot.
@@ -298,7 +298,7 @@
 		CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache);
 
 	if (length != CS4270_NUMREGS) {
-		printk(KERN_ERR "cs4270: I2C read failure, addr=0x%x\n",
+		dev_err(codec->dev, "i2c read failure, addr=0x%x\n",
 		       i2c_client->addr);
 		return -EIO;
 	}
@@ -306,12 +306,17 @@
 	return 0;
 }
 
-/*
- * Read from the CS4270 register cache.
+/**
+ * cs4270_read_reg_cache - read from the CS4270 register cache.
+ * @codec: the codec for this CS4270
+ * @reg: the register to read
+ *
+ * This function returns the value for a given register.  It reads only from
+ * the register cache, not the hardware itself.
  *
  * This CS4270 registers are cached to avoid excessive I2C I/O operations.
  * After the initial read to pre-fill the cache, the CS4270 never updates
- * the register values, so we won't have a cache coherncy problem.
+ * the register values, so we won't have a cache coherency problem.
  */
 static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec,
 	unsigned int reg)
@@ -324,8 +329,11 @@
 	return cache[reg - CS4270_FIRSTREG];
 }
 
-/*
- * Write to a CS4270 register via the I2C bus.
+/**
+ * cs4270_i2c_write - write to a CS4270 register via the I2C bus.
+ * @codec: the codec for this CS4270
+ * @reg: the register to write
+ * @value: the value to write to the register
  *
  * This function writes the given value to the given CS4270 register, and
  * also updates the register cache.
@@ -346,7 +354,7 @@
 	if (cache[reg - CS4270_FIRSTREG] != value) {
 		struct i2c_client *client = codec->control_data;
 		if (i2c_smbus_write_byte_data(client, reg, value)) {
-			printk(KERN_ERR "cs4270: I2C write failed\n");
+			dev_err(codec->dev, "i2c write failed\n");
 			return -EIO;
 		}
 
@@ -357,11 +365,17 @@
 	return 0;
 }
 
-/*
- * Program the CS4270 with the given hardware parameters.
+/**
+ * cs4270_hw_params - program the CS4270 with the given hardware parameters.
+ * @substream: the audio stream
+ * @params: the hardware parameters to set
+ * @dai: the SOC DAI (ignored)
  *
- * The .ops functions are used to provide board-specific data, like
- * input frequencies, to this driver.  This function takes that information,
+ * This function programs the hardware with the values provided.
+ * Specifically, the sample rate and the data format.
+ *
+ * The .ops functions are used to provide board-specific data, like input
+ * frequencies, to this driver.  This function takes that information,
  * combines it with the hardware parameters provided, and programs the
  * hardware accordingly.
  */
@@ -371,7 +385,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct cs4270_private *cs4270 = codec->private_data;
 	int ret;
 	unsigned int i;
@@ -391,33 +405,28 @@
 
 	if (i == NUM_MCLK_RATIOS) {
 		/* We did not find a matching ratio */
-		printk(KERN_ERR "cs4270: could not find matching ratio\n");
+		dev_err(codec->dev, "could not find matching ratio\n");
 		return -EINVAL;
 	}
 
-	/* Freeze and power-down the codec */
-
-	ret = snd_soc_write(codec, CS4270_PWRCTL, CS4270_PWRCTL_FREEZE |
-			    CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC |
-			    CS4270_PWRCTL_PDN);
-	if (ret < 0) {
-		printk(KERN_ERR "cs4270: I2C write failed\n");
-		return ret;
-	}
-
-	/* Program the mode control register */
+	/* Set the sample rate */
 
 	reg = snd_soc_read(codec, CS4270_MODE);
 	reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK);
-	reg |= cs4270_mode_ratios[i].speed_mode | cs4270_mode_ratios[i].mclk;
+	reg |= cs4270_mode_ratios[i].mclk;
+
+	if (cs4270->slave_mode)
+		reg |= CS4270_MODE_SLAVE;
+	else
+		reg |= cs4270_mode_ratios[i].speed_mode;
 
 	ret = snd_soc_write(codec, CS4270_MODE, reg);
 	if (ret < 0) {
-		printk(KERN_ERR "cs4270: I2C write failed\n");
+		dev_err(codec->dev, "i2c write failed\n");
 		return ret;
 	}
 
-	/* Program the format register */
+	/* Set the DAI format */
 
 	reg = snd_soc_read(codec, CS4270_FORMAT);
 	reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK);
@@ -430,55 +439,23 @@
 		reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ;
 		break;
 	default:
-		printk(KERN_ERR "cs4270: unknown format\n");
+		dev_err(codec->dev, "unknown dai format\n");
 		return -EINVAL;
 	}
 
 	ret = snd_soc_write(codec, CS4270_FORMAT, reg);
 	if (ret < 0) {
-		printk(KERN_ERR "cs4270: I2C write failed\n");
-		return ret;
-	}
-
-	/* Disable auto-mute.  This feature appears to be buggy, because in
-	   some situations, auto-mute will not deactivate when it should. */
-
-	reg = snd_soc_read(codec, CS4270_MUTE);
-	reg &= ~CS4270_MUTE_AUTO;
-	ret = snd_soc_write(codec, CS4270_MUTE, reg);
-	if (ret < 0) {
-		printk(KERN_ERR "cs4270: I2C write failed\n");
-		return ret;
-	}
-
-	/* Disable automatic volume control.  It's enabled by default, and
-	 * it causes volume change commands to be delayed, sometimes until
-	 * after playback has started.
-	 */
-
-	reg = cs4270_read_reg_cache(codec, CS4270_TRANS);
-	reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
-	ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
-	if (ret < 0) {
-		printk(KERN_ERR "I2C write failed\n");
-		return ret;
-	}
-
-	/* Thaw and power-up the codec */
-
-	ret = snd_soc_write(codec, CS4270_PWRCTL, 0);
-	if (ret < 0) {
-		printk(KERN_ERR "cs4270: I2C write failed\n");
+		dev_err(codec->dev, "i2c write failed\n");
 		return ret;
 	}
 
 	return ret;
 }
 
-#ifdef CONFIG_SND_SOC_CS4270_HWMUTE
-
-/*
- * Set the CS4270 external mute
+/**
+ * cs4270_mute - enable/disable the CS4270 external mute
+ * @dai: the SOC DAI
+ * @mute: 0 = disable mute, 1 = enable mute
  *
  * This function toggles the mute bits in the MUTE register.  The CS4270's
  * mute capability is intended for external muting circuitry, so if the
@@ -493,150 +470,47 @@
 	reg6 = snd_soc_read(codec, CS4270_MUTE);
 
 	if (mute)
-		reg6 |= CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B |
-			CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B;
+		reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B;
 	else
-		reg6 &= ~(CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B |
-			  CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B);
+		reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B);
 
 	return snd_soc_write(codec, CS4270_MUTE, reg6);
 }
 
-#endif
-
-static int cs4270_i2c_probe(struct i2c_client *, const struct i2c_device_id *);
-
 /* A list of non-DAPM controls that the CS4270 supports */
 static const struct snd_kcontrol_new cs4270_snd_controls[] = {
 	SOC_DOUBLE_R("Master Playback Volume",
-		CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1)
-};
-
-static const struct i2c_device_id cs4270_id[] = {
-	{"cs4270", 0},
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, cs4270_id);
-
-static struct i2c_driver cs4270_i2c_driver = {
-	.driver = {
-		.name = "CS4270 I2C",
-		.owner = THIS_MODULE,
-	},
-	.id_table = cs4270_id,
-	.probe = cs4270_i2c_probe,
+		CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1),
+	SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0),
+	SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0),
+	SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0),
+	SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1),
+	SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0),
+	SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 0)
 };
 
 /*
- * Global variable to store socdev for i2c probe function.
+ * cs4270_codec - global variable to store codec for the ASoC probe function
  *
  * If struct i2c_driver had a private_data field, we wouldn't need to use
- * cs4270_socdec.  This is the only way to pass the socdev structure to
- * cs4270_i2c_probe().
- *
- * The real solution to cs4270_socdev is to create a mechanism
- * that maps I2C addresses to snd_soc_device structures.  Perhaps the
- * creation of the snd_soc_device object should be moved out of
- * cs4270_probe() and into cs4270_i2c_probe(), but that would make this
- * driver dependent on I2C.  The CS4270 supports "stand-alone" mode, whereby
- * the chip is *not* connected to the I2C bus, but is instead configured via
- * input pins.
+ * cs4270_codec.  This is the only way to pass the codec structure from
+ * cs4270_i2c_probe() to cs4270_probe().  Unfortunately, there is no good
+ * way to synchronize these two functions.  cs4270_i2c_probe() can be called
+ * multiple times before cs4270_probe() is called even once.  So for now, we
+ * also only allow cs4270_i2c_probe() to be run once.  That means that we do
+ * not support more than one cs4270 device in the system, at least for now.
  */
-static struct snd_soc_device *cs4270_socdev;
+static struct snd_soc_codec *cs4270_codec;
 
-/*
- * Initialize the I2C interface of the CS4270
- *
- * This function is called for whenever the I2C subsystem finds a device
- * at a particular address.
- *
- * Note: snd_soc_new_pcms() must be called before this function can be called,
- * because of snd_ctl_add().
- */
-static int cs4270_i2c_probe(struct i2c_client *i2c_client,
-	const struct i2c_device_id *id)
-{
-	struct snd_soc_device *socdev = cs4270_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
-	int i;
-	int ret = 0;
-
-	/* Probing all possible addresses has one drawback: if there are
-	   multiple CS4270s on the bus, then you cannot specify which
-	   socdev is matched with which CS4270.  For now, we just reject
-	   this I2C device if the socdev already has one attached. */
-	if (codec->control_data)
-		return -ENODEV;
-
-	/* Note: codec_dai->codec is NULL here */
-
-	codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL);
-	if (!codec->reg_cache) {
-		printk(KERN_ERR "cs4270: could not allocate register cache\n");
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	/* Verify that we have a CS4270 */
-
-	ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
-	if (ret < 0) {
-		printk(KERN_ERR "cs4270: failed to read I2C\n");
-		goto error;
-	}
-	/* The top four bits of the chip ID should be 1100. */
-	if ((ret & 0xF0) != 0xC0) {
-		/* The device at this address is not a CS4270 codec */
-		ret = -ENODEV;
-		goto error;
-	}
-
-	printk(KERN_INFO "cs4270: found device at I2C address %X\n",
-		i2c_client->addr);
-	printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF);
-
-	codec->control_data = i2c_client;
-	codec->read = cs4270_read_reg_cache;
-	codec->write = cs4270_i2c_write;
-	codec->reg_cache_size = CS4270_NUMREGS;
-
-	/* The I2C interface is set up, so pre-fill our register cache */
-
-	ret = cs4270_fill_cache(codec);
-	if (ret < 0) {
-		printk(KERN_ERR "cs4270: failed to fill register cache\n");
-		goto error;
-	}
-
-	/* Add the non-DAPM controls */
-
-	for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) {
-		struct snd_kcontrol *kctrl =
-		snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL);
-
-		ret = snd_ctl_add(codec->card, kctrl);
-		if (ret < 0)
-			goto error;
-	}
-
-	i2c_set_clientdata(i2c_client, codec);
-
-	return 0;
-
-error:
-	codec->control_data = NULL;
-
-	kfree(codec->reg_cache);
-	codec->reg_cache = NULL;
-	codec->reg_cache_size = 0;
-
-	return ret;
-}
-
-#endif /* USE_I2C*/
+static struct snd_soc_dai_ops cs4270_dai_ops = {
+	.hw_params	= cs4270_hw_params,
+	.set_sysclk	= cs4270_set_dai_sysclk,
+	.set_fmt	= cs4270_set_dai_fmt,
+	.digital_mute	= cs4270_mute,
+};
 
 struct snd_soc_dai cs4270_dai = {
-	.name = "CS4270",
+	.name = "cs4270",
 	.playback = {
 		.stream_name = "Playback",
 		.channels_min = 1,
@@ -651,118 +525,251 @@
 		.rates = 0,
 		.formats = CS4270_FORMATS,
 	},
+	.ops = &cs4270_dai_ops,
 };
 EXPORT_SYMBOL_GPL(cs4270_dai);
 
-/*
- * ASoC probe function
+/**
+ * cs4270_probe - ASoC probe function
+ * @pdev: platform device
  *
- * This function is called when the machine driver calls
- * platform_device_add().
+ * This function is called when ASoC has all the pieces it needs to
+ * instantiate a sound driver.
  */
 static int cs4270_probe(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec;
-	int ret = 0;
+	struct snd_soc_codec *codec = cs4270_codec;
+	int ret;
 
-	printk(KERN_INFO "CS4270 ALSA SoC Codec\n");
-
-	/* Allocate enough space for the snd_soc_codec structure
-	   and our private data together. */
-	codec = kzalloc(ALIGN(sizeof(struct snd_soc_codec), 4) +
-			sizeof(struct cs4270_private), GFP_KERNEL);
-	if (!codec) {
-		printk(KERN_ERR "cs4270: Could not allocate codec structure\n");
-		return -ENOMEM;
-	}
-
-	mutex_init(&codec->mutex);
-	INIT_LIST_HEAD(&codec->dapm_widgets);
-	INIT_LIST_HEAD(&codec->dapm_paths);
-
-	codec->name = "CS4270";
-	codec->owner = THIS_MODULE;
-	codec->dai = &cs4270_dai;
-	codec->num_dai = 1;
-	codec->private_data = (void *) codec +
-		ALIGN(sizeof(struct snd_soc_codec), 4);
-
-	socdev->codec = codec;
+	/* Connect the codec to the socdev.  snd_soc_new_pcms() needs this. */
+	socdev->card->codec = codec;
 
 	/* Register PCMs */
-
 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
 	if (ret < 0) {
-		printk(KERN_ERR "cs4270: failed to create PCMs\n");
-		goto error_free_codec;
+		dev_err(codec->dev, "failed to create pcms\n");
+		return ret;
 	}
 
-#ifdef USE_I2C
-	cs4270_socdev = socdev;
-
-	ret = i2c_add_driver(&cs4270_i2c_driver);
-	if (ret) {
-		printk(KERN_ERR "cs4270: failed to attach driver");
+	/* Add the non-DAPM controls */
+	ret = snd_soc_add_controls(codec, cs4270_snd_controls,
+				ARRAY_SIZE(cs4270_snd_controls));
+	if (ret < 0) {
+		dev_err(codec->dev, "failed to add controls\n");
 		goto error_free_pcms;
 	}
 
-	/* Did we find a CS4270 on the I2C bus? */
-	if (codec->control_data) {
-		/* Initialize codec ops */
-		cs4270_dai.ops.hw_params = cs4270_hw_params;
-		cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk;
-		cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt;
-#ifdef CONFIG_SND_SOC_CS4270_HWMUTE
-		cs4270_dai.ops.digital_mute = cs4270_mute;
-#endif
-	} else
-		printk(KERN_INFO "cs4270: no I2C device found, "
-			"using stand-alone mode\n");
-#else
-	printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n");
-#endif
-
+	/* And finally, register the socdev */
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
-		printk(KERN_ERR "cs4270: failed to register card\n");
-		goto error_del_driver;
+		dev_err(codec->dev, "failed to register card\n");
+		goto error_free_pcms;
 	}
 
 	return 0;
 
-error_del_driver:
-#ifdef USE_I2C
-	i2c_del_driver(&cs4270_i2c_driver);
-
 error_free_pcms:
-#endif
 	snd_soc_free_pcms(socdev);
 
-error_free_codec:
-	kfree(socdev->codec);
-	socdev->codec = NULL;
-
 	return ret;
 }
 
+/**
+ * cs4270_remove - ASoC remove function
+ * @pdev: platform device
+ *
+ * This function is the counterpart to cs4270_probe().
+ */
 static int cs4270_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 
 	snd_soc_free_pcms(socdev);
 
-#ifdef USE_I2C
-	i2c_del_driver(&cs4270_i2c_driver);
-#endif
+	return 0;
+};
 
-	kfree(socdev->codec);
-	socdev->codec = NULL;
+/**
+ * cs4270_i2c_probe - initialize the I2C interface of the CS4270
+ * @i2c_client: the I2C client object
+ * @id: the I2C device ID (ignored)
+ *
+ * This function is called whenever the I2C subsystem finds a device that
+ * matches the device ID given via a prior call to i2c_add_driver().
+ */
+static int cs4270_i2c_probe(struct i2c_client *i2c_client,
+	const struct i2c_device_id *id)
+{
+	struct snd_soc_codec *codec;
+	struct cs4270_private *cs4270;
+	unsigned int reg;
+	int ret;
+
+	/* For now, we only support one cs4270 device in the system.  See the
+	 * comment for cs4270_codec.
+	 */
+	if (cs4270_codec) {
+		dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n",
+		       i2c_client->addr);
+		dev_err(&i2c_client->dev, "only one per board allowed\n");
+		/* Should we return something other than ENODEV here? */
+		return -ENODEV;
+	}
+
+	/* Verify that we have a CS4270 */
+
+	ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
+	if (ret < 0) {
+		dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n",
+		       i2c_client->addr);
+		return ret;
+	}
+	/* The top four bits of the chip ID should be 1100. */
+	if ((ret & 0xF0) != 0xC0) {
+		dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n",
+		       i2c_client->addr);
+		return -ENODEV;
+	}
+
+	dev_info(&i2c_client->dev, "found device at i2c address %X\n",
+		i2c_client->addr);
+	dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF);
+
+	/* Allocate enough space for the snd_soc_codec structure
+	   and our private data together. */
+	cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
+	if (!cs4270) {
+		dev_err(&i2c_client->dev, "could not allocate codec\n");
+		return -ENOMEM;
+	}
+	codec = &cs4270->codec;
+
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	codec->dev = &i2c_client->dev;
+	codec->name = "CS4270";
+	codec->owner = THIS_MODULE;
+	codec->dai = &cs4270_dai;
+	codec->num_dai = 1;
+	codec->private_data = cs4270;
+	codec->control_data = i2c_client;
+	codec->read = cs4270_read_reg_cache;
+	codec->write = cs4270_i2c_write;
+	codec->reg_cache = cs4270->reg_cache;
+	codec->reg_cache_size = CS4270_NUMREGS;
+
+	/* The I2C interface is set up, so pre-fill our register cache */
+
+	ret = cs4270_fill_cache(codec);
+	if (ret < 0) {
+		dev_err(&i2c_client->dev, "failed to fill register cache\n");
+		goto error_free_codec;
+	}
+
+	/* Disable auto-mute.  This feature appears to be buggy.  In some
+	 * situations, auto-mute will not deactivate when it should, so we want
+	 * this feature disabled by default.  An application (e.g. alsactl) can
+	 * re-enabled it by using the controls.
+	 */
+
+	reg = cs4270_read_reg_cache(codec, CS4270_MUTE);
+	reg &= ~CS4270_MUTE_AUTO;
+	ret = cs4270_i2c_write(codec, CS4270_MUTE, reg);
+	if (ret < 0) {
+		dev_err(&i2c_client->dev, "i2c write failed\n");
+		return ret;
+	}
+
+	/* Disable automatic volume control.  The hardware enables, and it
+	 * causes volume change commands to be delayed, sometimes until after
+	 * playback has started.  An application (e.g. alsactl) can
+	 * re-enabled it by using the controls.
+	 */
+
+	reg = cs4270_read_reg_cache(codec, CS4270_TRANS);
+	reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
+	ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
+	if (ret < 0) {
+		dev_err(&i2c_client->dev, "i2c write failed\n");
+		return ret;
+	}
+
+	/* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI
+	 * structure for each CS4270 device, but the machine driver needs to
+	 * have a pointer to the DAI structure, so for now it must be a global
+	 * variable.
+	 */
+	cs4270_dai.dev = &i2c_client->dev;
+
+	/* Register the DAI.  If all the other ASoC driver have already
+	 * registered, then this will call our probe function, so
+	 * cs4270_codec needs to be ready.
+	 */
+	cs4270_codec = codec;
+	ret = snd_soc_register_dai(&cs4270_dai);
+	if (ret < 0) {
+		dev_err(&i2c_client->dev, "failed to register DAIe\n");
+		goto error_free_codec;
+	}
+
+	i2c_set_clientdata(i2c_client, cs4270);
+
+	return 0;
+
+error_free_codec:
+	kfree(cs4270);
+	cs4270_codec = NULL;
+	cs4270_dai.dev = NULL;
+
+	return ret;
+}
+
+/**
+ * cs4270_i2c_remove - remove an I2C device
+ * @i2c_client: the I2C client object
+ *
+ * This function is the counterpart to cs4270_i2c_probe().
+ */
+static int cs4270_i2c_remove(struct i2c_client *i2c_client)
+{
+	struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client);
+
+	kfree(cs4270);
+	cs4270_codec = NULL;
+	cs4270_dai.dev = NULL;
 
 	return 0;
 }
 
 /*
+ * cs4270_id - I2C device IDs supported by this driver
+ */
+static struct i2c_device_id cs4270_id[] = {
+	{"cs4270", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, cs4270_id);
+
+/*
+ * cs4270_i2c_driver - I2C device identification
+ *
+ * This structure tells the I2C subsystem how to identify and support a
+ * given I2C device type.
+ */
+static struct i2c_driver cs4270_i2c_driver = {
+	.driver = {
+		.name = "cs4270",
+		.owner = THIS_MODULE,
+	},
+	.id_table = cs4270_id,
+	.probe = cs4270_i2c_probe,
+	.remove = cs4270_i2c_remove,
+};
+
+/*
  * ASoC codec device structure
  *
  * Assign this variable to the codec_dev field of the machine driver's
@@ -776,13 +783,15 @@
 
 static int __init cs4270_init(void)
 {
-	return snd_soc_register_dai(&cs4270_dai);
+	pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n");
+
+	return i2c_add_driver(&cs4270_i2c_driver);
 }
 module_init(cs4270_init);
 
 static void __exit cs4270_exit(void)
 {
-	snd_soc_unregister_dai(&cs4270_dai);
+	i2c_del_driver(&cs4270_i2c_driver);
 }
 module_exit(cs4270_exit);
 
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index 9a3e67e..5cda9e6 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -67,11 +67,11 @@
 
 	printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
 
-	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-	if (!socdev->codec)
+	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (!socdev->card->codec)
 		return -ENOMEM;
 
-	codec = socdev->codec;
+	codec = socdev->card->codec;
 	mutex_init(&codec->mutex);
 
 	codec->name = "PCM3008";
@@ -139,7 +139,7 @@
 card_err:
 	snd_soc_free_pcms(socdev);
 pcm_err:
-	kfree(socdev->codec);
+	kfree(socdev->card->codec);
 
 	return ret;
 }
@@ -147,7 +147,7 @@
 static int pcm3008_soc_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct pcm3008_setup_data *setup = socdev->codec_data;
 
 	if (!codec)
@@ -155,7 +155,7 @@
 
 	pcm3008_gpio_free(setup);
 	snd_soc_free_pcms(socdev);
-	kfree(socdev->codec);
+	kfree(socdev->card->codec);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index cac3736..87f606c7 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -151,21 +151,6 @@
 SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]),
 };
 
-/* add non dapm controls */
-static int ssm2602_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(ssm2602_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&ssm2602_snd_controls[i], codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 /* Output Mixer */
 static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = {
 SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0),
@@ -291,7 +276,7 @@
 	u16 srate;
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct ssm2602_priv *ssm2602 = codec->private_data;
 	struct i2c_client *i2c = codec->control_data;
 	u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
@@ -336,7 +321,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct ssm2602_priv *ssm2602 = codec->private_data;
 	struct i2c_client *i2c = codec->control_data;
 	struct snd_pcm_runtime *master_runtime;
@@ -373,7 +358,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	/* set active */
 	ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
 
@@ -385,7 +370,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct ssm2602_priv *ssm2602 = codec->private_data;
 	/* deactivate */
 	if (!codec->active)
@@ -521,6 +506,16 @@
 #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 		SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
+static struct snd_soc_dai_ops ssm2602_dai_ops = {
+	.startup	= ssm2602_startup,
+	.prepare	= ssm2602_pcm_prepare,
+	.hw_params	= ssm2602_hw_params,
+	.shutdown	= ssm2602_shutdown,
+	.digital_mute	= ssm2602_mute,
+	.set_sysclk	= ssm2602_set_dai_sysclk,
+	.set_fmt	= ssm2602_set_dai_fmt,
+};
+
 struct snd_soc_dai ssm2602_dai = {
 	.name = "SSM2602",
 	.playback = {
@@ -535,22 +530,14 @@
 		.channels_max = 2,
 		.rates = SSM2602_RATES,
 		.formats = SSM2602_FORMATS,},
-	.ops = {
-		.startup = ssm2602_startup,
-		.prepare = ssm2602_pcm_prepare,
-		.hw_params = ssm2602_hw_params,
-		.shutdown = ssm2602_shutdown,
-		.digital_mute = ssm2602_mute,
-		.set_sysclk = ssm2602_set_dai_sysclk,
-		.set_fmt = ssm2602_set_dai_fmt,
-	}
+	.ops = &ssm2602_dai_ops,
 };
 EXPORT_SYMBOL_GPL(ssm2602_dai);
 
 static int ssm2602_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -559,7 +546,7 @@
 static int ssm2602_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u8 data[2];
 	u16 *cache = codec->reg_cache;
@@ -581,7 +568,7 @@
  */
 static int ssm2602_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int reg, ret = 0;
 
 	codec->name = "SSM2602";
@@ -622,7 +609,8 @@
 			APANA_ENABLE_MIC_BOOST);
 	ssm2602_write(codec, SSM2602_PWR, 0);
 
-	ssm2602_add_controls(codec);
+	snd_soc_add_controls(codec, ssm2602_snd_controls,
+				ARRAY_SIZE(ssm2602_snd_controls));
 	ssm2602_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -653,7 +641,7 @@
 			     const struct i2c_device_id *id)
 {
 	struct snd_soc_device *socdev = ssm2602_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	i2c_set_clientdata(i2c, codec);
@@ -747,7 +735,7 @@
 	}
 
 	codec->private_data = ssm2602;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -768,7 +756,7 @@
 static int ssm2602_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec->control_data)
 		ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index cfdea00..c3f4afb 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -183,24 +183,6 @@
 	SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
 };
 
-/* add non dapm controls */
-static int tlv320aic23_add_controls(struct snd_soc_codec *codec)
-{
-
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&tlv320aic23_snd_controls[i],
-					       codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-
-}
-
 /* PGA Mixer controls for Line and Mic switch */
 static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = {
 	SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0),
@@ -423,7 +405,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 iface_reg;
 	int ret;
 	struct aic23 *aic23 = container_of(codec, struct aic23, codec);
@@ -471,7 +453,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	/* set active */
 	tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
@@ -484,7 +466,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct aic23 *aic23 = container_of(codec, struct aic23, codec);
 
 	/* deactivate */
@@ -598,6 +580,15 @@
 #define AIC23_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
+static struct snd_soc_dai_ops tlv320aic23_dai_ops = {
+	.prepare	= tlv320aic23_pcm_prepare,
+	.hw_params	= tlv320aic23_hw_params,
+	.shutdown	= tlv320aic23_shutdown,
+	.digital_mute	= tlv320aic23_mute,
+	.set_fmt	= tlv320aic23_set_dai_fmt,
+	.set_sysclk	= tlv320aic23_set_dai_sysclk,
+};
+
 struct snd_soc_dai tlv320aic23_dai = {
 	.name = "tlv320aic23",
 	.playback = {
@@ -612,14 +603,7 @@
 		    .channels_max = 2,
 		    .rates = AIC23_RATES,
 		    .formats = AIC23_FORMATS,},
-	.ops = {
-		.prepare = tlv320aic23_pcm_prepare,
-		.hw_params = tlv320aic23_hw_params,
-		.shutdown = tlv320aic23_shutdown,
-		.digital_mute = tlv320aic23_mute,
-		.set_fmt = tlv320aic23_set_dai_fmt,
-		.set_sysclk = tlv320aic23_set_dai_sysclk,
-	}
+	.ops = &tlv320aic23_dai_ops,
 };
 EXPORT_SYMBOL_GPL(tlv320aic23_dai);
 
@@ -627,7 +611,7 @@
 			       pm_message_t state)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
 	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -638,7 +622,7 @@
 static int tlv320aic23_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u16 reg;
 
@@ -660,7 +644,7 @@
  */
 static int tlv320aic23_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret = 0;
 	u16 reg;
 
@@ -718,7 +702,8 @@
 
 	tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
 
-	tlv320aic23_add_controls(codec);
+	snd_soc_add_controls(codec, tlv320aic23_snd_controls,
+				ARRAY_SIZE(tlv320aic23_snd_controls));
 	tlv320aic23_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -746,7 +731,7 @@
 				   const struct i2c_device_id *i2c_id)
 {
 	struct snd_soc_device *socdev = tlv320aic23_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -804,7 +789,7 @@
 	if (aic23 == NULL)
 		return -ENOMEM;
 	codec = &aic23->codec;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -823,7 +808,7 @@
 static int tlv320aic23_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct aic23 *aic23 = container_of(codec, struct aic23, codec);
 
 	if (codec->control_data)
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 29f2f1a..3387d9e 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -130,7 +130,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct aic26 *aic26 = codec->private_data;
 	int fsref, divisor, wlen, pval, jval, dval, qval;
 	u16 reg;
@@ -270,6 +270,13 @@
 #define AIC26_FORMATS	(SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_BE |\
 			 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE)
 
+static struct snd_soc_dai_ops aic26_dai_ops = {
+	.hw_params	= aic26_hw_params,
+	.digital_mute	= aic26_mute,
+	.set_sysclk	= aic26_set_sysclk,
+	.set_fmt	= aic26_set_fmt,
+};
+
 struct snd_soc_dai aic26_dai = {
 	.name = "tlv320aic26",
 	.playback = {
@@ -286,12 +293,7 @@
 		.rates = AIC26_RATES,
 		.formats = AIC26_FORMATS,
 	},
-	.ops = {
-		.hw_params = aic26_hw_params,
-		.digital_mute = aic26_mute,
-		.set_sysclk = aic26_set_sysclk,
-		.set_fmt = aic26_set_fmt,
-	},
+	.ops = &aic26_dai_ops,
 };
 EXPORT_SYMBOL_GPL(aic26_dai);
 
@@ -322,9 +324,8 @@
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 	struct snd_soc_codec *codec;
-	struct snd_kcontrol *kcontrol;
 	struct aic26 *aic26;
-	int i, ret, err;
+	int ret, err;
 
 	dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n");
 	dev_dbg(&pdev->dev, "socdev=%p\n", socdev);
@@ -338,7 +339,7 @@
 		return -ENODEV;
 	}
 	codec = &aic26->codec;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 
 	dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n",
 		&pdev->dev, socdev->dev);
@@ -351,11 +352,9 @@
 
 	/* register controls */
 	dev_dbg(&pdev->dev, "Registering controls\n");
-	for (i = 0; i < ARRAY_SIZE(aic26_snd_controls); i++) {
-		kcontrol = snd_soc_cnew(&aic26_snd_controls[i], codec, NULL);
-		err = snd_ctl_add(codec->card, kcontrol);
-		WARN_ON(err < 0);
-	}
+	err = snd_soc_add_controls(codec, aic26_snd_controls,
+			ARRAY_SIZE(aic26_snd_controls));
+	WARN_ON(err < 0);
 
 	/* CODEC is setup, we can register the card now */
 	dev_dbg(&pdev->dev, "Registering card\n");
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index aea0cb7..ab099f4 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -45,6 +45,7 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
+#include <sound/tlv.h>
 
 #include "tlv320aic3x.h"
 
@@ -250,56 +251,86 @@
 	SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf),
 };
 
+/*
+ * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(dac_tlv, -6350, 50, 0);
+/* ADC PGA gain volumes. From 0 to 59.5 dB in 0.5 dB steps */
+static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 50, 0);
+/*
+ * Output stage volumes. From -78.3 to 0 dB. Muted below -78.3 dB.
+ * Step size is approximately 0.5 dB over most of the scale but increasing
+ * near the very low levels.
+ * Define dB scale so that it is mostly correct for range about -55 to 0 dB
+ * but having increasing dB difference below that (and where it doesn't count
+ * so much). This setting shows -50 dB (actual is -50.3 dB) for register
+ * value 100 and -58.5 dB (actual is -78.3 dB) for register value 117.
+ */
+static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1);
+
 static const struct snd_kcontrol_new aic3x_snd_controls[] = {
 	/* Output */
-	SOC_DOUBLE_R("PCM Playback Volume", LDAC_VOL, RDAC_VOL, 0, 0x7f, 1),
+	SOC_DOUBLE_R_TLV("PCM Playback Volume",
+			 LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv),
 
-	SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL,
-		     DACR1_2_RLOPM_VOL, 0, 0x7f, 1),
+	SOC_DOUBLE_R_TLV("Line DAC Playback Volume",
+			 DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL,
+			 0, 118, 1, output_stage_tlv),
 	SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0),
 	SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0),
-	SOC_DOUBLE_R("LineL DAC Playback Volume", DACL1_2_LLOPM_VOL,
-		     DACR1_2_LLOPM_VOL, 0, 0x7f, 1),
-	SOC_SINGLE("LineL Left PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL,
-		     0, 0x7f, 1),
-	SOC_SINGLE("LineR Right PGA Bypass Playback Volume", PGAR_2_RLOPM_VOL,
-		     0, 0x7f, 1),
-	SOC_DOUBLE_R("LineL Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL,
-		     LINE2R_2_LLOPM_VOL, 0, 0x7f, 1),
-	SOC_DOUBLE_R("LineR Line2 Bypass Playback Volume", LINE2L_2_RLOPM_VOL,
-		     LINE2R_2_RLOPM_VOL, 0, 0x7f, 1),
+	SOC_DOUBLE_R_TLV("LineL DAC Playback Volume",
+			 DACL1_2_LLOPM_VOL, DACR1_2_LLOPM_VOL,
+			 0, 118, 1, output_stage_tlv),
+	SOC_SINGLE_TLV("LineL Left PGA Bypass Playback Volume",
+		       PGAL_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
+	SOC_SINGLE_TLV("LineR Right PGA Bypass Playback Volume",
+		       PGAR_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
+	SOC_DOUBLE_R_TLV("LineL Line2 Bypass Playback Volume",
+			 LINE2L_2_LLOPM_VOL, LINE2R_2_LLOPM_VOL,
+			 0, 118, 1, output_stage_tlv),
+	SOC_DOUBLE_R_TLV("LineR Line2 Bypass Playback Volume",
+			 LINE2L_2_RLOPM_VOL, LINE2R_2_RLOPM_VOL,
+			 0, 118, 1, output_stage_tlv),
 
-	SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL,
-		     DACR1_2_MONOLOPM_VOL, 0, 0x7f, 1),
+	SOC_DOUBLE_R_TLV("Mono DAC Playback Volume",
+			 DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL,
+			 0, 118, 1, output_stage_tlv),
 	SOC_SINGLE("Mono DAC Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
-	SOC_DOUBLE_R("Mono PGA Bypass Playback Volume", PGAL_2_MONOLOPM_VOL,
-		     PGAR_2_MONOLOPM_VOL, 0, 0x7f, 1),
-	SOC_DOUBLE_R("Mono Line2 Bypass Playback Volume", LINE2L_2_MONOLOPM_VOL,
-		     LINE2R_2_MONOLOPM_VOL, 0, 0x7f, 1),
+	SOC_DOUBLE_R_TLV("Mono PGA Bypass Playback Volume",
+			 PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
+			 0, 118, 1, output_stage_tlv),
+	SOC_DOUBLE_R_TLV("Mono Line2 Bypass Playback Volume",
+			 LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
+			 0, 118, 1, output_stage_tlv),
 
-	SOC_DOUBLE_R("HP DAC Playback Volume", DACL1_2_HPLOUT_VOL,
-		     DACR1_2_HPROUT_VOL, 0, 0x7f, 1),
+	SOC_DOUBLE_R_TLV("HP DAC Playback Volume",
+			 DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL,
+			 0, 118, 1, output_stage_tlv),
 	SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
 		     0x01, 0),
-	SOC_DOUBLE_R("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL,
-		     PGAR_2_HPROUT_VOL, 0, 0x7f, 1),
-	SOC_SINGLE("HPL PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL,
-		     0, 0x7f, 1),
-	SOC_SINGLE("HPR PGA Bypass Playback Volume", PGAL_2_HPROUT_VOL,
-		     0, 0x7f, 1),
-	SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL,
-		     LINE2R_2_HPROUT_VOL, 0, 0x7f, 1),
+	SOC_DOUBLE_R_TLV("HP Right PGA Bypass Playback Volume",
+			 PGAR_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL,
+			 0, 118, 1, output_stage_tlv),
+	SOC_SINGLE_TLV("HPL PGA Bypass Playback Volume",
+		       PGAL_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
+	SOC_SINGLE_TLV("HPR PGA Bypass Playback Volume",
+		       PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
+	SOC_DOUBLE_R_TLV("HP Line2 Bypass Playback Volume",
+			 LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
+			 0, 118, 1, output_stage_tlv),
 
-	SOC_DOUBLE_R("HPCOM DAC Playback Volume", DACL1_2_HPLCOM_VOL,
-		     DACR1_2_HPRCOM_VOL, 0, 0x7f, 1),
+	SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume",
+			 DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL,
+			 0, 118, 1, output_stage_tlv),
 	SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
 		     0x01, 0),
-	SOC_SINGLE("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL,
-		     0, 0x7f, 1),
-	SOC_SINGLE("HPRCOM PGA Bypass Playback Volume", PGAL_2_HPRCOM_VOL,
-		     0, 0x7f, 1),
-	SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL,
-		     LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1),
+	SOC_SINGLE_TLV("HPLCOM PGA Bypass Playback Volume",
+		       PGAL_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
+	SOC_SINGLE_TLV("HPRCOM PGA Bypass Playback Volume",
+		       PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
+	SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Playback Volume",
+			 LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL,
+			 0, 118, 1, output_stage_tlv),
 
 	/*
 	 * Note: enable Automatic input Gain Controller with care. It can
@@ -308,28 +339,13 @@
 	SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0),
 
 	/* Input */
-	SOC_DOUBLE_R("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 0x7f, 0),
+	SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL,
+			 0, 119, 0, adc_tlv),
 	SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1),
 
 	SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
 };
 
-/* add non dapm controls */
-static int aic3x_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(aic3x_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&aic3x_snd_controls[i],
-					       codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 /* Left DAC Mux */
 static const struct snd_kcontrol_new aic3x_left_dac_mux_controls =
 SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]);
@@ -746,7 +762,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct aic3x_priv *aic3x = codec->private_data;
 	int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
 	u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
@@ -1072,6 +1088,13 @@
 #define AIC3X_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
+static struct snd_soc_dai_ops aic3x_dai_ops = {
+	.hw_params	= aic3x_hw_params,
+	.digital_mute	= aic3x_mute,
+	.set_sysclk	= aic3x_set_dai_sysclk,
+	.set_fmt	= aic3x_set_dai_fmt,
+};
+
 struct snd_soc_dai aic3x_dai = {
 	.name = "tlv320aic3x",
 	.playback = {
@@ -1086,19 +1109,14 @@
 		.channels_max = 2,
 		.rates = AIC3X_RATES,
 		.formats = AIC3X_FORMATS,},
-	.ops = {
-		.hw_params = aic3x_hw_params,
-		.digital_mute = aic3x_mute,
-		.set_sysclk = aic3x_set_dai_sysclk,
-		.set_fmt = aic3x_set_dai_fmt,
-	}
+	.ops = &aic3x_dai_ops,
 };
 EXPORT_SYMBOL_GPL(aic3x_dai);
 
 static int aic3x_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1108,7 +1126,7 @@
 static int aic3x_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u8 data[2];
 	u8 *cache = codec->reg_cache;
@@ -1131,7 +1149,7 @@
  */
 static int aic3x_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct aic3x_setup_data *setup = socdev->codec_data;
 	int reg, ret = 0;
 
@@ -1227,7 +1245,8 @@
 	aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4);
 	aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4);
 
-	aic3x_add_controls(codec);
+	snd_soc_add_controls(codec, aic3x_snd_controls,
+				ARRAY_SIZE(aic3x_snd_controls));
 	aic3x_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -1261,7 +1280,7 @@
 			   const struct i2c_device_id *id)
 {
 	struct snd_soc_device *socdev = aic3x_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	i2c_set_clientdata(i2c, codec);
@@ -1366,7 +1385,7 @@
 	}
 
 	codec->private_data = aic3x;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -1392,7 +1411,7 @@
 static int aic3x_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	/* power down chip */
 	if (codec->control_data)
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index ea370a4..97738e2 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -42,7 +42,7 @@
  */
 static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
 	0x00, /* this register not used		*/
-	0x93, /* REG_CODEC_MODE		(0x1)	*/
+	0x91, /* REG_CODEC_MODE		(0x1)	*/
 	0xc3, /* REG_OPTION		(0x2)	*/
 	0x00, /* REG_UNKNOWN		(0x3)	*/
 	0x00, /* REG_MICBIAS_CTL	(0x4)	*/
@@ -117,6 +117,13 @@
 	0x00, /* REG_MISC_SET_2		(0x49)	*/
 };
 
+/* codec private data */
+struct twl4030_priv {
+	unsigned int bypass_state;
+	unsigned int codec_powered;
+	unsigned int codec_muted;
+};
+
 /*
  * read twl4030 register cache
  */
@@ -125,6 +132,9 @@
 {
 	u8 *cache = codec->reg_cache;
 
+	if (reg >= TWL4030_CACHEREGNUM)
+		return -EIO;
+
 	return cache[reg];
 }
 
@@ -151,26 +161,22 @@
 	return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
 }
 
-static void twl4030_clear_codecpdz(struct snd_soc_codec *codec)
+static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
 {
+	struct twl4030_priv *twl4030 = codec->private_data;
 	u8 mode;
 
-	mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
-	twl4030_write(codec, TWL4030_REG_CODEC_MODE,
-		mode & ~TWL4030_CODECPDZ);
-
-	/* REVISIT: this delay is present in TI sample drivers */
-	/* but there seems to be no TRM requirement for it     */
-	udelay(10);
-}
-
-static void twl4030_set_codecpdz(struct snd_soc_codec *codec)
-{
-	u8 mode;
+	if (enable == twl4030->codec_powered)
+		return;
 
 	mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
-	twl4030_write(codec, TWL4030_REG_CODEC_MODE,
-		mode | TWL4030_CODECPDZ);
+	if (enable)
+		mode |= TWL4030_CODECPDZ;
+	else
+		mode &= ~TWL4030_CODECPDZ;
+
+	twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
+	twl4030->codec_powered = enable;
 
 	/* REVISIT: this delay is present in TI sample drivers */
 	/* but there seems to be no TRM requirement for it     */
@@ -182,7 +188,7 @@
 	int i;
 
 	/* clear CODECPDZ prior to setting register defaults */
-	twl4030_clear_codecpdz(codec);
+	twl4030_codec_enable(codec, 0);
 
 	/* set all audio section registers to reasonable defaults */
 	for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
@@ -190,6 +196,122 @@
 
 }
 
+static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute)
+{
+	struct twl4030_priv *twl4030 = codec->private_data;
+	u8 reg_val;
+
+	if (mute == twl4030->codec_muted)
+		return;
+
+	if (mute) {
+		/* Bypass the reg_cache and mute the volumes
+		 * Headset mute is done in it's own event handler
+		 * Things to mute:  Earpiece, PreDrivL/R, CarkitL/R
+		 */
+		reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL);
+		twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+					reg_val & (~TWL4030_EAR_GAIN),
+					TWL4030_REG_EAR_CTL);
+
+		reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL);
+		twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+					reg_val & (~TWL4030_PREDL_GAIN),
+					TWL4030_REG_PREDL_CTL);
+		reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL);
+		twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+					reg_val & (~TWL4030_PREDR_GAIN),
+					TWL4030_REG_PREDL_CTL);
+
+		reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL);
+		twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+					reg_val & (~TWL4030_PRECKL_GAIN),
+					TWL4030_REG_PRECKL_CTL);
+		reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL);
+		twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+					reg_val & (~TWL4030_PRECKL_GAIN),
+					TWL4030_REG_PRECKR_CTL);
+
+		/* Disable PLL */
+		reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
+		reg_val &= ~TWL4030_APLL_EN;
+		twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val);
+	} else {
+		/* Restore the volumes
+		 * Headset mute is done in it's own event handler
+		 * Things to restore:  Earpiece, PreDrivL/R, CarkitL/R
+		 */
+		twl4030_write(codec, TWL4030_REG_EAR_CTL,
+			twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL));
+
+		twl4030_write(codec, TWL4030_REG_PREDL_CTL,
+			twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL));
+		twl4030_write(codec, TWL4030_REG_PREDR_CTL,
+			twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL));
+
+		twl4030_write(codec, TWL4030_REG_PRECKL_CTL,
+			twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL));
+		twl4030_write(codec, TWL4030_REG_PRECKR_CTL,
+			twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL));
+
+		/* Enable PLL */
+		reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
+		reg_val |= TWL4030_APLL_EN;
+		twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val);
+	}
+
+	twl4030->codec_muted = mute;
+}
+
+static void twl4030_power_up(struct snd_soc_codec *codec)
+{
+	struct twl4030_priv *twl4030 = codec->private_data;
+	u8 anamicl, regmisc1, byte;
+	int i = 0;
+
+	if (twl4030->codec_powered)
+		return;
+
+	/* set CODECPDZ to turn on codec */
+	twl4030_codec_enable(codec, 1);
+
+	/* initiate offset cancellation */
+	anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
+	twl4030_write(codec, TWL4030_REG_ANAMICL,
+		anamicl | TWL4030_CNCL_OFFSET_START);
+
+	/* wait for offset cancellation to complete */
+	do {
+		/* this takes a little while, so don't slam i2c */
+		udelay(2000);
+		twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
+				    TWL4030_REG_ANAMICL);
+	} while ((i++ < 100) &&
+		 ((byte & TWL4030_CNCL_OFFSET_START) ==
+		  TWL4030_CNCL_OFFSET_START));
+
+	/* Make sure that the reg_cache has the same value as the HW */
+	twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte);
+
+	/* anti-pop when changing analog gain */
+	regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
+	twl4030_write(codec, TWL4030_REG_MISC_SET_1,
+		regmisc1 | TWL4030_SMOOTH_ANAVOL_EN);
+
+	/* toggle CODECPDZ as per TRM */
+	twl4030_codec_enable(codec, 0);
+	twl4030_codec_enable(codec, 1);
+}
+
+/*
+ * Unconditional power down
+ */
+static void twl4030_power_down(struct snd_soc_codec *codec)
+{
+	/* power down */
+	twl4030_codec_enable(codec, 0);
+}
+
 /* Earpiece */
 static const char *twl4030_earpiece_texts[] =
 		{"Off", "DACL1", "DACL2", "DACR1"};
@@ -366,6 +488,41 @@
 static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control =
 SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum);
 
+/* Analog bypass for AudioR1 */
+static const struct snd_kcontrol_new twl4030_dapm_abypassr1_control =
+	SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR1_APGA_CTL, 2, 1, 0);
+
+/* Analog bypass for AudioL1 */
+static const struct snd_kcontrol_new twl4030_dapm_abypassl1_control =
+	SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL1_APGA_CTL, 2, 1, 0);
+
+/* Analog bypass for AudioR2 */
+static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control =
+	SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR2_APGA_CTL, 2, 1, 0);
+
+/* Analog bypass for AudioL2 */
+static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control =
+	SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0);
+
+/* Digital bypass gain, 0 mutes the bypass */
+static const unsigned int twl4030_dapm_dbypass_tlv[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 3, TLV_DB_SCALE_ITEM(-2400, 0, 1),
+	4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0),
+};
+
+/* Digital bypass left (TX1L -> RX2L) */
+static const struct snd_kcontrol_new twl4030_dapm_dbypassl_control =
+	SOC_DAPM_SINGLE_TLV("Volume",
+			TWL4030_REG_ATX2ARXPGA, 3, 7, 0,
+			twl4030_dapm_dbypass_tlv);
+
+/* Digital bypass right (TX1R -> RX2R) */
+static const struct snd_kcontrol_new twl4030_dapm_dbypassr_control =
+	SOC_DAPM_SINGLE_TLV("Volume",
+			TWL4030_REG_ATX2ARXPGA, 0, 7, 0,
+			twl4030_dapm_dbypass_tlv);
+
 static int micpath_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -420,6 +577,79 @@
 	return 0;
 }
 
+static int headsetl_event(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	unsigned char hs_gain, hs_pop;
+
+	/* Save the current volume */
+	hs_gain = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_GAIN_SET);
+	hs_pop = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_POPN_SET);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/* Do the anti-pop/bias ramp enable according to the TRM */
+		hs_pop |= TWL4030_VMID_EN;
+		twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop);
+		/* Is this needed? Can we just use whatever gain here? */
+		twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET,
+				(hs_gain & (~0x0f)) | 0x0a);
+		hs_pop |= TWL4030_RAMP_EN;
+		twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop);
+
+		/* Restore the original volume */
+		twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, hs_gain);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Do the anti-pop/bias ramp disable according to the TRM */
+		hs_pop &= ~TWL4030_RAMP_EN;
+		twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop);
+		/* Bypass the reg_cache to mute the headset */
+		twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+					hs_gain & (~0x0f),
+					TWL4030_REG_HS_GAIN_SET);
+		hs_pop &= ~TWL4030_VMID_EN;
+		twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop);
+		break;
+	}
+	return 0;
+}
+
+static int bypass_event(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct soc_mixer_control *m =
+		(struct soc_mixer_control *)w->kcontrols->private_value;
+	struct twl4030_priv *twl4030 = w->codec->private_data;
+	unsigned char reg;
+
+	reg = twl4030_read_reg_cache(w->codec, m->reg);
+
+	if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
+		/* Analog bypass */
+		if (reg & (1 << m->shift))
+			twl4030->bypass_state |=
+				(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
+		else
+			twl4030->bypass_state &=
+				~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
+	} else {
+		/* Digital bypass */
+		if (reg & (0x7 << m->shift))
+			twl4030->bypass_state |= (1 << (m->shift ? 5 : 4));
+		else
+			twl4030->bypass_state &= ~(1 << (m->shift ? 5 : 4));
+	}
+
+	if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
+		if (twl4030->bypass_state)
+			twl4030_codec_mute(w->codec, 0);
+		else
+			twl4030_codec_mute(w->codec, 1);
+	}
+	return 0;
+}
+
 /*
  * Some of the gain controls in TWL (mostly those which are associated with
  * the outputs) are implemented in an interesting way:
@@ -614,6 +844,17 @@
  */
 static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
 
+static const char *twl4030_rampdelay_texts[] = {
+	"27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms",
+	"437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms",
+	"3495/2581/1748 ms"
+};
+
+static const struct soc_enum twl4030_rampdelay_enum =
+	SOC_ENUM_SINGLE(TWL4030_REG_HS_POPN_SET, 2,
+			ARRAY_SIZE(twl4030_rampdelay_texts),
+			twl4030_rampdelay_texts);
+
 static const struct snd_kcontrol_new twl4030_snd_controls[] = {
 	/* Common playback gain controls */
 	SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume",
@@ -668,24 +909,10 @@
 
 	SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN,
 		0, 3, 5, 0, input_gain_tlv),
+
+	SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum),
 };
 
-/* add non dapm controls */
-static int twl4030_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&twl4030_snd_controls[i],
-						codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
 	/* Left channel inputs */
 	SND_SOC_DAPM_INPUT("MAINMIC"),
@@ -714,13 +941,13 @@
 
 	/* DACs */
 	SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback",
-			TWL4030_REG_AVDAC_CTL, 0, 0),
+			SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback",
-			TWL4030_REG_AVDAC_CTL, 1, 0),
+			SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback",
-			TWL4030_REG_AVDAC_CTL, 2, 0),
+			SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback",
-			TWL4030_REG_AVDAC_CTL, 3, 0),
+			SND_SOC_NOPM, 0, 0),
 
 	/* Analog PGAs */
 	SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL,
@@ -732,6 +959,37 @@
 	SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL,
 			0, 0, NULL, 0),
 
+	/* Analog bypasses */
+	SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0,
+			&twl4030_dapm_abypassr1_control, bypass_event,
+			SND_SOC_DAPM_POST_REG),
+	SND_SOC_DAPM_SWITCH_E("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0,
+			&twl4030_dapm_abypassl1_control,
+			bypass_event, SND_SOC_DAPM_POST_REG),
+	SND_SOC_DAPM_SWITCH_E("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0,
+			&twl4030_dapm_abypassr2_control,
+			bypass_event, SND_SOC_DAPM_POST_REG),
+	SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0,
+			&twl4030_dapm_abypassl2_control,
+			bypass_event, SND_SOC_DAPM_POST_REG),
+
+	/* Digital bypasses */
+	SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0,
+			&twl4030_dapm_dbypassl_control, bypass_event,
+			SND_SOC_DAPM_POST_REG),
+	SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0,
+			&twl4030_dapm_dbypassr_control, bypass_event,
+			SND_SOC_DAPM_POST_REG),
+
+	SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL,
+			0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", TWL4030_REG_AVDAC_CTL,
+			1, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer", TWL4030_REG_AVDAC_CTL,
+			2, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer", TWL4030_REG_AVDAC_CTL,
+			3, 0, NULL, 0),
+
 	/* Output MUX controls */
 	/* Earpiece */
 	SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0,
@@ -742,8 +1000,9 @@
 	SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0,
 		&twl4030_dapm_predriver_control),
 	/* HeadsetL/R */
-	SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
-		&twl4030_dapm_hsol_control),
+	SND_SOC_DAPM_MUX_E("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
+		&twl4030_dapm_hsol_control, headsetl_event,
+		SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0,
 		&twl4030_dapm_hsor_control),
 	/* CarkitL/R */
@@ -782,16 +1041,16 @@
 		SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD|
 		SND_SOC_DAPM_POST_REG),
 
-	/* Analog input muxes with power switch for the physical ADCL/R */
+	/* Analog input muxes with switch for the capture amplifiers */
 	SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route",
-		TWL4030_REG_AVADC_CTL, 3, 0, &twl4030_dapm_analoglmic_control),
+		TWL4030_REG_ANAMICL, 4, 0, &twl4030_dapm_analoglmic_control),
 	SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route",
-		TWL4030_REG_AVADC_CTL, 1, 0, &twl4030_dapm_analogrmic_control),
+		TWL4030_REG_ANAMICR, 4, 0, &twl4030_dapm_analogrmic_control),
 
-	SND_SOC_DAPM_PGA("Analog Left Amplifier",
-		TWL4030_REG_ANAMICL, 4, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("Analog Right Amplifier",
-		TWL4030_REG_ANAMICR, 4, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("ADC Physical Left",
+		TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("ADC Physical Right",
+		TWL4030_REG_AVADC_CTL, 1, 0, NULL, 0),
 
 	SND_SOC_DAPM_PGA("Digimic0 Enable",
 		TWL4030_REG_ADCMICSEL, 1, 0, NULL, 0),
@@ -801,13 +1060,19 @@
 	SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0),
 	SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0),
 	SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0),
+
 };
 
 static const struct snd_soc_dapm_route intercon[] = {
-	{"ARXL1_APGA", NULL, "DAC Left1"},
-	{"ARXR1_APGA", NULL, "DAC Right1"},
-	{"ARXL2_APGA", NULL, "DAC Left2"},
-	{"ARXR2_APGA", NULL, "DAC Right2"},
+	{"Analog L1 Playback Mixer", NULL, "DAC Left1"},
+	{"Analog R1 Playback Mixer", NULL, "DAC Right1"},
+	{"Analog L2 Playback Mixer", NULL, "DAC Left2"},
+	{"Analog R2 Playback Mixer", NULL, "DAC Right2"},
+
+	{"ARXL1_APGA", NULL, "Analog L1 Playback Mixer"},
+	{"ARXR1_APGA", NULL, "Analog R1 Playback Mixer"},
+	{"ARXL2_APGA", NULL, "Analog L2 Playback Mixer"},
+	{"ARXR2_APGA", NULL, "Analog R2 Playback Mixer"},
 
 	/* Internal playback routings */
 	/* Earpiece */
@@ -865,23 +1130,23 @@
 	{"Analog Right Capture Route", "Sub mic", "SUBMIC"},
 	{"Analog Right Capture Route", "AUXR", "AUXR"},
 
-	{"Analog Left Amplifier", NULL, "Analog Left Capture Route"},
-	{"Analog Right Amplifier", NULL, "Analog Right Capture Route"},
+	{"ADC Physical Left", NULL, "Analog Left Capture Route"},
+	{"ADC Physical Right", NULL, "Analog Right Capture Route"},
 
 	{"Digimic0 Enable", NULL, "DIGIMIC0"},
 	{"Digimic1 Enable", NULL, "DIGIMIC1"},
 
 	/* TX1 Left capture path */
-	{"TX1 Capture Route", "Analog", "Analog Left Amplifier"},
+	{"TX1 Capture Route", "Analog", "ADC Physical Left"},
 	{"TX1 Capture Route", "Digimic0", "Digimic0 Enable"},
 	/* TX1 Right capture path */
-	{"TX1 Capture Route", "Analog", "Analog Right Amplifier"},
+	{"TX1 Capture Route", "Analog", "ADC Physical Right"},
 	{"TX1 Capture Route", "Digimic0", "Digimic0 Enable"},
 	/* TX2 Left capture path */
-	{"TX2 Capture Route", "Analog", "Analog Left Amplifier"},
+	{"TX2 Capture Route", "Analog", "ADC Physical Left"},
 	{"TX2 Capture Route", "Digimic1", "Digimic1 Enable"},
 	/* TX2 Right capture path */
-	{"TX2 Capture Route", "Analog", "Analog Right Amplifier"},
+	{"TX2 Capture Route", "Analog", "ADC Physical Right"},
 	{"TX2 Capture Route", "Digimic1", "Digimic1 Enable"},
 
 	{"ADC Virtual Left1", NULL, "TX1 Capture Route"},
@@ -889,6 +1154,24 @@
 	{"ADC Virtual Left2", NULL, "TX2 Capture Route"},
 	{"ADC Virtual Right2", NULL, "TX2 Capture Route"},
 
+	/* Analog bypass routes */
+	{"Right1 Analog Loopback", "Switch", "Analog Right Capture Route"},
+	{"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"},
+	{"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"},
+	{"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"},
+
+	{"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
+	{"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
+	{"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
+	{"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"},
+
+	/* Digital bypass routes */
+	{"Right Digital Loopback", "Volume", "TX1 Capture Route"},
+	{"Left Digital Loopback", "Volume", "TX1 Capture Route"},
+
+	{"Analog R2 Playback Mixer", NULL, "Right Digital Loopback"},
+	{"Analog L2 Playback Mixer", NULL, "Left Digital Loopback"},
+
 };
 
 static int twl4030_add_widgets(struct snd_soc_codec *codec)
@@ -902,82 +1185,28 @@
 	return 0;
 }
 
-static void twl4030_power_up(struct snd_soc_codec *codec)
-{
-	u8 anamicl, regmisc1, byte, popn;
-	int i = 0;
-
-	/* set CODECPDZ to turn on codec */
-	twl4030_set_codecpdz(codec);
-
-	/* initiate offset cancellation */
-	anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
-	twl4030_write(codec, TWL4030_REG_ANAMICL,
-		anamicl | TWL4030_CNCL_OFFSET_START);
-
-
-	/* wait for offset cancellation to complete */
-	do {
-		/* this takes a little while, so don't slam i2c */
-		udelay(2000);
-		twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
-				    TWL4030_REG_ANAMICL);
-	} while ((i++ < 100) &&
-		 ((byte & TWL4030_CNCL_OFFSET_START) ==
-		  TWL4030_CNCL_OFFSET_START));
-
-	/* anti-pop when changing analog gain */
-	regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
-	twl4030_write(codec, TWL4030_REG_MISC_SET_1,
-		regmisc1 | TWL4030_SMOOTH_ANAVOL_EN);
-
-	/* toggle CODECPDZ as per TRM */
-	twl4030_clear_codecpdz(codec);
-	twl4030_set_codecpdz(codec);
-
-	/* program anti-pop with bias ramp delay */
-	popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
-	popn &= TWL4030_RAMP_DELAY;
-	popn |=	TWL4030_RAMP_DELAY_645MS;
-	twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
-	popn |=	TWL4030_VMID_EN;
-	twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
-
-	/* enable anti-pop ramp */
-	popn |= TWL4030_RAMP_EN;
-	twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
-}
-
-static void twl4030_power_down(struct snd_soc_codec *codec)
-{
-	u8 popn;
-
-	/* disable anti-pop ramp */
-	popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
-	popn &= ~TWL4030_RAMP_EN;
-	twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
-
-	/* disable bias out */
-	popn &= ~TWL4030_VMID_EN;
-	twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
-
-	/* power down */
-	twl4030_clear_codecpdz(codec);
-}
-
 static int twl4030_set_bias_level(struct snd_soc_codec *codec,
 				  enum snd_soc_bias_level level)
 {
+	struct twl4030_priv *twl4030 = codec->private_data;
+
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		twl4030_power_up(codec);
+		twl4030_codec_mute(codec, 0);
 		break;
 	case SND_SOC_BIAS_PREPARE:
-		/* TODO: develop a twl4030_prepare function */
+		twl4030_power_up(codec);
+		if (twl4030->bypass_state)
+			twl4030_codec_mute(codec, 0);
+		else
+			twl4030_codec_mute(codec, 1);
 		break;
 	case SND_SOC_BIAS_STANDBY:
-		/* TODO: develop a twl4030_standby function */
-		twl4030_power_down(codec);
+		twl4030_power_up(codec);
+		if (twl4030->bypass_state)
+			twl4030_codec_mute(codec, 0);
+		else
+			twl4030_codec_mute(codec, 1);
 		break;
 	case SND_SOC_BIAS_OFF:
 		twl4030_power_down(codec);
@@ -994,10 +1223,9 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u8 mode, old_mode, format, old_format;
 
-
 	/* bit rate */
 	old_mode = twl4030_read_reg_cache(codec,
 			TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
@@ -1039,8 +1267,9 @@
 
 	if (mode != old_mode) {
 		/* change rate and set CODECPDZ */
+		twl4030_codec_enable(codec, 0);
 		twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
-		twl4030_set_codecpdz(codec);
+		twl4030_codec_enable(codec, 1);
 	}
 
 	/* sample size */
@@ -1063,13 +1292,13 @@
 	if (format != old_format) {
 
 		/* clear CODECPDZ before changing format (codec requirement) */
-		twl4030_clear_codecpdz(codec);
+		twl4030_codec_enable(codec, 0);
 
 		/* change format */
 		twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
 
 		/* set CODECPDZ afterwards */
-		twl4030_set_codecpdz(codec);
+		twl4030_codec_enable(codec, 1);
 	}
 	return 0;
 }
@@ -1139,13 +1368,13 @@
 	if (format != old_format) {
 
 		/* clear CODECPDZ before changing format (codec requirement) */
-		twl4030_clear_codecpdz(codec);
+		twl4030_codec_enable(codec, 0);
 
 		/* change format */
 		twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
 
 		/* set CODECPDZ afterwards */
-		twl4030_set_codecpdz(codec);
+		twl4030_codec_enable(codec, 1);
 	}
 
 	return 0;
@@ -1154,6 +1383,12 @@
 #define TWL4030_RATES	 (SNDRV_PCM_RATE_8000_48000)
 #define TWL4030_FORMATS	 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
 
+static struct snd_soc_dai_ops twl4030_dai_ops = {
+	.hw_params	= twl4030_hw_params,
+	.set_sysclk	= twl4030_set_dai_sysclk,
+	.set_fmt	= twl4030_set_dai_fmt,
+};
+
 struct snd_soc_dai twl4030_dai = {
 	.name = "twl4030",
 	.playback = {
@@ -1168,18 +1403,14 @@
 		.channels_max = 2,
 		.rates = TWL4030_RATES,
 		.formats = TWL4030_FORMATS,},
-	.ops = {
-		.hw_params = twl4030_hw_params,
-		.set_sysclk = twl4030_set_dai_sysclk,
-		.set_fmt = twl4030_set_dai_fmt,
-	}
+	.ops = &twl4030_dai_ops,
 };
 EXPORT_SYMBOL_GPL(twl4030_dai);
 
 static int twl4030_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1189,7 +1420,7 @@
 static int twl4030_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	twl4030_set_bias_level(codec, codec->suspend_bias_level);
@@ -1203,7 +1434,7 @@
 
 static int twl4030_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret = 0;
 
 	printk(KERN_INFO "TWL4030 Audio Codec init \n");
@@ -1233,7 +1464,8 @@
 	/* power on device */
 	twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	twl4030_add_controls(codec);
+	snd_soc_add_controls(codec, twl4030_snd_controls,
+				ARRAY_SIZE(twl4030_snd_controls));
 	twl4030_add_widgets(codec);
 
 	ret = snd_soc_init_card(socdev);
@@ -1258,12 +1490,20 @@
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 	struct snd_soc_codec *codec;
+	struct twl4030_priv *twl4030;
 
 	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
 	if (codec == NULL)
 		return -ENOMEM;
 
-	socdev->codec = codec;
+	twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
+	if (twl4030 == NULL) {
+		kfree(codec);
+		return -ENOMEM;
+	}
+
+	codec->private_data = twl4030;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -1277,11 +1517,13 @@
 static int twl4030_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	printk(KERN_INFO "TWL4030 Audio Codec remove\n");
+	twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	snd_soc_free_pcms(socdev);
 	snd_soc_dapm_free(socdev);
+	kfree(codec->private_data);
 	kfree(codec);
 
 	return 0;
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index 442e5a8..33dbb14 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -170,6 +170,9 @@
 #define TWL4030_CLK256FS_EN		0x02
 #define TWL4030_AIF_EN			0x01
 
+/* EAR_CTL (0x21) */
+#define TWL4030_EAR_GAIN		0x30
+
 /* HS_GAIN_SET (0x23) Fields */
 
 #define TWL4030_HSR_GAIN		0x0C
@@ -198,6 +201,18 @@
 #define TWL4030_RAMP_DELAY_2581MS	0x1C
 #define TWL4030_RAMP_EN			0x02
 
+/* PREDL_CTL (0x25) */
+#define TWL4030_PREDL_GAIN		0x30
+
+/* PREDR_CTL (0x26) */
+#define TWL4030_PREDR_GAIN		0x30
+
+/* PRECKL_CTL (0x27) */
+#define TWL4030_PRECKL_GAIN		0x30
+
+/* PRECKR_CTL (0x28) */
+#define TWL4030_PRECKR_GAIN		0x30
+
 /* HFL_CTL (0x29, 0x2A) Fields */
 #define TWL4030_HF_CTL_HB_EN		0x04
 #define TWL4030_HF_CTL_LOOP_EN		0x08
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index a2c5064..ddefb8f 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -173,7 +173,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct uda134x_priv *uda134x = codec->private_data;
 	struct snd_pcm_runtime *master_runtime;
 
@@ -206,7 +206,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct uda134x_priv *uda134x = codec->private_data;
 
 	if (uda134x->master_substream == substream)
@@ -221,7 +221,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct uda134x_priv *uda134x = codec->private_data;
 	u8 hw_params;
 
@@ -431,38 +431,14 @@
 SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
 };
 
-static int uda134x_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i, n;
-	const struct snd_kcontrol_new *ctrls;
-	struct uda134x_platform_data *pd = codec->control_data;
-
-	switch (pd->model) {
-	case UDA134X_UDA1340:
-	case UDA134X_UDA1344:
-		n = ARRAY_SIZE(uda1340_snd_controls);
-		ctrls = uda1340_snd_controls;
-		break;
-	case UDA134X_UDA1341:
-		n = ARRAY_SIZE(uda1341_snd_controls);
-		ctrls = uda1341_snd_controls;
-		break;
-	default:
-		printk(KERN_ERR "%s unkown codec type: %d",
-		       __func__, pd->model);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < n; i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&ctrls[i],
-					       codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
+static struct snd_soc_dai_ops uda134x_dai_ops = {
+	.startup	= uda134x_startup,
+	.shutdown	= uda134x_shutdown,
+	.hw_params	= uda134x_hw_params,
+	.digital_mute	= uda134x_mute,
+	.set_sysclk	= uda134x_set_dai_sysclk,
+	.set_fmt	= uda134x_set_dai_fmt,
+};
 
 struct snd_soc_dai uda134x_dai = {
 	.name = "UDA134X",
@@ -483,14 +459,7 @@
 		.formats = UDA134X_FORMATS,
 	},
 	/* pcm operations */
-	.ops = {
-		.startup = uda134x_startup,
-		.shutdown = uda134x_shutdown,
-		.hw_params = uda134x_hw_params,
-		.digital_mute = uda134x_mute,
-		.set_sysclk = uda134x_set_dai_sysclk,
-		.set_fmt = uda134x_set_dai_fmt,
-	}
+	.ops = &uda134x_dai_ops,
 };
 EXPORT_SYMBOL(uda134x_dai);
 
@@ -525,11 +494,11 @@
 		return -EINVAL;
 	}
 
-	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-	if (socdev->codec == NULL)
+	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (socdev->card->codec == NULL)
 		return ret;
 
-	codec = socdev->codec;
+	codec = socdev->card->codec;
 
 	uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
 	if (uda134x == NULL)
@@ -572,7 +541,22 @@
 		goto pcm_err;
 	}
 
-	ret = uda134x_add_controls(codec);
+	switch (pd->model) {
+	case UDA134X_UDA1340:
+	case UDA134X_UDA1344:
+		ret = snd_soc_add_controls(codec, uda1340_snd_controls,
+					ARRAY_SIZE(uda1340_snd_controls));
+	break;
+	case UDA134X_UDA1341:
+		ret = snd_soc_add_controls(codec, uda1341_snd_controls,
+					ARRAY_SIZE(uda1341_snd_controls));
+	break;
+	default:
+		printk(KERN_ERR "%s unkown codec type: %d",
+			__func__, pd->model);
+	return -EINVAL;
+	}
+
 	if (ret < 0) {
 		printk(KERN_ERR "UDA134X: failed to register controls\n");
 		goto pcm_err;
@@ -602,7 +586,7 @@
 static int uda134x_soc_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -622,7 +606,7 @@
 						pm_message_t state)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -632,7 +616,7 @@
 static int uda134x_soc_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
 	uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index e6bf084..5b21594 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -25,6 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/workqueue.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/initval.h>
@@ -35,7 +36,8 @@
 
 #include "uda1380.h"
 
-#define UDA1380_VERSION "0.6"
+static struct work_struct uda1380_work;
+static struct snd_soc_codec *uda1380_codec;
 
 /*
  * uda1380 register cache
@@ -52,6 +54,8 @@
 	0x0000, 0x8000, 0x0002, 0x0000,
 };
 
+static unsigned long uda1380_cache_dirty;
+
 /*
  * read uda1380 register cache
  */
@@ -73,8 +77,11 @@
 	u16 reg, unsigned int value)
 {
 	u16 *cache = codec->reg_cache;
+
 	if (reg >= UDA1380_CACHEREGNUM)
 		return;
+	if ((reg >= 0x10) && (cache[reg] != value))
+		set_bit(reg - 0x10, &uda1380_cache_dirty);
 	cache[reg] = value;
 }
 
@@ -113,6 +120,8 @@
 					(data[0]<<8) | data[1]);
 			return -EIO;
 		}
+		if (reg >= 0x10)
+			clear_bit(reg - 0x10, &uda1380_cache_dirty);
 		return 0;
 	} else
 		return -EIO;
@@ -120,6 +129,20 @@
 
 #define uda1380_reset(c)	uda1380_write(c, UDA1380_RESET, 0)
 
+static void uda1380_flush_work(struct work_struct *work)
+{
+	int bit, reg;
+
+	for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
+		reg = 0x10 + bit;
+		pr_debug("uda1380: flush reg %x val %x:\n", reg,
+				uda1380_read_reg_cache(uda1380_codec, reg));
+		uda1380_write(uda1380_codec, reg,
+				uda1380_read_reg_cache(uda1380_codec, reg));
+		clear_bit(bit, &uda1380_cache_dirty);
+	}
+}
+
 /* declarations of ALSA reg_elem_REAL controls */
 static const char *uda1380_deemp[] = {
 	"None",
@@ -254,7 +277,6 @@
 	SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0),	/* DA_POL_INV */
 	SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum),				/* SEL_NS */
 	SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum),		/* MIX_POS, MIX */
-	SOC_SINGLE("Silence Switch", UDA1380_MIXER, 7, 1, 0),			/* SILENCE, force DAC output to silence */
 	SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0),		/* SDET_ON */
 	SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum),		/* SD_VALUE */
 	SOC_ENUM("Oversampling Input", uda1380_os_enum),			/* OS */
@@ -271,21 +293,6 @@
 	SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0),
 };
 
-/* add non dapm controls */
-static int uda1380_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(uda1380_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&uda1380_snd_controls[i], codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 /* Input mux */
 static const struct snd_kcontrol_new uda1380_input_mux_control =
 	SOC_DAPM_ENUM("Route", uda1380_input_sel_enum);
@@ -371,7 +378,7 @@
 	return 0;
 }
 
-static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int uda1380_set_dai_fmt_both(struct snd_soc_dai *codec_dai,
 		unsigned int fmt)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
@@ -381,16 +388,75 @@
 	iface = uda1380_read_reg_cache(codec, UDA1380_IFACE);
 	iface &= ~(R01_SFORI_MASK | R01_SIM | R01_SFORO_MASK);
 
-	/* FIXME: how to select I2S for DATAO and MSB for DATAI correctly? */
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
 		iface |= R01_SFORI_I2S | R01_SFORO_I2S;
 		break;
 	case SND_SOC_DAIFMT_LSB:
-		iface |= R01_SFORI_LSB16 | R01_SFORO_I2S;
+		iface |= R01_SFORI_LSB16 | R01_SFORO_LSB16;
 		break;
 	case SND_SOC_DAIFMT_MSB:
-		iface |= R01_SFORI_MSB | R01_SFORO_I2S;
+		iface |= R01_SFORI_MSB | R01_SFORO_MSB;
+	}
+
+	/* DATAI is slave only, so in single-link mode, this has to be slave */
+	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+		return -EINVAL;
+
+	uda1380_write(codec, UDA1380_IFACE, iface);
+
+	return 0;
+}
+
+static int uda1380_set_dai_fmt_playback(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	int iface;
+
+	/* set up DAI based upon fmt */
+	iface = uda1380_read_reg_cache(codec, UDA1380_IFACE);
+	iface &= ~R01_SFORI_MASK;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		iface |= R01_SFORI_I2S;
+		break;
+	case SND_SOC_DAIFMT_LSB:
+		iface |= R01_SFORI_LSB16;
+		break;
+	case SND_SOC_DAIFMT_MSB:
+		iface |= R01_SFORI_MSB;
+	}
+
+	/* DATAI is slave only, so this has to be slave */
+	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+		return -EINVAL;
+
+	uda1380_write(codec, UDA1380_IFACE, iface);
+
+	return 0;
+}
+
+static int uda1380_set_dai_fmt_capture(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	int iface;
+
+	/* set up DAI based upon fmt */
+	iface = uda1380_read_reg_cache(codec, UDA1380_IFACE);
+	iface &= ~(R01_SIM | R01_SFORO_MASK);
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		iface |= R01_SFORO_I2S;
+		break;
+	case SND_SOC_DAIFMT_LSB:
+		iface |= R01_SFORO_LSB16;
+		break;
+	case SND_SOC_DAIFMT_MSB:
+		iface |= R01_SFORO_MSB;
 	}
 
 	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM)
@@ -401,41 +467,28 @@
 	return 0;
 }
 
-/*
- * Flush reg cache
- * We can only write the interpolator and decimator registers
- * when the DAI is being clocked by the CPU DAI. It's up to the
- * machine and cpu DAI driver to do this before we are called.
- */
-static int uda1380_pcm_prepare(struct snd_pcm_substream *substream,
-			       struct snd_soc_dai *dai)
+static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
+		struct snd_soc_dai *dai)
 {
 	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, reg_start, reg_end, clk;
+	struct snd_soc_codec *codec = socdev->card->codec;
+	int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		reg_start = UDA1380_MVOL;
-		reg_end = UDA1380_MIXER;
-	} else {
-		reg_start = UDA1380_DEC;
-		reg_end = UDA1380_AGC;
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		uda1380_write_reg_cache(codec, UDA1380_MIXER,
+					mixer & ~R14_SILENCE);
+		schedule_work(&uda1380_work);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		uda1380_write_reg_cache(codec, UDA1380_MIXER,
+					mixer | R14_SILENCE);
+		schedule_work(&uda1380_work);
+		break;
 	}
-
-	/* FIXME disable DAC_CLK */
-	clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
-	uda1380_write(codec, UDA1380_CLK, clk & ~R00_DAC_CLK);
-
-	for (reg = reg_start; reg <= reg_end; reg++) {
-		pr_debug("uda1380: flush reg %x val %x:", reg,
-				uda1380_read_reg_cache(codec, reg));
-		uda1380_write(codec, reg, uda1380_read_reg_cache(codec, reg));
-	}
-
-	/* FIXME enable DAC_CLK */
-	uda1380_write(codec, UDA1380_CLK, clk | R00_DAC_CLK);
-
 	return 0;
 }
 
@@ -445,7 +498,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
 
 	/* set WSPLL power and divider if running from this clock */
@@ -484,7 +537,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
 
 	/* shut down WSPLL power if running from this clock */
@@ -501,24 +554,6 @@
 	uda1380_write(codec, UDA1380_CLK, clk);
 }
 
-static int uda1380_mute(struct snd_soc_dai *codec_dai, int mute)
-{
-	struct snd_soc_codec *codec = codec_dai->codec;
-	u16 mute_reg = uda1380_read_reg_cache(codec, UDA1380_DEEMP) & ~R13_MTM;
-
-	/* FIXME: mute(codec,0) is called when the magician clock is already
-	 * set to WSPLL, but for some unknown reason writing to interpolator
-	 * registers works only when clocked by SYSCLK */
-	u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
-	uda1380_write(codec, UDA1380_CLK, ~R00_DAC_CLK & clk);
-	if (mute)
-		uda1380_write(codec, UDA1380_DEEMP, mute_reg | R13_MTM);
-	else
-		uda1380_write(codec, UDA1380_DEEMP, mute_reg);
-	uda1380_write(codec, UDA1380_CLK, clk);
-	return 0;
-}
-
 static int uda1380_set_bias_level(struct snd_soc_codec *codec,
 	enum snd_soc_bias_level level)
 {
@@ -544,6 +579,27 @@
 		       SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
 		       SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
 
+static struct snd_soc_dai_ops uda1380_dai_ops = {
+	.hw_params	= uda1380_pcm_hw_params,
+	.shutdown	= uda1380_pcm_shutdown,
+	.trigger	= uda1380_trigger,
+	.set_fmt	= uda1380_set_dai_fmt_both,
+};
+
+static struct snd_soc_dai_ops uda1380_dai_ops_playback = {
+	.hw_params	= uda1380_pcm_hw_params,
+	.shutdown	= uda1380_pcm_shutdown,
+	.trigger	= uda1380_trigger,
+	.set_fmt	= uda1380_set_dai_fmt_playback,
+};
+
+static struct snd_soc_dai_ops uda1380_dai_ops_capture = {
+	.hw_params	= uda1380_pcm_hw_params,
+	.shutdown	= uda1380_pcm_shutdown,
+	.trigger	= uda1380_trigger,
+	.set_fmt	= uda1380_set_dai_fmt_capture,
+};
+
 struct snd_soc_dai uda1380_dai[] = {
 {
 	.name = "UDA1380",
@@ -559,13 +615,7 @@
 		.channels_max = 2,
 		.rates = UDA1380_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.hw_params = uda1380_pcm_hw_params,
-		.shutdown = uda1380_pcm_shutdown,
-		.prepare = uda1380_pcm_prepare,
-		.digital_mute = uda1380_mute,
-		.set_fmt = uda1380_set_dai_fmt,
-	},
+	.ops = &uda1380_dai_ops,
 },
 { /* playback only - dual interface */
 	.name = "UDA1380",
@@ -576,13 +626,7 @@
 		.rates = UDA1380_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
-	.ops = {
-		.hw_params = uda1380_pcm_hw_params,
-		.shutdown = uda1380_pcm_shutdown,
-		.prepare = uda1380_pcm_prepare,
-		.digital_mute = uda1380_mute,
-		.set_fmt = uda1380_set_dai_fmt,
-	},
+	.ops = &uda1380_dai_ops_playback,
 },
 { /* capture only - dual interface*/
 	.name = "UDA1380",
@@ -593,12 +637,7 @@
 		.rates = UDA1380_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
-	.ops = {
-		.hw_params = uda1380_pcm_hw_params,
-		.shutdown = uda1380_pcm_shutdown,
-		.prepare = uda1380_pcm_prepare,
-		.set_fmt = uda1380_set_dai_fmt,
-	},
+	.ops = &uda1380_dai_ops_capture,
 },
 };
 EXPORT_SYMBOL_GPL(uda1380_dai);
@@ -606,7 +645,7 @@
 static int uda1380_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -615,7 +654,7 @@
 static int uda1380_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u8 data[2];
 	u16 *cache = codec->reg_cache;
@@ -637,7 +676,7 @@
  */
 static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret = 0;
 
 	codec->name = "UDA1380";
@@ -655,6 +694,9 @@
 	codec->reg_cache_step = 1;
 	uda1380_reset(codec);
 
+	uda1380_codec = codec;
+	INIT_WORK(&uda1380_work, uda1380_flush_work);
+
 	/* register pcms */
 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
 	if (ret < 0) {
@@ -675,7 +717,8 @@
 	}
 
 	/* uda1380 init */
-	uda1380_add_controls(codec);
+	snd_soc_add_controls(codec, uda1380_snd_controls,
+				ARRAY_SIZE(uda1380_snd_controls));
 	uda1380_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -702,7 +745,7 @@
 {
 	struct snd_soc_device *socdev = uda1380_socdev;
 	struct uda1380_setup_data *setup = socdev->codec_data;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	i2c_set_clientdata(i2c, codec);
@@ -786,14 +829,12 @@
 	struct snd_soc_codec *codec;
 	int ret;
 
-	pr_info("UDA1380 Audio Codec %s", UDA1380_VERSION);
-
 	setup = socdev->codec_data;
 	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
 	if (codec == NULL)
 		return -ENOMEM;
 
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -817,7 +858,7 @@
 static int uda1380_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec->control_data)
 		uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 35d9975..3b1d099 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -51,10 +51,17 @@
 	u16 mute;
 };
 
+struct wm8350_jack_data {
+	struct snd_soc_jack *jack;
+	int report;
+};
+
 struct wm8350_data {
 	struct snd_soc_codec codec;
 	struct wm8350_output out1;
 	struct wm8350_output out2;
+	struct wm8350_jack_data hpl;
+	struct wm8350_jack_data hpr;
 	struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
 };
 
@@ -775,21 +782,6 @@
 	{"Beep", NULL, "IN3R PGA"},
 };
 
-static int wm8350_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&wm8350_snd_controls[i],
-					       codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 static int wm8350_add_widgets(struct snd_soc_codec *codec)
 {
 	int ret;
@@ -1309,7 +1301,7 @@
 static int wm8350_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -1318,7 +1310,7 @@
 static int wm8350_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -1328,6 +1320,95 @@
 	return 0;
 }
 
+static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data)
+{
+	struct wm8350_data *priv = data;
+	u16 reg;
+	int report;
+	int mask;
+	struct wm8350_jack_data *jack = NULL;
+
+	switch (irq) {
+	case WM8350_IRQ_CODEC_JCK_DET_L:
+		jack = &priv->hpl;
+		mask = WM8350_JACK_L_LVL;
+		break;
+
+	case WM8350_IRQ_CODEC_JCK_DET_R:
+		jack = &priv->hpr;
+		mask = WM8350_JACK_R_LVL;
+		break;
+
+	default:
+		BUG();
+	}
+
+	if (!jack->jack) {
+		dev_warn(wm8350->dev, "Jack interrupt called with no jack\n");
+		return;
+	}
+
+	/* Debounce */
+	msleep(200);
+
+	reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS);
+	if (reg & mask)
+		report = jack->report;
+	else
+		report = 0;
+
+	snd_soc_jack_report(jack->jack, report, jack->report);
+}
+
+/**
+ * wm8350_hp_jack_detect - Enable headphone jack detection.
+ *
+ * @codec:  WM8350 codec
+ * @which:  left or right jack detect signal
+ * @jack:   jack to report detection events on
+ * @report: value to report
+ *
+ * Enables the headphone jack detection of the WM8350.
+ */
+int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
+			  struct snd_soc_jack *jack, int report)
+{
+	struct wm8350_data *priv = codec->private_data;
+	struct wm8350 *wm8350 = codec->control_data;
+	int irq;
+	int ena;
+
+	switch (which) {
+	case WM8350_JDL:
+		priv->hpl.jack = jack;
+		priv->hpl.report = report;
+		irq = WM8350_IRQ_CODEC_JCK_DET_L;
+		ena = WM8350_JDL_ENA;
+		break;
+
+	case WM8350_JDR:
+		priv->hpr.jack = jack;
+		priv->hpr.report = report;
+		irq = WM8350_IRQ_CODEC_JCK_DET_R;
+		ena = WM8350_JDR_ENA;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
+	wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena);
+
+	/* Sync status */
+	wm8350_hp_jack_handler(wm8350, irq, priv);
+
+	wm8350_unmask_irq(wm8350, irq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect);
+
 static struct snd_soc_codec *wm8350_codec;
 
 static int wm8350_probe(struct platform_device *pdev)
@@ -1342,8 +1423,8 @@
 
 	BUG_ON(!wm8350_codec);
 
-	socdev->codec = wm8350_codec;
-	codec = socdev->codec;
+	socdev->card->codec = wm8350_codec;
+	codec = socdev->card->codec;
 	wm8350 = codec->control_data;
 	priv = codec->private_data;
 
@@ -1381,13 +1462,21 @@
 	wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME,
 			WM8350_OUT2_VU | WM8350_OUT2R_MUTE);
 
+	wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
+	wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
+	wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L,
+			    wm8350_hp_jack_handler, priv);
+	wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
+			    wm8350_hp_jack_handler, priv);
+
 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to create pcms\n");
 		return ret;
 	}
 
-	wm8350_add_controls(codec);
+	snd_soc_add_controls(codec, wm8350_snd_controls,
+				ARRAY_SIZE(wm8350_snd_controls));
 	wm8350_add_widgets(codec);
 
 	wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1409,10 +1498,23 @@
 static int wm8350_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8350 *wm8350 = codec->control_data;
+	struct wm8350_data *priv = codec->private_data;
 	int ret;
 
+	wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
+			  WM8350_JDL_ENA | WM8350_JDR_ENA);
+	wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
+
+	wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
+	wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
+
+	priv->hpl.jack = NULL;
+	priv->hpr.jack = NULL;
+
 	/* cancel any work waiting to be queued. */
 	ret = cancel_delayed_work(&codec->delayed_work);
 
@@ -1436,6 +1538,16 @@
 			SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE)
 
+static struct snd_soc_dai_ops wm8350_dai_ops = {
+	 .hw_params	= wm8350_pcm_hw_params,
+	 .digital_mute	= wm8350_mute,
+	 .trigger	= wm8350_pcm_trigger,
+	 .set_fmt	= wm8350_set_dai_fmt,
+	 .set_sysclk	= wm8350_set_dai_sysclk,
+	 .set_pll	= wm8350_set_fll,
+	 .set_clkdiv	= wm8350_set_clkdiv,
+};
+
 struct snd_soc_dai wm8350_dai = {
 	.name = "WM8350",
 	.playback = {
@@ -1452,15 +1564,7 @@
 		 .rates = WM8350_RATES,
 		 .formats = WM8350_FORMATS,
 	 },
-	.ops = {
-		 .hw_params = wm8350_pcm_hw_params,
-		 .digital_mute = wm8350_mute,
-		 .trigger = wm8350_pcm_trigger,
-		 .set_fmt = wm8350_set_dai_fmt,
-		 .set_sysclk = wm8350_set_dai_sysclk,
-		 .set_pll = wm8350_set_fll,
-		 .set_clkdiv = wm8350_set_clkdiv,
-	 },
+	.ops = &wm8350_dai_ops,
 };
 EXPORT_SYMBOL_GPL(wm8350_dai);
 
@@ -1472,7 +1576,7 @@
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350);
 
-static int wm8350_codec_probe(struct platform_device *pdev)
+static __devinit int wm8350_codec_probe(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
 	struct wm8350_data *priv;
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index cc2887a..d11bd92 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -17,4 +17,12 @@
 extern struct snd_soc_dai wm8350_dai;
 extern struct snd_soc_codec_device soc_codec_dev_wm8350;
 
+enum wm8350_jack {
+	WM8350_JDL = 1,
+	WM8350_JDR = 2,
+};
+
+int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
+			  struct snd_soc_jack *jack, int report);
+
 #endif
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
new file mode 100644
index 0000000..510efa6
--- /dev/null
+++ b/sound/soc/codecs/wm8400.c
@@ -0,0 +1,1582 @@
+/*
+ * wm8400.c  --  WM8400 ALSA Soc Audio driver
+ *
+ * Copyright 2008, 2009 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/wm8400-audio.h>
+#include <linux/mfd/wm8400-private.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8400.h"
+
+/* Fake register for internal state */
+#define WM8400_INTDRIVBITS      (WM8400_REGISTER_COUNT + 1)
+#define WM8400_INMIXL_PWR			0
+#define WM8400_AINLMUX_PWR			1
+#define WM8400_INMIXR_PWR			2
+#define WM8400_AINRMUX_PWR			3
+
+static struct regulator_bulk_data power[] = {
+	{
+		.supply = "I2S1VDD",
+	},
+	{
+		.supply = "I2S2VDD",
+	},
+	{
+		.supply = "DCVDD",
+	},
+	{
+		.supply = "AVDD",
+	},
+	{
+		.supply = "FLLVDD",
+	},
+	{
+		.supply = "HPVDD",
+	},
+	{
+		.supply = "SPKVDD",
+	},
+};
+
+/* codec private data */
+struct wm8400_priv {
+	struct snd_soc_codec codec;
+	struct wm8400 *wm8400;
+	u16 fake_register;
+	unsigned int sysclk;
+	unsigned int pcmclk;
+	struct work_struct work;
+	int fll_in, fll_out;
+};
+
+static inline unsigned int wm8400_read(struct snd_soc_codec *codec,
+				       unsigned int reg)
+{
+	struct wm8400_priv *wm8400 = codec->private_data;
+
+	if (reg == WM8400_INTDRIVBITS)
+		return wm8400->fake_register;
+	else
+		return wm8400_reg_read(wm8400->wm8400, reg);
+}
+
+/*
+ * write to the wm8400 register space
+ */
+static int wm8400_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int value)
+{
+	struct wm8400_priv *wm8400 = codec->private_data;
+
+	if (reg == WM8400_INTDRIVBITS) {
+		wm8400->fake_register = value;
+		return 0;
+	} else
+		return wm8400_set_bits(wm8400->wm8400, reg, 0xffff, value);
+}
+
+static void wm8400_codec_reset(struct snd_soc_codec *codec)
+{
+	struct wm8400_priv *wm8400 = codec->private_data;
+
+	wm8400_reset_codec_reg_cache(wm8400->wm8400);
+}
+
+static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
+
+static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000);
+
+static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, -2100, 0);
+
+static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600);
+
+static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0);
+
+static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0);
+
+static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763);
+
+static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0);
+
+static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
+        struct snd_ctl_elem_value *ucontrol)
+{
+        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	int reg = mc->reg;
+        int ret;
+        u16 val;
+
+        ret = snd_soc_put_volsw(kcontrol, ucontrol);
+        if (ret < 0)
+                return ret;
+
+        /* now hit the volume update bits (always bit 8) */
+        val = wm8400_read(codec, reg);
+        return wm8400_write(codec, reg, val | 0x0100);
+}
+
+#define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+		SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+	.tlv.p = (tlv_array), \
+	.info = snd_soc_info_volsw, \
+	.get = snd_soc_get_volsw, .put = wm8400_outpga_put_volsw_vu, \
+	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
+
+
+static const char *wm8400_digital_sidetone[] =
+	{"None", "Left ADC", "Right ADC", "Reserved"};
+
+static const struct soc_enum wm8400_left_digital_sidetone_enum =
+SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
+		WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone);
+
+static const struct soc_enum wm8400_right_digital_sidetone_enum =
+SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
+		WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone);
+
+static const char *wm8400_adcmode[] =
+	{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
+
+static const struct soc_enum wm8400_right_adcmode_enum =
+SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode);
+
+static const struct snd_kcontrol_new wm8400_snd_controls[] = {
+/* INMIXL */
+SOC_SINGLE("LIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L12MNBST_SHIFT,
+	   1, 0),
+SOC_SINGLE("LIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L34MNBST_SHIFT,
+	   1, 0),
+/* INMIXR */
+SOC_SINGLE("RIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R12MNBST_SHIFT,
+	   1, 0),
+SOC_SINGLE("RIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R34MNBST_SHIFT,
+	   1, 0),
+
+/* LOMIX */
+SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER3,
+	WM8400_LLI3LOVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3,
+	WM8400_LR12LOVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3,
+	WM8400_LL12LOVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER5,
+	WM8400_LRI3LOVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER5,
+	WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER5,
+	WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv),
+
+/* ROMIX */
+SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER4,
+	WM8400_RRI3ROVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4,
+	WM8400_RL12ROVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4,
+	WM8400_RR12ROVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER6,
+	WM8400_RLI3ROVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER6,
+	WM8400_RLBROVOL_SHIFT, 7, 0, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER6,
+	WM8400_RRBROVOL_SHIFT, 7, 0, out_mix_tlv),
+
+/* LOUT */
+WM8400_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8400_LEFT_OUTPUT_VOLUME,
+	WM8400_LOUTVOL_SHIFT, WM8400_LOUTVOL_MASK, 0, out_pga_tlv),
+SOC_SINGLE("LOUT ZC", WM8400_LEFT_OUTPUT_VOLUME, WM8400_LOZC_SHIFT, 1, 0),
+
+/* ROUT */
+WM8400_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8400_RIGHT_OUTPUT_VOLUME,
+	WM8400_ROUTVOL_SHIFT, WM8400_ROUTVOL_MASK, 0, out_pga_tlv),
+SOC_SINGLE("ROUT ZC", WM8400_RIGHT_OUTPUT_VOLUME, WM8400_ROZC_SHIFT, 1, 0),
+
+/* LOPGA */
+WM8400_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8400_LEFT_OPGA_VOLUME,
+	WM8400_LOPGAVOL_SHIFT, WM8400_LOPGAVOL_MASK, 0, out_pga_tlv),
+SOC_SINGLE("LOPGA ZC Switch", WM8400_LEFT_OPGA_VOLUME,
+	WM8400_LOPGAZC_SHIFT, 1, 0),
+
+/* ROPGA */
+WM8400_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8400_RIGHT_OPGA_VOLUME,
+	WM8400_ROPGAVOL_SHIFT, WM8400_ROPGAVOL_MASK, 0, out_pga_tlv),
+SOC_SINGLE("ROPGA ZC Switch", WM8400_RIGHT_OPGA_VOLUME,
+	WM8400_ROPGAZC_SHIFT, 1, 0),
+
+SOC_SINGLE("LON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME,
+	WM8400_LONMUTE_SHIFT, 1, 0),
+SOC_SINGLE("LOP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME,
+	WM8400_LOPMUTE_SHIFT, 1, 0),
+SOC_SINGLE("LOP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME,
+	WM8400_LOATTN_SHIFT, 1, 0),
+SOC_SINGLE("RON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME,
+	WM8400_RONMUTE_SHIFT, 1, 0),
+SOC_SINGLE("ROP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME,
+	WM8400_ROPMUTE_SHIFT, 1, 0),
+SOC_SINGLE("ROP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME,
+	WM8400_ROATTN_SHIFT, 1, 0),
+
+SOC_SINGLE("OUT3 Mute Switch", WM8400_OUT3_4_VOLUME,
+	WM8400_OUT3MUTE_SHIFT, 1, 0),
+SOC_SINGLE("OUT3 Attenuation Switch", WM8400_OUT3_4_VOLUME,
+	WM8400_OUT3ATTN_SHIFT, 1, 0),
+
+SOC_SINGLE("OUT4 Mute Switch", WM8400_OUT3_4_VOLUME,
+	WM8400_OUT4MUTE_SHIFT, 1, 0),
+SOC_SINGLE("OUT4 Attenuation Switch", WM8400_OUT3_4_VOLUME,
+	WM8400_OUT4ATTN_SHIFT, 1, 0),
+
+SOC_SINGLE("Speaker Mode Switch", WM8400_CLASSD1,
+	WM8400_CDMODE_SHIFT, 1, 0),
+
+SOC_SINGLE("Speaker Output Attenuation Volume", WM8400_SPEAKER_VOLUME,
+	WM8400_SPKATTN_SHIFT, WM8400_SPKATTN_MASK, 0),
+SOC_SINGLE("Speaker DC Boost Volume", WM8400_CLASSD3,
+	WM8400_DCGAIN_SHIFT, 6, 0),
+SOC_SINGLE("Speaker AC Boost Volume", WM8400_CLASSD3,
+	WM8400_ACGAIN_SHIFT, 6, 0),
+
+WM8400_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume",
+	WM8400_LEFT_DAC_DIGITAL_VOLUME, WM8400_DACL_VOL_SHIFT,
+	127, 0, out_dac_tlv),
+
+WM8400_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume",
+	WM8400_RIGHT_DAC_DIGITAL_VOLUME, WM8400_DACR_VOL_SHIFT,
+	127, 0, out_dac_tlv),
+
+SOC_ENUM("Left Digital Sidetone", wm8400_left_digital_sidetone_enum),
+SOC_ENUM("Right Digital Sidetone", wm8400_right_digital_sidetone_enum),
+
+SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE,
+	WM8400_ADCL_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv),
+SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE,
+	WM8400_ADCR_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv),
+
+SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8400_ADC_CTRL,
+	WM8400_ADC_HPF_ENA_SHIFT, 1, 0),
+
+SOC_ENUM("ADC HPF Mode", wm8400_right_adcmode_enum),
+
+WM8400_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume",
+	WM8400_LEFT_ADC_DIGITAL_VOLUME,
+	WM8400_ADCL_VOL_SHIFT,
+	WM8400_ADCL_VOL_MASK,
+	0,
+	in_adc_tlv),
+
+WM8400_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume",
+	WM8400_RIGHT_ADC_DIGITAL_VOLUME,
+	WM8400_ADCR_VOL_SHIFT,
+	WM8400_ADCR_VOL_MASK,
+	0,
+	in_adc_tlv),
+
+WM8400_OUTPGA_SINGLE_R_TLV("LIN12 Volume",
+	WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
+	WM8400_LIN12VOL_SHIFT,
+	WM8400_LIN12VOL_MASK,
+	0,
+	in_pga_tlv),
+
+SOC_SINGLE("LIN12 ZC Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
+	WM8400_LI12ZC_SHIFT, 1, 0),
+
+SOC_SINGLE("LIN12 Mute Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
+	WM8400_LI12MUTE_SHIFT, 1, 0),
+
+WM8400_OUTPGA_SINGLE_R_TLV("LIN34 Volume",
+	WM8400_LEFT_LINE_INPUT_3_4_VOLUME,
+	WM8400_LIN34VOL_SHIFT,
+	WM8400_LIN34VOL_MASK,
+	0,
+	in_pga_tlv),
+
+SOC_SINGLE("LIN34 ZC Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME,
+	WM8400_LI34ZC_SHIFT, 1, 0),
+
+SOC_SINGLE("LIN34 Mute Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME,
+	WM8400_LI34MUTE_SHIFT, 1, 0),
+
+WM8400_OUTPGA_SINGLE_R_TLV("RIN12 Volume",
+	WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
+	WM8400_RIN12VOL_SHIFT,
+	WM8400_RIN12VOL_MASK,
+	0,
+	in_pga_tlv),
+
+SOC_SINGLE("RIN12 ZC Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
+	WM8400_RI12ZC_SHIFT, 1, 0),
+
+SOC_SINGLE("RIN12 Mute Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
+	WM8400_RI12MUTE_SHIFT, 1, 0),
+
+WM8400_OUTPGA_SINGLE_R_TLV("RIN34 Volume",
+	WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
+	WM8400_RIN34VOL_SHIFT,
+	WM8400_RIN34VOL_MASK,
+	0,
+	in_pga_tlv),
+
+SOC_SINGLE("RIN34 ZC Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
+	WM8400_RI34ZC_SHIFT, 1, 0),
+
+SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
+	WM8400_RI34MUTE_SHIFT, 1, 0),
+
+};
+
+/* add non dapm controls */
+static int wm8400_add_controls(struct snd_soc_codec *codec)
+{
+	return snd_soc_add_controls(codec, wm8400_snd_controls,
+				ARRAY_SIZE(wm8400_snd_controls));
+}
+
+/*
+ * _DAPM_ Controls
+ */
+
+static int inmixer_event (struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	u16 reg, fakepower;
+
+	reg = wm8400_read(w->codec, WM8400_POWER_MANAGEMENT_2);
+	fakepower = wm8400_read(w->codec, WM8400_INTDRIVBITS);
+
+	if (fakepower & ((1 << WM8400_INMIXL_PWR) |
+		(1 << WM8400_AINLMUX_PWR))) {
+		reg |= WM8400_AINL_ENA;
+	} else {
+		reg &= ~WM8400_AINL_ENA;
+	}
+
+	if (fakepower & ((1 << WM8400_INMIXR_PWR) |
+		(1 << WM8400_AINRMUX_PWR))) {
+		reg |= WM8400_AINR_ENA;
+	} else {
+		reg &= ~WM8400_AINL_ENA;
+	}
+	wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
+
+	return 0;
+}
+
+static int outmixer_event (struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol * kcontrol, int event)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	u32 reg_shift = mc->shift;
+	int ret = 0;
+	u16 reg;
+
+	switch (reg_shift) {
+	case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) :
+		reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER1);
+		if (reg & WM8400_LDLO) {
+			printk(KERN_WARNING
+			"Cannot set as Output Mixer 1 LDLO Set\n");
+			ret = -1;
+		}
+		break;
+	case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8):
+		reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER2);
+		if (reg & WM8400_RDRO) {
+			printk(KERN_WARNING
+			"Cannot set as Output Mixer 2 RDRO Set\n");
+			ret = -1;
+		}
+		break;
+	case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8):
+		reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER);
+		if (reg & WM8400_LDSPK) {
+			printk(KERN_WARNING
+			"Cannot set as Speaker Mixer LDSPK Set\n");
+			ret = -1;
+		}
+		break;
+	case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8):
+		reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER);
+		if (reg & WM8400_RDSPK) {
+			printk(KERN_WARNING
+			"Cannot set as Speaker Mixer RDSPK Set\n");
+			ret = -1;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+/* INMIX dB values */
+static const unsigned int in_mix_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0,7, TLV_DB_LINEAR_ITEM(-1200, 600),
+};
+
+/* Left In PGA Connections */
+static const struct snd_kcontrol_new wm8400_dapm_lin12_pga_controls[] = {
+SOC_DAPM_SINGLE("LIN1 Switch", WM8400_INPUT_MIXER2, WM8400_LMN1_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LIN2 Switch", WM8400_INPUT_MIXER2, WM8400_LMP2_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8400_dapm_lin34_pga_controls[] = {
+SOC_DAPM_SINGLE("LIN3 Switch", WM8400_INPUT_MIXER2, WM8400_LMN3_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LIN4 Switch", WM8400_INPUT_MIXER2, WM8400_LMP4_SHIFT, 1, 0),
+};
+
+/* Right In PGA Connections */
+static const struct snd_kcontrol_new wm8400_dapm_rin12_pga_controls[] = {
+SOC_DAPM_SINGLE("RIN1 Switch", WM8400_INPUT_MIXER2, WM8400_RMN1_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("RIN2 Switch", WM8400_INPUT_MIXER2, WM8400_RMP2_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8400_dapm_rin34_pga_controls[] = {
+SOC_DAPM_SINGLE("RIN3 Switch", WM8400_INPUT_MIXER2, WM8400_RMN3_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("RIN4 Switch", WM8400_INPUT_MIXER2, WM8400_RMP4_SHIFT, 1, 0),
+};
+
+/* INMIXL */
+static const struct snd_kcontrol_new wm8400_dapm_inmixl_controls[] = {
+SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8400_INPUT_MIXER3,
+	WM8400_LDBVOL_SHIFT, WM8400_LDBVOL_MASK, 0, in_mix_tlv),
+SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8400_INPUT_MIXER5, WM8400_LI2BVOL_SHIFT,
+	7, 0, in_mix_tlv),
+SOC_DAPM_SINGLE("LINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT,
+		1, 0),
+SOC_DAPM_SINGLE("LINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT,
+		1, 0),
+};
+
+/* INMIXR */
+static const struct snd_kcontrol_new wm8400_dapm_inmixr_controls[] = {
+SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8400_INPUT_MIXER4,
+	WM8400_RDBVOL_SHIFT, WM8400_RDBVOL_MASK, 0, in_mix_tlv),
+SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8400_INPUT_MIXER6, WM8400_RI2BVOL_SHIFT,
+	7, 0, in_mix_tlv),
+SOC_DAPM_SINGLE("RINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT,
+	1, 0),
+SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT,
+	1, 0),
+};
+
+/* AINLMUX */
+static const char *wm8400_ainlmux[] =
+	{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
+
+static const struct soc_enum wm8400_ainlmux_enum =
+SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT,
+	ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux);
+
+static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls =
+SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum);
+
+/* DIFFINL */
+
+/* AINRMUX */
+static const char *wm8400_ainrmux[] =
+	{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
+
+static const struct soc_enum wm8400_ainrmux_enum =
+SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT,
+	ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux);
+
+static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls =
+SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum);
+
+/* RXVOICE */
+static const struct snd_kcontrol_new wm8400_dapm_rxvoice_controls[] = {
+SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8400_INPUT_MIXER5, WM8400_LR4BVOL_SHIFT,
+			WM8400_LR4BVOL_MASK, 0, in_mix_tlv),
+SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8400_INPUT_MIXER6, WM8400_RL4BVOL_SHIFT,
+			WM8400_RL4BVOL_MASK, 0, in_mix_tlv),
+};
+
+/* LOMIX */
+static const struct snd_kcontrol_new wm8400_dapm_lomix_controls[] = {
+SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER1,
+	WM8400_LRBLO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER1,
+	WM8400_LLBLO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER1,
+	WM8400_LRI3LO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER1,
+	WM8400_LLI3LO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1,
+	WM8400_LR12LO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1,
+	WM8400_LL12LO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8400_OUTPUT_MIXER1,
+	WM8400_LDLO_SHIFT, 1, 0),
+};
+
+/* ROMIX */
+static const struct snd_kcontrol_new wm8400_dapm_romix_controls[] = {
+SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER2,
+	WM8400_RLBRO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER2,
+	WM8400_RRBRO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER2,
+	WM8400_RLI3RO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER2,
+	WM8400_RRI3RO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2,
+	WM8400_RL12RO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2,
+	WM8400_RR12RO_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8400_OUTPUT_MIXER2,
+	WM8400_RDRO_SHIFT, 1, 0),
+};
+
+/* LONMIX */
+static const struct snd_kcontrol_new wm8400_dapm_lonmix_controls[] = {
+SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1,
+	WM8400_LLOPGALON_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER1,
+	WM8400_LROPGALON_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8400_LINE_MIXER1,
+	WM8400_LOPLON_SHIFT, 1, 0),
+};
+
+/* LOPMIX */
+static const struct snd_kcontrol_new wm8400_dapm_lopmix_controls[] = {
+SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER1,
+	WM8400_LR12LOP_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER1,
+	WM8400_LL12LOP_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1,
+	WM8400_LLOPGALOP_SHIFT, 1, 0),
+};
+
+/* RONMIX */
+static const struct snd_kcontrol_new wm8400_dapm_ronmix_controls[] = {
+SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2,
+	WM8400_RROPGARON_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER2,
+	WM8400_RLOPGARON_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8400_LINE_MIXER2,
+	WM8400_ROPRON_SHIFT, 1, 0),
+};
+
+/* ROPMIX */
+static const struct snd_kcontrol_new wm8400_dapm_ropmix_controls[] = {
+SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER2,
+	WM8400_RL12ROP_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER2,
+	WM8400_RR12ROP_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2,
+	WM8400_RROPGAROP_SHIFT, 1, 0),
+};
+
+/* OUT3MIX */
+static const struct snd_kcontrol_new wm8400_dapm_out3mix_controls[] = {
+SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER,
+	WM8400_LI4O3_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8400_OUT3_4_MIXER,
+	WM8400_LPGAO3_SHIFT, 1, 0),
+};
+
+/* OUT4MIX */
+static const struct snd_kcontrol_new wm8400_dapm_out4mix_controls[] = {
+SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8400_OUT3_4_MIXER,
+	WM8400_RPGAO4_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER,
+	WM8400_RI4O4_SHIFT, 1, 0),
+};
+
+/* SPKMIX */
+static const struct snd_kcontrol_new wm8400_dapm_spkmix_controls[] = {
+SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8400_SPEAKER_MIXER,
+	WM8400_LI2SPK_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8400_SPEAKER_MIXER,
+	WM8400_LB2SPK_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8400_SPEAKER_MIXER,
+	WM8400_LOPGASPK_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8400_SPEAKER_MIXER,
+	WM8400_LDSPK_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8400_SPEAKER_MIXER,
+	WM8400_RDSPK_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8400_SPEAKER_MIXER,
+	WM8400_ROPGASPK_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8400_SPEAKER_MIXER,
+	WM8400_RL12ROP_SHIFT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8400_SPEAKER_MIXER,
+	WM8400_RI2SPK_SHIFT, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget wm8400_dapm_widgets[] = {
+/* Input Side */
+/* Input Lines */
+SND_SOC_DAPM_INPUT("LIN1"),
+SND_SOC_DAPM_INPUT("LIN2"),
+SND_SOC_DAPM_INPUT("LIN3"),
+SND_SOC_DAPM_INPUT("LIN4/RXN"),
+SND_SOC_DAPM_INPUT("RIN3"),
+SND_SOC_DAPM_INPUT("RIN4/RXP"),
+SND_SOC_DAPM_INPUT("RIN1"),
+SND_SOC_DAPM_INPUT("RIN2"),
+SND_SOC_DAPM_INPUT("Internal ADC Source"),
+
+/* DACs */
+SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8400_POWER_MANAGEMENT_2,
+	WM8400_ADCL_ENA_SHIFT, 0),
+SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8400_POWER_MANAGEMENT_2,
+	WM8400_ADCR_ENA_SHIFT, 0),
+
+/* Input PGAs */
+SND_SOC_DAPM_MIXER("LIN12 PGA", WM8400_POWER_MANAGEMENT_2,
+		   WM8400_LIN12_ENA_SHIFT,
+		   0, &wm8400_dapm_lin12_pga_controls[0],
+		   ARRAY_SIZE(wm8400_dapm_lin12_pga_controls)),
+SND_SOC_DAPM_MIXER("LIN34 PGA", WM8400_POWER_MANAGEMENT_2,
+		   WM8400_LIN34_ENA_SHIFT,
+		   0, &wm8400_dapm_lin34_pga_controls[0],
+		   ARRAY_SIZE(wm8400_dapm_lin34_pga_controls)),
+SND_SOC_DAPM_MIXER("RIN12 PGA", WM8400_POWER_MANAGEMENT_2,
+		   WM8400_RIN12_ENA_SHIFT,
+		   0, &wm8400_dapm_rin12_pga_controls[0],
+		   ARRAY_SIZE(wm8400_dapm_rin12_pga_controls)),
+SND_SOC_DAPM_MIXER("RIN34 PGA", WM8400_POWER_MANAGEMENT_2,
+		   WM8400_RIN34_ENA_SHIFT,
+		   0, &wm8400_dapm_rin34_pga_controls[0],
+		   ARRAY_SIZE(wm8400_dapm_rin34_pga_controls)),
+
+/* INMIXL */
+SND_SOC_DAPM_MIXER_E("INMIXL", WM8400_INTDRIVBITS, WM8400_INMIXL_PWR, 0,
+	&wm8400_dapm_inmixl_controls[0],
+	ARRAY_SIZE(wm8400_dapm_inmixl_controls),
+	inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+/* AINLMUX */
+SND_SOC_DAPM_MUX_E("AILNMUX", WM8400_INTDRIVBITS, WM8400_AINLMUX_PWR, 0,
+	&wm8400_dapm_ainlmux_controls, inmixer_event,
+	SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+/* INMIXR */
+SND_SOC_DAPM_MIXER_E("INMIXR", WM8400_INTDRIVBITS, WM8400_INMIXR_PWR, 0,
+	&wm8400_dapm_inmixr_controls[0],
+	ARRAY_SIZE(wm8400_dapm_inmixr_controls),
+	inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+/* AINRMUX */
+SND_SOC_DAPM_MUX_E("AIRNMUX", WM8400_INTDRIVBITS, WM8400_AINRMUX_PWR, 0,
+	&wm8400_dapm_ainrmux_controls, inmixer_event,
+	SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+/* Output Side */
+/* DACs */
+SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8400_POWER_MANAGEMENT_3,
+	WM8400_DACL_ENA_SHIFT, 0),
+SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8400_POWER_MANAGEMENT_3,
+	WM8400_DACR_ENA_SHIFT, 0),
+
+/* LOMIX */
+SND_SOC_DAPM_MIXER_E("LOMIX", WM8400_POWER_MANAGEMENT_3,
+		     WM8400_LOMIX_ENA_SHIFT,
+		     0, &wm8400_dapm_lomix_controls[0],
+		     ARRAY_SIZE(wm8400_dapm_lomix_controls),
+		     outmixer_event, SND_SOC_DAPM_PRE_REG),
+
+/* LONMIX */
+SND_SOC_DAPM_MIXER("LONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LON_ENA_SHIFT,
+		   0, &wm8400_dapm_lonmix_controls[0],
+		   ARRAY_SIZE(wm8400_dapm_lonmix_controls)),
+
+/* LOPMIX */
+SND_SOC_DAPM_MIXER("LOPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LOP_ENA_SHIFT,
+		   0, &wm8400_dapm_lopmix_controls[0],
+		   ARRAY_SIZE(wm8400_dapm_lopmix_controls)),
+
+/* OUT3MIX */
+SND_SOC_DAPM_MIXER("OUT3MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT3_ENA_SHIFT,
+		   0, &wm8400_dapm_out3mix_controls[0],
+		   ARRAY_SIZE(wm8400_dapm_out3mix_controls)),
+
+/* SPKMIX */
+SND_SOC_DAPM_MIXER_E("SPKMIX", WM8400_POWER_MANAGEMENT_1, WM8400_SPK_ENA_SHIFT,
+		     0, &wm8400_dapm_spkmix_controls[0],
+		     ARRAY_SIZE(wm8400_dapm_spkmix_controls), outmixer_event,
+		     SND_SOC_DAPM_PRE_REG),
+
+/* OUT4MIX */
+SND_SOC_DAPM_MIXER("OUT4MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT4_ENA_SHIFT,
+	0, &wm8400_dapm_out4mix_controls[0],
+	ARRAY_SIZE(wm8400_dapm_out4mix_controls)),
+
+/* ROPMIX */
+SND_SOC_DAPM_MIXER("ROPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_ROP_ENA_SHIFT,
+		   0, &wm8400_dapm_ropmix_controls[0],
+		   ARRAY_SIZE(wm8400_dapm_ropmix_controls)),
+
+/* RONMIX */
+SND_SOC_DAPM_MIXER("RONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_RON_ENA_SHIFT,
+		   0, &wm8400_dapm_ronmix_controls[0],
+		   ARRAY_SIZE(wm8400_dapm_ronmix_controls)),
+
+/* ROMIX */
+SND_SOC_DAPM_MIXER_E("ROMIX", WM8400_POWER_MANAGEMENT_3,
+		     WM8400_ROMIX_ENA_SHIFT,
+		     0, &wm8400_dapm_romix_controls[0],
+		     ARRAY_SIZE(wm8400_dapm_romix_controls),
+		     outmixer_event, SND_SOC_DAPM_PRE_REG),
+
+/* LOUT PGA */
+SND_SOC_DAPM_PGA("LOUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_LOUT_ENA_SHIFT,
+		 0, NULL, 0),
+
+/* ROUT PGA */
+SND_SOC_DAPM_PGA("ROUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_ROUT_ENA_SHIFT,
+		 0, NULL, 0),
+
+/* LOPGA */
+SND_SOC_DAPM_PGA("LOPGA", WM8400_POWER_MANAGEMENT_3, WM8400_LOPGA_ENA_SHIFT, 0,
+	NULL, 0),
+
+/* ROPGA */
+SND_SOC_DAPM_PGA("ROPGA", WM8400_POWER_MANAGEMENT_3, WM8400_ROPGA_ENA_SHIFT, 0,
+	NULL, 0),
+
+/* MICBIAS */
+SND_SOC_DAPM_MICBIAS("MICBIAS", WM8400_POWER_MANAGEMENT_1,
+	WM8400_MIC1BIAS_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_OUTPUT("LON"),
+SND_SOC_DAPM_OUTPUT("LOP"),
+SND_SOC_DAPM_OUTPUT("OUT3"),
+SND_SOC_DAPM_OUTPUT("LOUT"),
+SND_SOC_DAPM_OUTPUT("SPKN"),
+SND_SOC_DAPM_OUTPUT("SPKP"),
+SND_SOC_DAPM_OUTPUT("ROUT"),
+SND_SOC_DAPM_OUTPUT("OUT4"),
+SND_SOC_DAPM_OUTPUT("ROP"),
+SND_SOC_DAPM_OUTPUT("RON"),
+
+SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* Make DACs turn on when playing even if not mixed into any outputs */
+	{"Internal DAC Sink", NULL, "Left DAC"},
+	{"Internal DAC Sink", NULL, "Right DAC"},
+
+	/* Make ADCs turn on when recording
+	 * even if not mixed from any inputs */
+	{"Left ADC", NULL, "Internal ADC Source"},
+	{"Right ADC", NULL, "Internal ADC Source"},
+
+	/* Input Side */
+	/* LIN12 PGA */
+	{"LIN12 PGA", "LIN1 Switch", "LIN1"},
+	{"LIN12 PGA", "LIN2 Switch", "LIN2"},
+	/* LIN34 PGA */
+	{"LIN34 PGA", "LIN3 Switch", "LIN3"},
+	{"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"},
+	/* INMIXL */
+	{"INMIXL", "Record Left Volume", "LOMIX"},
+	{"INMIXL", "LIN2 Volume", "LIN2"},
+	{"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
+	{"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
+	/* AILNMUX */
+	{"AILNMUX", "INMIXL Mix", "INMIXL"},
+	{"AILNMUX", "DIFFINL Mix", "LIN12 PGA"},
+	{"AILNMUX", "DIFFINL Mix", "LIN34 PGA"},
+	{"AILNMUX", "RXVOICE Mix", "LIN4/RXN"},
+	{"AILNMUX", "RXVOICE Mix", "RIN4/RXP"},
+	/* ADC */
+	{"Left ADC", NULL, "AILNMUX"},
+
+	/* RIN12 PGA */
+	{"RIN12 PGA", "RIN1 Switch", "RIN1"},
+	{"RIN12 PGA", "RIN2 Switch", "RIN2"},
+	/* RIN34 PGA */
+	{"RIN34 PGA", "RIN3 Switch", "RIN3"},
+	{"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"},
+	/* INMIXL */
+	{"INMIXR", "Record Right Volume", "ROMIX"},
+	{"INMIXR", "RIN2 Volume", "RIN2"},
+	{"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
+	{"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
+	/* AIRNMUX */
+	{"AIRNMUX", "INMIXR Mix", "INMIXR"},
+	{"AIRNMUX", "DIFFINR Mix", "RIN12 PGA"},
+	{"AIRNMUX", "DIFFINR Mix", "RIN34 PGA"},
+	{"AIRNMUX", "RXVOICE Mix", "LIN4/RXN"},
+	{"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"},
+	/* ADC */
+	{"Right ADC", NULL, "AIRNMUX"},
+
+	/* LOMIX */
+	{"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"},
+	{"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"},
+	{"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
+	{"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
+	{"LOMIX", "LOMIX Right ADC Bypass Switch", "AIRNMUX"},
+	{"LOMIX", "LOMIX Left ADC Bypass Switch", "AILNMUX"},
+	{"LOMIX", "LOMIX Left DAC Switch", "Left DAC"},
+
+	/* ROMIX */
+	{"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"},
+	{"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"},
+	{"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
+	{"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
+	{"ROMIX", "ROMIX Right ADC Bypass Switch", "AIRNMUX"},
+	{"ROMIX", "ROMIX Left ADC Bypass Switch", "AILNMUX"},
+	{"ROMIX", "ROMIX Right DAC Switch", "Right DAC"},
+
+	/* SPKMIX */
+	{"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"},
+	{"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"},
+	{"SPKMIX", "SPKMIX LADC Bypass Switch", "AILNMUX"},
+	{"SPKMIX", "SPKMIX RADC Bypass Switch", "AIRNMUX"},
+	{"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"},
+	{"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"},
+	{"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"},
+	{"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"},
+
+	/* LONMIX */
+	{"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"},
+	{"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"},
+	{"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"},
+
+	/* LOPMIX */
+	{"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"},
+	{"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"},
+	{"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"},
+
+	/* OUT3MIX */
+	{"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"},
+	{"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"},
+
+	/* OUT4MIX */
+	{"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"},
+	{"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"},
+
+	/* RONMIX */
+	{"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"},
+	{"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"},
+	{"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"},
+
+	/* ROPMIX */
+	{"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"},
+	{"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"},
+	{"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"},
+
+	/* Out Mixer PGAs */
+	{"LOPGA", NULL, "LOMIX"},
+	{"ROPGA", NULL, "ROMIX"},
+
+	{"LOUT PGA", NULL, "LOMIX"},
+	{"ROUT PGA", NULL, "ROMIX"},
+
+	/* Output Pins */
+	{"LON", NULL, "LONMIX"},
+	{"LOP", NULL, "LOPMIX"},
+	{"OUT3", NULL, "OUT3MIX"},
+	{"LOUT", NULL, "LOUT PGA"},
+	{"SPKN", NULL, "SPKMIX"},
+	{"ROUT", NULL, "ROUT PGA"},
+	{"OUT4", NULL, "OUT4MIX"},
+	{"ROP", NULL, "ROPMIX"},
+	{"RON", NULL, "RONMIX"},
+};
+
+static int wm8400_add_widgets(struct snd_soc_codec *codec)
+{
+	snd_soc_dapm_new_controls(codec, wm8400_dapm_widgets,
+				  ARRAY_SIZE(wm8400_dapm_widgets));
+
+	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+	snd_soc_dapm_new_widgets(codec);
+	return 0;
+}
+
+/*
+ * Clock after FLL and dividers
+ */
+static int wm8400_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct wm8400_priv *wm8400 = codec->private_data;
+
+	wm8400->sysclk = freq;
+	return 0;
+}
+
+struct fll_factors {
+	u16 n;
+	u16 k;
+	u16 outdiv;
+	u16 fratio;
+	u16 freq_ref;
+};
+
+#define FIXED_FLL_SIZE ((1 << 16) * 10)
+
+static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors,
+		       unsigned int Fref, unsigned int Fout)
+{
+	u64 Kpart;
+	unsigned int K, Nmod, target;
+
+	factors->outdiv = 2;
+	while (Fout * factors->outdiv <  90000000 ||
+	       Fout * factors->outdiv > 100000000) {
+		factors->outdiv *= 2;
+		if (factors->outdiv > 32) {
+			dev_err(wm8400->wm8400->dev,
+				"Unsupported FLL output frequency %dHz\n",
+				Fout);
+			return -EINVAL;
+		}
+	}
+	target = Fout * factors->outdiv;
+	factors->outdiv = factors->outdiv >> 2;
+
+	if (Fref < 48000)
+		factors->freq_ref = 1;
+	else
+		factors->freq_ref = 0;
+
+	if (Fref < 1000000)
+		factors->fratio = 9;
+	else
+		factors->fratio = 0;
+
+	/* Ensure we have a fractional part */
+	do {
+		if (Fref < 1000000)
+			factors->fratio--;
+		else
+			factors->fratio++;
+
+		if (factors->fratio < 1 || factors->fratio > 8) {
+			dev_err(wm8400->wm8400->dev,
+				"Unable to calculate FRATIO\n");
+			return -EINVAL;
+		}
+
+		factors->n = target / (Fref * factors->fratio);
+		Nmod = target % (Fref * factors->fratio);
+	} while (Nmod == 0);
+
+	/* Calculate fractional part - scale up so we can round. */
+	Kpart = FIXED_FLL_SIZE * (long long)Nmod;
+
+	do_div(Kpart, (Fref * factors->fratio));
+
+	K = Kpart & 0xFFFFFFFF;
+
+	if ((K % 10) >= 5)
+		K += 5;
+
+	/* Move down to proper range now rounding is done */
+	factors->k = K / 10;
+
+	dev_dbg(wm8400->wm8400->dev,
+		"FLL: Fref=%d Fout=%d N=%x K=%x, FRATIO=%x OUTDIV=%x\n",
+		Fref, Fout,
+		factors->n, factors->k, factors->fratio, factors->outdiv);
+
+	return 0;
+}
+
+static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+			      unsigned int freq_in, unsigned int freq_out)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct wm8400_priv *wm8400 = codec->private_data;
+	struct fll_factors factors;
+	int ret;
+	u16 reg;
+
+	if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out)
+		return 0;
+
+	if (freq_out != 0) {
+		ret = fll_factors(wm8400, &factors, freq_in, freq_out);
+		if (ret != 0)
+			return ret;
+	}
+
+	wm8400->fll_out = freq_out;
+	wm8400->fll_in = freq_in;
+
+	/* We *must* disable the FLL before any changes */
+	reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_2);
+	reg &= ~WM8400_FLL_ENA;
+	wm8400_write(codec, WM8400_POWER_MANAGEMENT_2, reg);
+
+	reg = wm8400_read(codec, WM8400_FLL_CONTROL_1);
+	reg &= ~WM8400_FLL_OSC_ENA;
+	wm8400_write(codec, WM8400_FLL_CONTROL_1, reg);
+
+	if (freq_out == 0)
+		return 0;
+
+	reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK);
+	reg |= WM8400_FLL_FRAC | factors.fratio;
+	reg |= factors.freq_ref << WM8400_FLL_REF_FREQ_SHIFT;
+	wm8400_write(codec, WM8400_FLL_CONTROL_1, reg);
+
+	wm8400_write(codec, WM8400_FLL_CONTROL_2, factors.k);
+	wm8400_write(codec, WM8400_FLL_CONTROL_3, factors.n);
+
+	reg = wm8400_read(codec, WM8400_FLL_CONTROL_4);
+	reg &= WM8400_FLL_OUTDIV_MASK;
+	reg |= factors.outdiv;
+	wm8400_write(codec, WM8400_FLL_CONTROL_4, reg);
+
+	return 0;
+}
+
+/*
+ * Sets ADC and Voice DAC format.
+ */
+static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 audio1, audio3;
+
+	audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1);
+	audio3 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_3);
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		audio3 &= ~WM8400_AIF_MSTR1;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		audio3 |= WM8400_AIF_MSTR1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	audio1 &= ~WM8400_AIF_FMT_MASK;
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		audio1 |= WM8400_AIF_FMT_I2S;
+		audio1 &= ~WM8400_AIF_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		audio1 |= WM8400_AIF_FMT_RIGHTJ;
+		audio1 &= ~WM8400_AIF_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		audio1 |= WM8400_AIF_FMT_LEFTJ;
+		audio1 &= ~WM8400_AIF_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		audio1 |= WM8400_AIF_FMT_DSP;
+		audio1 &= ~WM8400_AIF_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		audio1 |= WM8400_AIF_FMT_DSP | WM8400_AIF_LRCLK_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1);
+	wm8400_write(codec, WM8400_AUDIO_INTERFACE_3, audio3);
+	return 0;
+}
+
+static int wm8400_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
+		int div_id, int div)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 reg;
+
+	switch (div_id) {
+	case WM8400_MCLK_DIV:
+		reg = wm8400_read(codec, WM8400_CLOCKING_2) &
+			~WM8400_MCLK_DIV_MASK;
+		wm8400_write(codec, WM8400_CLOCKING_2, reg | div);
+		break;
+	case WM8400_DACCLK_DIV:
+		reg = wm8400_read(codec, WM8400_CLOCKING_2) &
+			~WM8400_DAC_CLKDIV_MASK;
+		wm8400_write(codec, WM8400_CLOCKING_2, reg | div);
+		break;
+	case WM8400_ADCCLK_DIV:
+		reg = wm8400_read(codec, WM8400_CLOCKING_2) &
+			~WM8400_ADC_CLKDIV_MASK;
+		wm8400_write(codec, WM8400_CLOCKING_2, reg | div);
+		break;
+	case WM8400_BCLK_DIV:
+		reg = wm8400_read(codec, WM8400_CLOCKING_1) &
+			~WM8400_BCLK_DIV_MASK;
+		wm8400_write(codec, WM8400_CLOCKING_1, reg | div);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Set PCM DAI bit size and sample rate.
+ */
+static int wm8400_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params,
+	struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->card->codec;
+	u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1);
+
+	audio1 &= ~WM8400_AIF_WL_MASK;
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		audio1 |= WM8400_AIF_WL_20BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		audio1 |= WM8400_AIF_WL_24BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		audio1 |= WM8400_AIF_WL_32BITS;
+		break;
+	}
+
+	wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1);
+	return 0;
+}
+
+static int wm8400_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u16 val = wm8400_read(codec, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE;
+
+	if (mute)
+		wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE);
+	else
+		wm8400_write(codec, WM8400_DAC_CTRL, val);
+
+	return 0;
+}
+
+/* TODO: set bias for best performance at standby */
+static int wm8400_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	struct wm8400_priv *wm8400 = codec->private_data;
+	u16 val;
+	int ret;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		/* VMID=2*50k */
+		val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) &
+			~WM8400_VMID_MODE_MASK;
+		wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x2);
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->bias_level == SND_SOC_BIAS_OFF) {
+			ret = regulator_bulk_enable(ARRAY_SIZE(power),
+						    &power[0]);
+			if (ret != 0) {
+				dev_err(wm8400->wm8400->dev,
+					"Failed to enable regulators: %d\n",
+					ret);
+				return ret;
+			}
+
+			wm8400_write(codec, WM8400_POWER_MANAGEMENT_1,
+				     WM8400_CODEC_ENA | WM8400_SYSCLK_ENA);
+
+			/* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
+			wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
+				     WM8400_BUFDCOPEN | WM8400_POBCTRL);
+
+			msleep(50);
+
+			/* Enable VREF & VMID at 2x50k */
+			val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
+			val |= 0x2 | WM8400_VREF_ENA;
+			wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val);
+
+			/* Enable BUFIOEN */
+			wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
+				     WM8400_BUFDCOPEN | WM8400_POBCTRL |
+				     WM8400_BUFIOEN);
+
+			/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
+			wm8400_write(codec, WM8400_ANTIPOP2, WM8400_BUFIOEN);
+		}
+
+		/* VMID=2*300k */
+		val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) &
+			~WM8400_VMID_MODE_MASK;
+		wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x4);
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		/* Enable POBCTRL and SOFT_ST */
+		wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
+			WM8400_POBCTRL | WM8400_BUFIOEN);
+
+		/* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
+		wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
+			WM8400_BUFDCOPEN | WM8400_POBCTRL |
+			WM8400_BUFIOEN);
+
+		/* mute DAC */
+		val = wm8400_read(codec, WM8400_DAC_CTRL);
+		wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE);
+
+		/* Enable any disabled outputs */
+		val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
+		val |= WM8400_SPK_ENA | WM8400_OUT3_ENA |
+			WM8400_OUT4_ENA | WM8400_LOUT_ENA |
+			WM8400_ROUT_ENA;
+		wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val);
+
+		/* Disable VMID */
+		val &= ~WM8400_VMID_MODE_MASK;
+		wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val);
+
+		msleep(300);
+
+		/* Enable all output discharge bits */
+		wm8400_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE |
+			WM8400_DIS_RLINE | WM8400_DIS_OUT3 |
+			WM8400_DIS_OUT4 | WM8400_DIS_LOUT |
+			WM8400_DIS_ROUT);
+
+		/* Disable VREF */
+		val &= ~WM8400_VREF_ENA;
+		wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val);
+
+		/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
+		wm8400_write(codec, WM8400_ANTIPOP2, 0x0);
+
+		ret = regulator_bulk_disable(ARRAY_SIZE(power),
+					     &power[0]);
+		if (ret != 0)
+			return ret;
+
+		break;
+	}
+
+	codec->bias_level = level;
+	return 0;
+}
+
+#define WM8400_RATES SNDRV_PCM_RATE_8000_96000
+
+#define WM8400_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+	SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops wm8400_dai_ops = {
+	.hw_params = wm8400_hw_params,
+	.digital_mute = wm8400_mute,
+	.set_fmt = wm8400_set_dai_fmt,
+	.set_clkdiv = wm8400_set_dai_clkdiv,
+	.set_sysclk = wm8400_set_dai_sysclk,
+	.set_pll = wm8400_set_dai_pll,
+};
+
+/*
+ * The WM8400 supports 2 different and mutually exclusive DAI
+ * configurations.
+ *
+ * 1. ADC/DAC on Primary Interface
+ * 2. ADC on Primary Interface/DAC on secondary
+ */
+struct snd_soc_dai wm8400_dai = {
+/* ADC/DAC on primary */
+	.name = "WM8400 ADC/DAC Primary",
+	.id = 1,
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8400_RATES,
+		.formats = WM8400_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8400_RATES,
+		.formats = WM8400_FORMATS,
+	},
+	.ops = &wm8400_dai_ops,
+};
+EXPORT_SYMBOL_GPL(wm8400_dai);
+
+static int wm8400_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->card->codec;
+
+	wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+static int wm8400_resume(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->card->codec;
+
+	wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	return 0;
+}
+
+static struct snd_soc_codec *wm8400_codec;
+
+static int wm8400_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
+	int ret;
+
+	if (!wm8400_codec) {
+		dev_err(&pdev->dev, "wm8400 not yet discovered\n");
+		return -ENODEV;
+	}
+	codec = wm8400_codec;
+
+	socdev->card->codec = codec;
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to create pcms\n");
+		goto pcm_err;
+	}
+
+	wm8400_add_controls(codec);
+	wm8400_add_widgets(codec);
+
+	ret = snd_soc_init_card(socdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register card\n");
+		goto card_err;
+	}
+
+	return ret;
+
+card_err:
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+pcm_err:
+	return ret;
+}
+
+/* power down chip */
+static int wm8400_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8400 = {
+	.probe =	wm8400_probe,
+	.remove =	wm8400_remove,
+	.suspend =	wm8400_suspend,
+	.resume =	wm8400_resume,
+};
+
+static void wm8400_probe_deferred(struct work_struct *work)
+{
+	struct wm8400_priv *priv = container_of(work, struct wm8400_priv,
+						work);
+	struct snd_soc_codec *codec = &priv->codec;
+	int ret;
+
+	/* charge output caps */
+	wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	/* We're done, tell the subsystem. */
+	ret = snd_soc_register_codec(codec);
+	if (ret != 0) {
+		dev_err(priv->wm8400->dev,
+			"Failed to register codec: %d\n", ret);
+		goto err;
+	}
+
+	ret = snd_soc_register_dai(&wm8400_dai);
+	if (ret != 0) {
+		dev_err(priv->wm8400->dev,
+			"Failed to register DAI: %d\n", ret);
+		goto err_codec;
+	}
+
+	return;
+
+err_codec:
+	snd_soc_unregister_codec(codec);
+err:
+	wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
+}
+
+static int wm8400_codec_probe(struct platform_device *dev)
+{
+	struct wm8400_priv *priv;
+	int ret;
+	u16 reg;
+	struct snd_soc_codec *codec;
+
+	priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return -ENOMEM;
+
+	codec = &priv->codec;
+	codec->private_data = priv;
+	codec->control_data = dev->dev.driver_data;
+	priv->wm8400 = dev->dev.driver_data;
+
+	ret = regulator_bulk_get(priv->wm8400->dev,
+				 ARRAY_SIZE(power), &power[0]);
+	if (ret != 0) {
+		dev_err(&dev->dev, "Failed to get regulators: %d\n", ret);
+	        goto err;
+	}
+
+	codec->dev = &dev->dev;
+	wm8400_dai.dev = &dev->dev;
+
+	codec->name = "WM8400";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8400_read;
+	codec->write = wm8400_write;
+	codec->bias_level = SND_SOC_BIAS_OFF;
+	codec->set_bias_level = wm8400_set_bias_level;
+	codec->dai = &wm8400_dai;
+	codec->num_dai = 1;
+	codec->reg_cache_size = WM8400_REGISTER_COUNT;
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+	INIT_WORK(&priv->work, wm8400_probe_deferred);
+
+	wm8400_codec_reset(codec);
+
+	reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
+	wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA);
+
+	/* Latch volume update bits */
+	reg = wm8400_read(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME);
+	wm8400_write(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
+		     reg & WM8400_IPVU);
+	reg = wm8400_read(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME);
+	wm8400_write(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
+		     reg & WM8400_IPVU);
+
+	wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
+	wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
+
+	wm8400_codec = codec;
+
+	if (!schedule_work(&priv->work)) {
+		ret = -EINVAL;
+		goto err_regulator;
+	}
+
+	return 0;
+
+err_regulator:
+	wm8400_codec = NULL;
+	regulator_bulk_free(ARRAY_SIZE(power), power);
+err:
+	kfree(priv);
+	return ret;
+}
+
+static int __exit wm8400_codec_remove(struct platform_device *dev)
+{
+	struct wm8400_priv *priv = wm8400_codec->private_data;
+	u16 reg;
+
+	snd_soc_unregister_dai(&wm8400_dai);
+	snd_soc_unregister_codec(wm8400_codec);
+
+	reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1);
+	wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1,
+		     reg & (~WM8400_CODEC_ENA));
+
+	regulator_bulk_free(ARRAY_SIZE(power), power);
+	kfree(priv);
+
+	wm8400_codec = NULL;
+
+	return 0;
+}
+
+static struct platform_driver wm8400_codec_driver = {
+	.driver = {
+		.name = "wm8400-codec",
+		.owner = THIS_MODULE,
+	},
+	.probe = wm8400_codec_probe,
+	.remove	= __exit_p(wm8400_codec_remove),
+};
+
+static int __init wm8400_codec_init(void)
+{
+	return platform_driver_register(&wm8400_codec_driver);
+}
+module_init(wm8400_codec_init);
+
+static void __exit wm8400_codec_exit(void)
+{
+	platform_driver_unregister(&wm8400_codec_driver);
+}
+module_exit(wm8400_codec_exit);
+
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400);
+
+MODULE_DESCRIPTION("ASoC WM8400 driver");
+MODULE_AUTHOR("Mark Brown");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8400-codec");
diff --git a/sound/soc/codecs/wm8400.h b/sound/soc/codecs/wm8400.h
new file mode 100644
index 0000000..79c5934
--- /dev/null
+++ b/sound/soc/codecs/wm8400.h
@@ -0,0 +1,62 @@
+/*
+ * wm8400.h  --  audio driver for WM8400
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef _WM8400_CODEC_H
+#define _WM8400_CODEC_H
+
+#define WM8400_MCLK_DIV 0
+#define WM8400_DACCLK_DIV 1
+#define WM8400_ADCCLK_DIV 2
+#define WM8400_BCLK_DIV 3
+
+#define WM8400_MCLK_DIV_1 0x400
+#define WM8400_MCLK_DIV_2 0x800
+
+#define WM8400_DAC_CLKDIV_1    0x00
+#define WM8400_DAC_CLKDIV_1_5  0x04
+#define WM8400_DAC_CLKDIV_2    0x08
+#define WM8400_DAC_CLKDIV_3    0x0c
+#define WM8400_DAC_CLKDIV_4    0x10
+#define WM8400_DAC_CLKDIV_5_5  0x14
+#define WM8400_DAC_CLKDIV_6    0x18
+
+#define WM8400_ADC_CLKDIV_1    0x00
+#define WM8400_ADC_CLKDIV_1_5  0x20
+#define WM8400_ADC_CLKDIV_2    0x40
+#define WM8400_ADC_CLKDIV_3    0x60
+#define WM8400_ADC_CLKDIV_4    0x80
+#define WM8400_ADC_CLKDIV_5_5  0xa0
+#define WM8400_ADC_CLKDIV_6    0xc0
+
+
+#define WM8400_BCLK_DIV_1                       (0x0 << 1)
+#define WM8400_BCLK_DIV_1_5                     (0x1 << 1)
+#define WM8400_BCLK_DIV_2                       (0x2 << 1)
+#define WM8400_BCLK_DIV_3                       (0x3 << 1)
+#define WM8400_BCLK_DIV_4                       (0x4 << 1)
+#define WM8400_BCLK_DIV_5_5                     (0x5 << 1)
+#define WM8400_BCLK_DIV_6                       (0x6 << 1)
+#define WM8400_BCLK_DIV_8                       (0x7 << 1)
+#define WM8400_BCLK_DIV_11                      (0x8 << 1)
+#define WM8400_BCLK_DIV_12                      (0x9 << 1)
+#define WM8400_BCLK_DIV_16                      (0xA << 1)
+#define WM8400_BCLK_DIV_22                      (0xB << 1)
+#define WM8400_BCLK_DIV_24                      (0xC << 1)
+#define WM8400_BCLK_DIV_32                      (0xD << 1)
+#define WM8400_BCLK_DIV_44                      (0xE << 1)
+#define WM8400_BCLK_DIV_48                      (0xF << 1)
+
+extern struct snd_soc_dai wm8400_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8400;
+
+#endif
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 40f8238..6a4cea0 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -171,22 +171,6 @@
 SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1),
 };
 
-/* add non dapm controls */
-static int wm8510_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8510_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&wm8510_snd_controls[i], codec,
-					NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 /* Speaker Output Mixer */
 static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = {
 SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0),
@@ -352,7 +336,7 @@
 		return 0;
 	}
 
-	pll_factors(freq_out*8, freq_in);
+	pll_factors(freq_out*4, freq_in);
 
 	wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n);
 	wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18);
@@ -383,7 +367,7 @@
 		wm8510_write(codec, WM8510_GPIO, reg | div);
 		break;
 	case WM8510_MCLKDIV:
-		reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1f;
+		reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x11f;
 		wm8510_write(codec, WM8510_CLOCK, reg | div);
 		break;
 	case WM8510_ADCCLK:
@@ -468,7 +452,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f;
 	u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1;
 
@@ -570,6 +554,14 @@
 #define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
+static struct snd_soc_dai_ops wm8510_dai_ops = {
+	.hw_params	= wm8510_pcm_hw_params,
+	.digital_mute	= wm8510_mute,
+	.set_fmt	= wm8510_set_dai_fmt,
+	.set_clkdiv	= wm8510_set_dai_clkdiv,
+	.set_pll	= wm8510_set_dai_pll,
+};
+
 struct snd_soc_dai wm8510_dai = {
 	.name = "WM8510 HiFi",
 	.playback = {
@@ -584,20 +576,14 @@
 		.channels_max = 2,
 		.rates = WM8510_RATES,
 		.formats = WM8510_FORMATS,},
-	.ops = {
-		.hw_params = wm8510_pcm_hw_params,
-		.digital_mute = wm8510_mute,
-		.set_fmt = wm8510_set_dai_fmt,
-		.set_clkdiv = wm8510_set_dai_clkdiv,
-		.set_pll = wm8510_set_dai_pll,
-	},
+	.ops = &wm8510_dai_ops,
 };
 EXPORT_SYMBOL_GPL(wm8510_dai);
 
 static int wm8510_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -606,7 +592,7 @@
 static int wm8510_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u8 data[2];
 	u16 *cache = codec->reg_cache;
@@ -628,7 +614,7 @@
  */
 static int wm8510_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret = 0;
 
 	codec->name = "WM8510";
@@ -656,7 +642,8 @@
 	/* power on device */
 	codec->bias_level = SND_SOC_BIAS_OFF;
 	wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-	wm8510_add_controls(codec);
+	snd_soc_add_controls(codec, wm8510_snd_controls,
+				ARRAY_SIZE(wm8510_snd_controls));
 	wm8510_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -685,7 +672,7 @@
 			    const struct i2c_device_id *id)
 {
 	struct snd_soc_device *socdev = wm8510_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	i2c_set_clientdata(i2c, codec);
@@ -766,7 +753,7 @@
 static int __devinit wm8510_spi_probe(struct spi_device *spi)
 {
 	struct snd_soc_device *socdev = wm8510_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	codec->control_data = spi;
@@ -832,7 +819,7 @@
 	if (codec == NULL)
 		return -ENOMEM;
 
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -862,7 +849,7 @@
 static int wm8510_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec->control_data)
 		wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index d004e58..442ea6f 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -1,7 +1,7 @@
 /*
  * wm8580.c  --  WM8580 ALSA Soc Audio driver
  *
- * Copyright 2008 Wolfson Microelectronics PLC.
+ * Copyright 2008, 2009 Wolfson Microelectronics PLC.
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -35,19 +35,6 @@
 
 #include "wm8580.h"
 
-#define WM8580_VERSION "0.1"
-
-struct pll_state {
-	unsigned int in;
-	unsigned int out;
-};
-
-/* codec private data */
-struct wm8580_priv {
-	struct pll_state a;
-	struct pll_state b;
-};
-
 /* WM8580 register space */
 #define WM8580_PLLA1                         0x00
 #define WM8580_PLLA2                         0x01
@@ -102,6 +89,8 @@
 #define WM8580_READBACK                      0x34
 #define WM8580_RESET                         0x35
 
+#define WM8580_MAX_REGISTER                  0x35
+
 /* PLLB4 (register 7h) */
 #define WM8580_PLLB4_MCLKOUTSRC_MASK   0x60
 #define WM8580_PLLB4_MCLKOUTSRC_PLLA   0x20
@@ -193,6 +182,20 @@
 	0x0000, 0x0000 /*R53*/
 };
 
+struct pll_state {
+	unsigned int in;
+	unsigned int out;
+};
+
+/* codec private data */
+struct wm8580_priv {
+	struct snd_soc_codec codec;
+	u16 reg_cache[WM8580_MAX_REGISTER + 1];
+	struct pll_state a;
+	struct pll_state b;
+};
+
+
 /*
  * read wm8580 register cache
  */
@@ -200,7 +203,7 @@
 	unsigned int reg)
 {
 	u16 *cache = codec->reg_cache;
-	BUG_ON(reg > ARRAY_SIZE(wm8580_reg));
+	BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
 	return cache[reg];
 }
 
@@ -223,7 +226,7 @@
 {
 	u8 data[2];
 
-	BUG_ON(reg > ARRAY_SIZE(wm8580_reg));
+	BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
 
 	/* Registers are 9 bits wide */
 	value &= 0x1ff;
@@ -330,20 +333,6 @@
 SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
 };
 
-/* Add non-DAPM controls */
-static int wm8580_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8580_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&wm8580_snd_controls[i],
-					       codec, NULL));
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
 static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {
 SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1),
 SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1),
@@ -553,7 +542,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id);
 
 	paifb &= ~WM8580_AIF_LENGTH_MASK;
@@ -771,8 +760,22 @@
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 	case SND_SOC_BIAS_PREPARE:
-	case SND_SOC_BIAS_STANDBY:
 		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->bias_level == SND_SOC_BIAS_OFF) {
+			/* Power up and get individual control of the DACs */
+			reg = wm8580_read(codec, WM8580_PWRDN1);
+			reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
+			wm8580_write(codec, WM8580_PWRDN1, reg);
+
+			/* Make VMID high impedence */
+			reg = wm8580_read(codec,  WM8580_ADC_CONTROL1);
+			reg &= ~0x100;
+			wm8580_write(codec, WM8580_ADC_CONTROL1, reg);
+		}
+		break;
+
 	case SND_SOC_BIAS_OFF:
 		reg = wm8580_read(codec, WM8580_PWRDN1);
 		wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
@@ -785,6 +788,21 @@
 #define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
+static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
+	.hw_params	= wm8580_paif_hw_params,
+	.set_fmt	= wm8580_set_paif_dai_fmt,
+	.set_clkdiv	= wm8580_set_dai_clkdiv,
+	.set_pll	= wm8580_set_dai_pll,
+	.digital_mute	= wm8580_digital_mute,
+};
+
+static struct snd_soc_dai_ops wm8580_dai_ops_capture = {
+	.hw_params	= wm8580_paif_hw_params,
+	.set_fmt	= wm8580_set_paif_dai_fmt,
+	.set_clkdiv	= wm8580_set_dai_clkdiv,
+	.set_pll	= wm8580_set_dai_pll,
+};
+
 struct snd_soc_dai wm8580_dai[] = {
 	{
 		.name = "WM8580 PAIFRX",
@@ -796,13 +814,7 @@
 			.rates = SNDRV_PCM_RATE_8000_192000,
 			.formats = WM8580_FORMATS,
 		},
-		.ops = {
-			 .hw_params = wm8580_paif_hw_params,
-			 .set_fmt = wm8580_set_paif_dai_fmt,
-			 .set_clkdiv = wm8580_set_dai_clkdiv,
-			 .set_pll = wm8580_set_dai_pll,
-			 .digital_mute = wm8580_digital_mute,
-		 },
+		.ops = &wm8580_dai_ops_playback,
 	},
 	{
 		.name = "WM8580 PAIFTX",
@@ -814,109 +826,168 @@
 			.rates = SNDRV_PCM_RATE_8000_192000,
 			.formats = WM8580_FORMATS,
 		},
-		.ops = {
-			 .hw_params = wm8580_paif_hw_params,
-			 .set_fmt = wm8580_set_paif_dai_fmt,
-			 .set_clkdiv = wm8580_set_dai_clkdiv,
-			 .set_pll = wm8580_set_dai_pll,
-		 },
+		.ops = &wm8580_dai_ops_capture,
 	},
 };
 EXPORT_SYMBOL_GPL(wm8580_dai);
 
-/*
- * initialise the WM8580 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8580_init(struct snd_soc_device *socdev)
+static struct snd_soc_codec *wm8580_codec;
+
+static int wm8580_probe(struct platform_device *pdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
 	int ret = 0;
 
-	codec->name = "WM8580";
-	codec->owner = THIS_MODULE;
-	codec->read = wm8580_read_reg_cache;
-	codec->write = wm8580_write;
-	codec->set_bias_level = wm8580_set_bias_level;
-	codec->dai = wm8580_dai;
-	codec->num_dai = ARRAY_SIZE(wm8580_dai);
-	codec->reg_cache_size = ARRAY_SIZE(wm8580_reg);
-	codec->reg_cache = kmemdup(wm8580_reg, sizeof(wm8580_reg),
-				   GFP_KERNEL);
+	if (wm8580_codec == NULL) {
+		dev_err(&pdev->dev, "Codec device not registered\n");
+		return -ENODEV;
+	}
 
-	if (codec->reg_cache == NULL)
-		return -ENOMEM;
-
-	/* Get the codec into a known state */
-	wm8580_write(codec, WM8580_RESET, 0);
-
-	/* Power up and get individual control of the DACs */
-	wm8580_write(codec, WM8580_PWRDN1, wm8580_read(codec, WM8580_PWRDN1) &
-		     ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD));
-
-	/* Make VMID high impedence */
-	wm8580_write(codec, WM8580_ADC_CONTROL1,
-		     wm8580_read(codec,  WM8580_ADC_CONTROL1) & ~0x100);
+	socdev->card->codec = wm8580_codec;
+	codec = wm8580_codec;
 
 	/* register pcms */
-	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1,
-			       SNDRV_DEFAULT_STR1);
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
 	if (ret < 0) {
-		printk(KERN_ERR "wm8580: failed to create pcms\n");
+		dev_err(codec->dev, "failed to create pcms: %d\n", ret);
 		goto pcm_err;
 	}
 
-	wm8580_add_controls(codec);
+	snd_soc_add_controls(codec, wm8580_snd_controls,
+			     ARRAY_SIZE(wm8580_snd_controls));
 	wm8580_add_widgets(codec);
-
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
-		printk(KERN_ERR "wm8580: failed to register card\n");
+		dev_err(codec->dev, "failed to register card: %d\n", ret);
 		goto card_err;
 	}
+
 	return ret;
 
 card_err:
 	snd_soc_free_pcms(socdev);
 	snd_soc_dapm_free(socdev);
 pcm_err:
-	kfree(codec->reg_cache);
 	return ret;
 }
 
-/* If the i2c layer weren't so broken, we could pass this kind of data
-   around */
-static struct snd_soc_device *wm8580_socdev;
+/* power down chip */
+static int wm8580_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8580 = {
+	.probe = 	wm8580_probe,
+	.remove = 	wm8580_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
+
+static int wm8580_register(struct wm8580_priv *wm8580)
+{
+	int ret, i;
+	struct snd_soc_codec *codec = &wm8580->codec;
+
+	if (wm8580_codec) {
+		dev_err(codec->dev, "Another WM8580 is registered\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	codec->private_data = wm8580;
+	codec->name = "WM8580";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8580_read_reg_cache;
+	codec->write = wm8580_write;
+	codec->bias_level = SND_SOC_BIAS_OFF;
+	codec->set_bias_level = wm8580_set_bias_level;
+	codec->dai = wm8580_dai;
+	codec->num_dai = ARRAY_SIZE(wm8580_dai);
+	codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache);
+	codec->reg_cache = &wm8580->reg_cache;
+
+	memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
+
+	/* Get the codec into a known state */
+	ret = wm8580_write(codec, WM8580_RESET, 0);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to reset codec: %d\n", ret);
+		goto err;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
+		wm8580_dai[i].dev = codec->dev;
+
+	wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	wm8580_codec = codec;
+
+	ret = snd_soc_register_codec(codec);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+		goto err;
+	}
+
+	ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+		goto err_codec;
+	}
+
+	return 0;
+
+err_codec:
+	snd_soc_unregister_codec(codec);
+err:
+	kfree(wm8580);
+	return ret;
+}
+
+static void wm8580_unregister(struct wm8580_priv *wm8580)
+{
+	wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF);
+	snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
+	snd_soc_unregister_codec(&wm8580->codec);
+	kfree(wm8580);
+	wm8580_codec = NULL;
+}
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-/*
- * WM8580 2 wire address is determined by GPIO5
- * state during powerup.
- *    low  = 0x1a
- *    high = 0x1b
- */
-
 static int wm8580_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
-	struct snd_soc_device *socdev = wm8580_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
-	int ret;
+	struct wm8580_priv *wm8580;
+	struct snd_soc_codec *codec;
 
-	i2c_set_clientdata(i2c, codec);
+	wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);
+	if (wm8580 == NULL)
+		return -ENOMEM;
+
+	codec = &wm8580->codec;
+	codec->hw_write = (hw_write_t)i2c_master_send;
+
+	i2c_set_clientdata(i2c, wm8580);
 	codec->control_data = i2c;
 
-	ret = wm8580_init(socdev);
-	if (ret < 0)
-		dev_err(&i2c->dev, "failed to initialise WM8580\n");
-	return ret;
+	codec->dev = &i2c->dev;
+
+	return wm8580_register(wm8580);
 }
 
 static int wm8580_i2c_remove(struct i2c_client *client)
 {
-	struct snd_soc_codec *codec = i2c_get_clientdata(client);
-	kfree(codec->reg_cache);
+	struct wm8580_priv *wm8580 = i2c_get_clientdata(client);
+	wm8580_unregister(wm8580);
 	return 0;
 }
 
@@ -928,129 +999,35 @@
 
 static struct i2c_driver wm8580_i2c_driver = {
 	.driver = {
-		.name = "WM8580 I2C Codec",
+		.name = "wm8580",
 		.owner = THIS_MODULE,
 	},
 	.probe =    wm8580_i2c_probe,
 	.remove =   wm8580_i2c_remove,
 	.id_table = wm8580_i2c_id,
 };
-
-static int wm8580_add_i2c_device(struct platform_device *pdev,
-				 const struct wm8580_setup_data *setup)
-{
-	struct i2c_board_info info;
-	struct i2c_adapter *adapter;
-	struct i2c_client *client;
-	int ret;
-
-	ret = i2c_add_driver(&wm8580_i2c_driver);
-	if (ret != 0) {
-		dev_err(&pdev->dev, "can't add i2c driver\n");
-		return ret;
-	}
-
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	info.addr = setup->i2c_address;
-	strlcpy(info.type, "wm8580", I2C_NAME_SIZE);
-
-	adapter = i2c_get_adapter(setup->i2c_bus);
-	if (!adapter) {
-		dev_err(&pdev->dev, "can't get i2c adapter %d\n",
-			setup->i2c_bus);
-		goto err_driver;
-	}
-
-	client = i2c_new_device(adapter, &info);
-	i2c_put_adapter(adapter);
-	if (!client) {
-		dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
-			(unsigned int)info.addr);
-		goto err_driver;
-	}
-
-	return 0;
-
-err_driver:
-	i2c_del_driver(&wm8580_i2c_driver);
-	return -ENODEV;
-}
 #endif
 
-static int wm8580_probe(struct platform_device *pdev)
-{
-	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct wm8580_setup_data *setup;
-	struct snd_soc_codec *codec;
-	struct wm8580_priv *wm8580;
-	int ret = 0;
-
-	pr_info("WM8580 Audio Codec %s\n", WM8580_VERSION);
-
-	setup = socdev->codec_data;
-	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-	if (codec == NULL)
-		return -ENOMEM;
-
-	wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);
-	if (wm8580 == NULL) {
-		kfree(codec);
-		return -ENOMEM;
-	}
-
-	codec->private_data = wm8580;
-	socdev->codec = codec;
-	mutex_init(&codec->mutex);
-	INIT_LIST_HEAD(&codec->dapm_widgets);
-	INIT_LIST_HEAD(&codec->dapm_paths);
-	wm8580_socdev = socdev;
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	if (setup->i2c_address) {
-		codec->hw_write = (hw_write_t)i2c_master_send;
-		ret = wm8580_add_i2c_device(pdev, setup);
-	}
-#else
-		/* Add other interfaces here */
-#endif
-	return ret;
-}
-
-/* power down chip */
-static int wm8580_remove(struct platform_device *pdev)
-{
-	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
-
-	if (codec->control_data)
-		wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF);
-	snd_soc_free_pcms(socdev);
-	snd_soc_dapm_free(socdev);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	i2c_unregister_device(codec->control_data);
-	i2c_del_driver(&wm8580_i2c_driver);
-#endif
-	kfree(codec->private_data);
-	kfree(codec);
-
-	return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8580 = {
-	.probe = 	wm8580_probe,
-	.remove = 	wm8580_remove,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
-
 static int __init wm8580_modinit(void)
 {
-	return snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
+	int ret;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	ret = i2c_add_driver(&wm8580_i2c_driver);
+	if (ret != 0) {
+		pr_err("Failed to register WM8580 I2C driver: %d\n", ret);
+	}
+#endif
+
+	return 0;
 }
 module_init(wm8580_modinit);
 
 static void __exit wm8580_exit(void)
 {
-	snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_driver(&wm8580_i2c_driver);
+#endif
 }
 module_exit(wm8580_exit);
 
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h
index 09e4422..0dfb5dd 100644
--- a/sound/soc/codecs/wm8580.h
+++ b/sound/soc/codecs/wm8580.h
@@ -28,11 +28,6 @@
 #define WM8580_CLKSRC_OSC  4
 #define WM8580_CLKSRC_NONE 5
 
-struct wm8580_setup_data {
-	int i2c_bus;
-	unsigned short i2c_address;
-};
-
 #define WM8580_DAI_PAIFRX 0
 #define WM8580_DAI_PAIFTX 1
 
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 80b1198..e7ff212 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -47,7 +47,7 @@
 	unsigned int reg)
 {
 	u16 *cache = codec->reg_cache;
-	BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
+	BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
 	return cache[reg];
 }
 
@@ -55,7 +55,7 @@
 	u16 reg, unsigned int value)
 {
 	u16 *cache = codec->reg_cache;
-	BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
+	BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
 	cache[reg] = value;
 }
 
@@ -92,21 +92,6 @@
 SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0),
 };
 
-static int wm8728_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&wm8728_snd_controls[i],
-						codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 /*
  * DAPM controls.
  */
@@ -152,7 +137,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL);
 
 	dac &= ~0x18;
@@ -259,6 +244,12 @@
 #define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
+static struct snd_soc_dai_ops wm8728_dai_ops = {
+	.hw_params	= wm8728_hw_params,
+	.digital_mute	= wm8728_mute,
+	.set_fmt	= wm8728_set_dai_fmt,
+};
+
 struct snd_soc_dai wm8728_dai = {
 	.name = "WM8728",
 	.playback = {
@@ -268,18 +259,14 @@
 		.rates = WM8728_RATES,
 		.formats = WM8728_FORMATS,
 	},
-	.ops = {
-		 .hw_params = wm8728_hw_params,
-		 .digital_mute = wm8728_mute,
-		 .set_fmt = wm8728_set_dai_fmt,
-	}
+	.ops = &wm8728_dai_ops,
 };
 EXPORT_SYMBOL_GPL(wm8728_dai);
 
 static int wm8728_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -289,7 +276,7 @@
 static int wm8728_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm8728_set_bias_level(codec, codec->suspend_bias_level);
 
@@ -302,7 +289,7 @@
  */
 static int wm8728_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret = 0;
 
 	codec->name = "WM8728";
@@ -330,7 +317,8 @@
 	/* power on device */
 	wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	wm8728_add_controls(codec);
+	snd_soc_add_controls(codec, wm8728_snd_controls,
+				ARRAY_SIZE(wm8728_snd_controls));
 	wm8728_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -363,7 +351,7 @@
 			    const struct i2c_device_id *id)
 {
 	struct snd_soc_device *socdev = wm8728_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	i2c_set_clientdata(i2c, codec);
@@ -444,7 +432,7 @@
 static int __devinit wm8728_spi_probe(struct spi_device *spi)
 {
 	struct snd_soc_device *socdev = wm8728_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	codec->control_data = spi;
@@ -508,7 +496,7 @@
 	if (codec == NULL)
 		return -ENOMEM;
 
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -541,7 +529,7 @@
 static int wm8728_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec->control_data)
 		wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index c444b9f..e043e3f 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -29,15 +29,20 @@
 
 #include "wm8731.h"
 
-#define WM8731_VERSION "0.13"
-
+static struct snd_soc_codec *wm8731_codec;
 struct snd_soc_codec_device soc_codec_dev_wm8731;
 
 /* codec private data */
 struct wm8731_priv {
+	struct snd_soc_codec codec;
+	u16 reg_cache[WM8731_CACHEREGNUM];
 	unsigned int sysclk;
 };
 
+#ifdef CONFIG_SPI_MASTER
+static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
+#endif
+
 /*
  * wm8731 register cache
  * We can't read the WM8731 register space when we are
@@ -129,22 +134,6 @@
 SOC_ENUM("Playback De-emphasis", wm8731_enum[1]),
 };
 
-/* add non dapm controls */
-static int wm8731_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&wm8731_snd_controls[i],
-						codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 /* Output Mixer */
 static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = {
 SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
@@ -269,7 +258,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8731_priv *wm8731 = codec->private_data;
 	u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3;
 	int i = get_coeff(wm8731->sysclk, params_rate(params));
@@ -299,7 +288,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	/* set active */
 	wm8731_write(codec, WM8731_ACTIVE, 0x0001);
@@ -312,7 +301,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	/* deactivate */
 	if (!codec->active) {
@@ -414,21 +403,19 @@
 static int wm8731_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
-	u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f;
+	u16 reg;
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		/* vref/mid, osc on, dac unmute */
-		wm8731_write(codec, WM8731_PWR, reg);
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		break;
 	case SND_SOC_BIAS_STANDBY:
-		/* everything off except vref/vmid, */
+		/* Clear PWROFF, gate CLKOUT, everything else as-is */
+		reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f;
 		wm8731_write(codec, WM8731_PWR, reg | 0x0040);
 		break;
 	case SND_SOC_BIAS_OFF:
-		/* everything off, dac mute, inactive */
 		wm8731_write(codec, WM8731_ACTIVE, 0x0);
 		wm8731_write(codec, WM8731_PWR, 0xffff);
 		break;
@@ -446,6 +433,15 @@
 #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
+static struct snd_soc_dai_ops wm8731_dai_ops = {
+	.prepare	= wm8731_pcm_prepare,
+	.hw_params	= wm8731_hw_params,
+	.shutdown	= wm8731_shutdown,
+	.digital_mute	= wm8731_mute,
+	.set_sysclk	= wm8731_set_dai_sysclk,
+	.set_fmt	= wm8731_set_dai_fmt,
+};
+
 struct snd_soc_dai wm8731_dai = {
 	.name = "WM8731",
 	.playback = {
@@ -460,21 +456,14 @@
 		.channels_max = 2,
 		.rates = WM8731_RATES,
 		.formats = WM8731_FORMATS,},
-	.ops = {
-		.prepare = wm8731_pcm_prepare,
-		.hw_params = wm8731_hw_params,
-		.shutdown = wm8731_shutdown,
-		.digital_mute = wm8731_mute,
-		.set_sysclk = wm8731_set_dai_sysclk,
-		.set_fmt = wm8731_set_dai_fmt,
-	}
+	.ops = &wm8731_dai_ops,
 };
 EXPORT_SYMBOL_GPL(wm8731_dai);
 
 static int wm8731_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm8731_write(codec, WM8731_ACTIVE, 0x0);
 	wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -484,7 +473,7 @@
 static int wm8731_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u8 data[2];
 	u16 *cache = codec->reg_cache;
@@ -500,54 +489,33 @@
 	return 0;
 }
 
-/*
- * initialise the WM8731 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8731_init(struct snd_soc_device *socdev)
+static int wm8731_probe(struct platform_device *pdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
-	int reg, ret = 0;
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
+	int ret = 0;
 
-	codec->name = "WM8731";
-	codec->owner = THIS_MODULE;
-	codec->read = wm8731_read_reg_cache;
-	codec->write = wm8731_write;
-	codec->set_bias_level = wm8731_set_bias_level;
-	codec->dai = &wm8731_dai;
-	codec->num_dai = 1;
-	codec->reg_cache_size = ARRAY_SIZE(wm8731_reg);
-	codec->reg_cache = kmemdup(wm8731_reg, sizeof(wm8731_reg), GFP_KERNEL);
-	if (codec->reg_cache == NULL)
-		return -ENOMEM;
+	if (wm8731_codec == NULL) {
+		dev_err(&pdev->dev, "Codec device not registered\n");
+		return -ENODEV;
+	}
 
-	wm8731_reset(codec);
+	socdev->card->codec = wm8731_codec;
+	codec = wm8731_codec;
 
 	/* register pcms */
 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
 	if (ret < 0) {
-		printk(KERN_ERR "wm8731: failed to create pcms\n");
+		dev_err(codec->dev, "failed to create pcms: %d\n", ret);
 		goto pcm_err;
 	}
 
-	/* power on device */
-	wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-	/* set the update bits */
-	reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
-	wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100);
-	reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V);
-	wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100);
-	reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
-	wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100);
-	reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
-	wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100);
-
-	wm8731_add_controls(codec);
+	snd_soc_add_controls(codec, wm8731_snd_controls,
+			     ARRAY_SIZE(wm8731_snd_controls));
 	wm8731_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
-		printk(KERN_ERR "wm8731: failed to register card\n");
+		dev_err(codec->dev, "failed to register card: %d\n", ret);
 		goto card_err;
 	}
 
@@ -557,133 +525,109 @@
 	snd_soc_free_pcms(socdev);
 	snd_soc_dapm_free(socdev);
 pcm_err:
-	kfree(codec->reg_cache);
 	return ret;
 }
 
-static struct snd_soc_device *wm8731_socdev;
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-/*
- * WM8731 2 wire address is determined by GPIO5
- * state during powerup.
- *    low  = 0x1a
- *    high = 0x1b
- */
-
-static int wm8731_i2c_probe(struct i2c_client *i2c,
-			    const struct i2c_device_id *id)
+/* power down chip */
+static int wm8731_remove(struct platform_device *pdev)
 {
-	struct snd_soc_device *socdev = wm8731_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
-	int ret;
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 
-	i2c_set_clientdata(i2c, codec);
-	codec->control_data = i2c;
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
 
-	ret = wm8731_init(socdev);
-	if (ret < 0)
-		pr_err("failed to initialise WM8731\n");
-
-	return ret;
-}
-
-static int wm8731_i2c_remove(struct i2c_client *client)
-{
-	struct snd_soc_codec *codec = i2c_get_clientdata(client);
-	kfree(codec->reg_cache);
 	return 0;
 }
 
-static const struct i2c_device_id wm8731_i2c_id[] = {
-	{ "wm8731", 0 },
-	{ }
+struct snd_soc_codec_device soc_codec_dev_wm8731 = {
+	.probe = 	wm8731_probe,
+	.remove = 	wm8731_remove,
+	.suspend = 	wm8731_suspend,
+	.resume =	wm8731_resume,
 };
-MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
 
-static struct i2c_driver wm8731_i2c_driver = {
-	.driver = {
-		.name = "WM8731 I2C Codec",
-		.owner = THIS_MODULE,
-	},
-	.probe =    wm8731_i2c_probe,
-	.remove =   wm8731_i2c_remove,
-	.id_table = wm8731_i2c_id,
-};
-
-static int wm8731_add_i2c_device(struct platform_device *pdev,
-				 const struct wm8731_setup_data *setup)
+static int wm8731_register(struct wm8731_priv *wm8731)
 {
-	struct i2c_board_info info;
-	struct i2c_adapter *adapter;
-	struct i2c_client *client;
 	int ret;
+	struct snd_soc_codec *codec = &wm8731->codec;
+	u16 reg;
 
-	ret = i2c_add_driver(&wm8731_i2c_driver);
-	if (ret != 0) {
-		dev_err(&pdev->dev, "can't add i2c driver\n");
+	if (wm8731_codec) {
+		dev_err(codec->dev, "Another WM8731 is registered\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	codec->private_data = wm8731;
+	codec->name = "WM8731";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8731_read_reg_cache;
+	codec->write = wm8731_write;
+	codec->bias_level = SND_SOC_BIAS_OFF;
+	codec->set_bias_level = wm8731_set_bias_level;
+	codec->dai = &wm8731_dai;
+	codec->num_dai = 1;
+	codec->reg_cache_size = WM8731_CACHEREGNUM;
+	codec->reg_cache = &wm8731->reg_cache;
+
+	memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
+
+	ret = wm8731_reset(codec);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to issue reset\n");
 		return ret;
 	}
 
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	info.addr = setup->i2c_address;
-	strlcpy(info.type, "wm8731", I2C_NAME_SIZE);
+	wm8731_dai.dev = codec->dev;
 
-	adapter = i2c_get_adapter(setup->i2c_bus);
-	if (!adapter) {
-		dev_err(&pdev->dev, "can't get i2c adapter %d\n",
-			setup->i2c_bus);
-		goto err_driver;
+	wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	/* Latch the update bits */
+	reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
+	wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100);
+	reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V);
+	wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100);
+	reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
+	wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100);
+	reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
+	wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100);
+
+	/* Disable bypass path by default */
+	reg = wm8731_read_reg_cache(codec, WM8731_APANA);
+	wm8731_write(codec, WM8731_APANA, reg & ~0x4);
+
+	wm8731_codec = codec;
+
+	ret = snd_soc_register_codec(codec);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+		return ret;
 	}
 
-	client = i2c_new_device(adapter, &info);
-	i2c_put_adapter(adapter);
-	if (!client) {
-		dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
-			(unsigned int)info.addr);
-		goto err_driver;
+	ret = snd_soc_register_dai(&wm8731_dai);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+		snd_soc_unregister_codec(codec);
+		return ret;
 	}
 
 	return 0;
-
-err_driver:
-	i2c_del_driver(&wm8731_i2c_driver);
-	return -ENODEV;
 }
-#endif
+
+static void wm8731_unregister(struct wm8731_priv *wm8731)
+{
+	wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
+	snd_soc_unregister_dai(&wm8731_dai);
+	snd_soc_unregister_codec(&wm8731->codec);
+	kfree(wm8731);
+	wm8731_codec = NULL;
+}
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8731_spi_probe(struct spi_device *spi)
-{
-	struct snd_soc_device *socdev = wm8731_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
-	int ret;
-
-	codec->control_data = spi;
-
-	ret = wm8731_init(socdev);
-	if (ret < 0)
-		dev_err(&spi->dev, "failed to initialise WM8731\n");
-
-	return ret;
-}
-
-static int __devexit wm8731_spi_remove(struct spi_device *spi)
-{
-	return 0;
-}
-
-static struct spi_driver wm8731_spi_driver = {
-	.driver = {
-		.name	= "wm8731",
-		.bus	= &spi_bus_type,
-		.owner	= THIS_MODULE,
-	},
-	.probe		= wm8731_spi_probe,
-	.remove		= __devexit_p(wm8731_spi_remove),
-};
-
 static int wm8731_spi_write(struct spi_device *spi, const char *data, int len)
 {
 	struct spi_transfer t;
@@ -707,101 +651,121 @@
 
 	return len;
 }
-#endif /* CONFIG_SPI_MASTER */
 
-static int wm8731_probe(struct platform_device *pdev)
+static int __devinit wm8731_spi_probe(struct spi_device *spi)
 {
-	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct wm8731_setup_data *setup;
 	struct snd_soc_codec *codec;
 	struct wm8731_priv *wm8731;
-	int ret = 0;
-
-	pr_info("WM8731 Audio Codec %s", WM8731_VERSION);
-
-	setup = socdev->codec_data;
-	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-	if (codec == NULL)
-		return -ENOMEM;
 
 	wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
-	if (wm8731 == NULL) {
-		kfree(codec);
+	if (wm8731 == NULL)
 		return -ENOMEM;
-	}
 
-	codec->private_data = wm8731;
-	socdev->codec = codec;
-	mutex_init(&codec->mutex);
-	INIT_LIST_HEAD(&codec->dapm_widgets);
-	INIT_LIST_HEAD(&codec->dapm_paths);
+	codec = &wm8731->codec;
+	codec->control_data = spi;
+	codec->hw_write = (hw_write_t)wm8731_spi_write;
+	codec->dev = &spi->dev;
 
-	wm8731_socdev = socdev;
-	ret = -ENODEV;
+	spi->dev.driver_data = wm8731;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	if (setup->i2c_address) {
-		codec->hw_write = (hw_write_t)i2c_master_send;
-		ret = wm8731_add_i2c_device(pdev, setup);
-	}
-#endif
-#if defined(CONFIG_SPI_MASTER)
-	if (setup->spi) {
-		codec->hw_write = (hw_write_t)wm8731_spi_write;
-		ret = spi_register_driver(&wm8731_spi_driver);
-		if (ret != 0)
-			printk(KERN_ERR "can't add spi driver");
-	}
-#endif
-
-	if (ret != 0) {
-		kfree(codec->private_data);
-		kfree(codec);
-	}
-	return ret;
+	return wm8731_register(wm8731);
 }
 
-/* power down chip */
-static int wm8731_remove(struct platform_device *pdev)
+static int __devexit wm8731_spi_remove(struct spi_device *spi)
 {
-	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct wm8731_priv *wm8731 = spi->dev.driver_data;
 
-	if (codec->control_data)
-		wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-	snd_soc_free_pcms(socdev);
-	snd_soc_dapm_free(socdev);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	i2c_unregister_device(codec->control_data);
-	i2c_del_driver(&wm8731_i2c_driver);
-#endif
-#if defined(CONFIG_SPI_MASTER)
-	spi_unregister_driver(&wm8731_spi_driver);
-#endif
-	kfree(codec->private_data);
-	kfree(codec);
+	wm8731_unregister(wm8731);
 
 	return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_wm8731 = {
-	.probe = 	wm8731_probe,
-	.remove = 	wm8731_remove,
-	.suspend = 	wm8731_suspend,
-	.resume =	wm8731_resume,
+static struct spi_driver wm8731_spi_driver = {
+	.driver = {
+		.name	= "wm8731",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= wm8731_spi_probe,
+	.remove		= __devexit_p(wm8731_spi_remove),
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
+#endif /* CONFIG_SPI_MASTER */
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
+{
+	struct wm8731_priv *wm8731;
+	struct snd_soc_codec *codec;
+
+	wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
+	if (wm8731 == NULL)
+		return -ENOMEM;
+
+	codec = &wm8731->codec;
+	codec->hw_write = (hw_write_t)i2c_master_send;
+
+	i2c_set_clientdata(i2c, wm8731);
+	codec->control_data = i2c;
+
+	codec->dev = &i2c->dev;
+
+	return wm8731_register(wm8731);
+}
+
+static __devexit int wm8731_i2c_remove(struct i2c_client *client)
+{
+	struct wm8731_priv *wm8731 = i2c_get_clientdata(client);
+	wm8731_unregister(wm8731);
+	return 0;
+}
+
+static const struct i2c_device_id wm8731_i2c_id[] = {
+	{ "wm8731", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
+
+static struct i2c_driver wm8731_i2c_driver = {
+	.driver = {
+		.name = "WM8731 I2C Codec",
+		.owner = THIS_MODULE,
+	},
+	.probe =    wm8731_i2c_probe,
+	.remove =   __devexit_p(wm8731_i2c_remove),
+	.id_table = wm8731_i2c_id,
+};
+#endif
 
 static int __init wm8731_modinit(void)
 {
-	return snd_soc_register_dai(&wm8731_dai);
+	int ret;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	ret = i2c_add_driver(&wm8731_i2c_driver);
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n",
+		       ret);
+	}
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	ret = spi_register_driver(&wm8731_spi_driver);
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to register WM8731 SPI driver: %d\n",
+		       ret);
+	}
+#endif
+	return 0;
 }
 module_init(wm8731_modinit);
 
 static void __exit wm8731_exit(void)
 {
-	snd_soc_unregister_dai(&wm8731_dai);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_driver(&wm8731_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	spi_unregister_driver(&wm8731_spi_driver);
+#endif
 }
 module_exit(wm8731_exit);
 
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h
index 95190e9..cd7b806 100644
--- a/sound/soc/codecs/wm8731.h
+++ b/sound/soc/codecs/wm8731.h
@@ -34,12 +34,6 @@
 #define WM8731_SYSCLK	0
 #define WM8731_DAI		0
 
-struct wm8731_setup_data {
-	int            spi;
-	int            i2c_bus;
-	unsigned short i2c_address;
-};
-
 extern struct snd_soc_dai wm8731_dai;
 extern struct snd_soc_codec_device soc_codec_dev_wm8731;
 
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 5997fa6..b64509b 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -231,21 +231,6 @@
 
 };
 
-/* add non dapm controls */
-static int wm8750_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	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));
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
 /*
  * DAPM Controls
  */
@@ -619,7 +604,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8750_priv *wm8750 = codec->private_data;
 	u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3;
 	u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0;
@@ -694,6 +679,13 @@
 #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
+static struct snd_soc_dai_ops wm8750_dai_ops = {
+	.hw_params	= wm8750_pcm_hw_params,
+	.digital_mute	= wm8750_mute,
+	.set_fmt	= wm8750_set_dai_fmt,
+	.set_sysclk	= wm8750_set_dai_sysclk,
+};
+
 struct snd_soc_dai wm8750_dai = {
 	.name = "WM8750",
 	.playback = {
@@ -708,12 +700,7 @@
 		.channels_max = 2,
 		.rates = WM8750_RATES,
 		.formats = WM8750_FORMATS,},
-	.ops = {
-		.hw_params = wm8750_pcm_hw_params,
-		.digital_mute = wm8750_mute,
-		.set_fmt = wm8750_set_dai_fmt,
-		.set_sysclk = wm8750_set_dai_sysclk,
-	},
+	.ops = &wm8750_dai_ops,
 };
 EXPORT_SYMBOL_GPL(wm8750_dai);
 
@@ -727,7 +714,7 @@
 static int wm8750_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -736,7 +723,7 @@
 static int wm8750_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u8 data[2];
 	u16 *cache = codec->reg_cache;
@@ -769,7 +756,7 @@
  */
 static int wm8750_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int reg, ret = 0;
 
 	codec->name = "WM8750";
@@ -816,7 +803,8 @@
 	reg = wm8750_read_reg_cache(codec, WM8750_RINVOL);
 	wm8750_write(codec, WM8750_RINVOL, reg | 0x0100);
 
-	wm8750_add_controls(codec);
+	snd_soc_add_controls(codec, wm8750_snd_controls,
+				ARRAY_SIZE(wm8750_snd_controls));
 	wm8750_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -850,7 +838,7 @@
 			    const struct i2c_device_id *id)
 {
 	struct snd_soc_device *socdev = wm8750_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	i2c_set_clientdata(i2c, codec);
@@ -931,7 +919,7 @@
 static int __devinit wm8750_spi_probe(struct spi_device *spi)
 {
 	struct snd_soc_device *socdev = wm8750_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	codec->control_data = spi;
@@ -1003,7 +991,7 @@
 	}
 
 	codec->private_data = wm8750;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -1057,7 +1045,7 @@
 static int wm8750_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec->control_data)
 		wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 77620ab..a6e8f3f 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -51,8 +51,6 @@
 
 #include "wm8753.h"
 
-#define WM8753_VERSION "0.16"
-
 static int caps_charge = 2000;
 module_param(caps_charge, int, 0);
 MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
@@ -60,12 +58,6 @@
 static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
 	unsigned int mode);
 
-/* codec private data */
-struct wm8753_priv {
-	unsigned int sysclk;
-	unsigned int pcmclk;
-};
-
 /*
  * wm8753 register cache
  * We can't read the WM8753 register space when we
@@ -90,6 +82,14 @@
 	0x0000, 0x0000
 };
 
+/* codec private data */
+struct wm8753_priv {
+	unsigned int sysclk;
+	unsigned int pcmclk;
+	struct snd_soc_codec codec;
+	u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
+};
+
 /*
  * read wm8753 register cache
  */
@@ -97,7 +97,7 @@
 	unsigned int reg)
 {
 	u16 *cache = codec->reg_cache;
-	if (reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1))
+	if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
 		return -1;
 	return cache[reg - 1];
 }
@@ -109,7 +109,7 @@
 	unsigned int reg, unsigned int value)
 {
 	u16 *cache = codec->reg_cache;
-	if (reg < 1 || reg > 0x3f)
+	if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
 		return;
 	cache[reg - 1] = value;
 }
@@ -339,21 +339,6 @@
 SOC_ENUM("ROUT2 Phase", wm8753_enum[28]),
 };
 
-/* add non dapm controls */
-static int wm8753_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&wm8753_snd_controls[i],
-						codec, NULL));
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
 /*
  * _DAPM_ Controls
  */
@@ -927,7 +912,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8753_priv *wm8753 = codec->private_data;
 	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;
 	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
@@ -1161,7 +1146,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8753_priv *wm8753 = codec->private_data;
 	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
 	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3;
@@ -1316,6 +1301,51 @@
  * 3. Voice disabled - HIFI over HIFI
  * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
  */
+static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = {
+	.hw_params	= wm8753_i2s_hw_params,
+	.digital_mute	= wm8753_mute,
+	.set_fmt	= wm8753_mode1h_set_dai_fmt,
+	.set_clkdiv	= wm8753_set_dai_clkdiv,
+	.set_pll	= wm8753_set_dai_pll,
+	.set_sysclk	= wm8753_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = {
+	.hw_params	= wm8753_pcm_hw_params,
+	.digital_mute	= wm8753_mute,
+	.set_fmt	= wm8753_mode1v_set_dai_fmt,
+	.set_clkdiv	= wm8753_set_dai_clkdiv,
+	.set_pll	= wm8753_set_dai_pll,
+	.set_sysclk	= wm8753_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = {
+	.hw_params	= wm8753_pcm_hw_params,
+	.digital_mute	= wm8753_mute,
+	.set_fmt	= wm8753_mode2_set_dai_fmt,
+	.set_clkdiv	= wm8753_set_dai_clkdiv,
+	.set_pll	= wm8753_set_dai_pll,
+	.set_sysclk	= wm8753_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3	= {
+	.hw_params	= wm8753_i2s_hw_params,
+	.digital_mute	= wm8753_mute,
+	.set_fmt	= wm8753_mode3_4_set_dai_fmt,
+	.set_clkdiv	= wm8753_set_dai_clkdiv,
+	.set_pll	= wm8753_set_dai_pll,
+	.set_sysclk	= wm8753_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4	= {
+	.hw_params	= wm8753_i2s_hw_params,
+	.digital_mute	= wm8753_mute,
+	.set_fmt	= wm8753_mode3_4_set_dai_fmt,
+	.set_clkdiv	= wm8753_set_dai_clkdiv,
+	.set_pll	= wm8753_set_dai_pll,
+	.set_sysclk	= wm8753_set_dai_sysclk,
+};
+
 static const struct snd_soc_dai wm8753_all_dai[] = {
 /* DAI HiFi mode 1 */
 {	.name = "WM8753 HiFi",
@@ -1332,14 +1362,7 @@
 		.channels_max = 2,
 		.rates = WM8753_RATES,
 		.formats = WM8753_FORMATS},
-	.ops = {
-		.hw_params = wm8753_i2s_hw_params,
-		.digital_mute = wm8753_mute,
-		.set_fmt = wm8753_mode1h_set_dai_fmt,
-		.set_clkdiv = wm8753_set_dai_clkdiv,
-		.set_pll = wm8753_set_dai_pll,
-		.set_sysclk = wm8753_set_dai_sysclk,
-	},
+	.ops = &wm8753_dai_ops_hifi_mode1,
 },
 /* DAI Voice mode 1 */
 {	.name = "WM8753 Voice",
@@ -1356,14 +1379,7 @@
 		.channels_max = 2,
 		.rates = WM8753_RATES,
 		.formats = WM8753_FORMATS,},
-	.ops = {
-		.hw_params = wm8753_pcm_hw_params,
-		.digital_mute = wm8753_mute,
-		.set_fmt = wm8753_mode1v_set_dai_fmt,
-		.set_clkdiv = wm8753_set_dai_clkdiv,
-		.set_pll = wm8753_set_dai_pll,
-		.set_sysclk = wm8753_set_dai_sysclk,
-	},
+	.ops = &wm8753_dai_ops_voice_mode1,
 },
 /* DAI HiFi mode 2 - dummy */
 {	.name = "WM8753 HiFi",
@@ -1384,14 +1400,7 @@
 		.channels_max = 2,
 		.rates = WM8753_RATES,
 		.formats = WM8753_FORMATS,},
-	.ops = {
-		.hw_params = wm8753_pcm_hw_params,
-		.digital_mute = wm8753_mute,
-		.set_fmt = wm8753_mode2_set_dai_fmt,
-		.set_clkdiv = wm8753_set_dai_clkdiv,
-		.set_pll = wm8753_set_dai_pll,
-		.set_sysclk = wm8753_set_dai_sysclk,
-	},
+	.ops = &wm8753_dai_ops_voice_mode2,
 },
 /* DAI HiFi mode 3 */
 {	.name = "WM8753 HiFi",
@@ -1408,14 +1417,7 @@
 		.channels_max = 2,
 		.rates = WM8753_RATES,
 		.formats = WM8753_FORMATS,},
-	.ops = {
-		.hw_params = wm8753_i2s_hw_params,
-		.digital_mute = wm8753_mute,
-		.set_fmt = wm8753_mode3_4_set_dai_fmt,
-		.set_clkdiv = wm8753_set_dai_clkdiv,
-		.set_pll = wm8753_set_dai_pll,
-		.set_sysclk = wm8753_set_dai_sysclk,
-	},
+	.ops = &wm8753_dai_ops_hifi_mode3,
 },
 /* DAI Voice mode 3 - dummy */
 {	.name = "WM8753 Voice",
@@ -1436,14 +1438,7 @@
 		.channels_max = 2,
 		.rates = WM8753_RATES,
 		.formats = WM8753_FORMATS,},
-	.ops = {
-		.hw_params = wm8753_i2s_hw_params,
-		.digital_mute = wm8753_mute,
-		.set_fmt = wm8753_mode3_4_set_dai_fmt,
-		.set_clkdiv = wm8753_set_dai_clkdiv,
-		.set_pll = wm8753_set_dai_pll,
-		.set_sysclk = wm8753_set_dai_sysclk,
-	},
+	.ops = &wm8753_dai_ops_hifi_mode4,
 },
 /* DAI Voice mode 4 - dummy */
 {	.name = "WM8753 Voice",
@@ -1466,30 +1461,35 @@
 	if (mode < 4) {
 		int playback_active, capture_active, codec_active, pop_wait;
 		void *private_data;
+		struct list_head list;
 
 		playback_active = wm8753_dai[0].playback.active;
 		capture_active = wm8753_dai[0].capture.active;
 		codec_active = wm8753_dai[0].active;
 		private_data = wm8753_dai[0].private_data;
 		pop_wait = wm8753_dai[0].pop_wait;
+		list = wm8753_dai[0].list;
 		wm8753_dai[0] = wm8753_all_dai[mode << 1];
 		wm8753_dai[0].playback.active = playback_active;
 		wm8753_dai[0].capture.active = capture_active;
 		wm8753_dai[0].active = codec_active;
 		wm8753_dai[0].private_data = private_data;
 		wm8753_dai[0].pop_wait = pop_wait;
+		wm8753_dai[0].list = list;
 
 		playback_active = wm8753_dai[1].playback.active;
 		capture_active = wm8753_dai[1].capture.active;
 		codec_active = wm8753_dai[1].active;
 		private_data = wm8753_dai[1].private_data;
 		pop_wait = wm8753_dai[1].pop_wait;
+		list = wm8753_dai[1].list;
 		wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1];
 		wm8753_dai[1].playback.active = playback_active;
 		wm8753_dai[1].capture.active = capture_active;
 		wm8753_dai[1].active = codec_active;
 		wm8753_dai[1].private_data = private_data;
 		wm8753_dai[1].pop_wait = pop_wait;
+		wm8753_dai[1].list = list;
 	}
 	wm8753_dai[0].codec = codec;
 	wm8753_dai[1].codec = codec;
@@ -1505,7 +1505,7 @@
 static int wm8753_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	/* we only need to suspend if we are a valid card */
 	if (!codec->card)
@@ -1518,7 +1518,7 @@
 static int wm8753_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u8 data[2];
 	u16 *cache = codec->reg_cache;
@@ -1531,6 +1531,11 @@
 	for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) {
 		if (i + 1 == WM8753_RESET)
 			continue;
+
+		/* No point in writing hardware default values back */
+		if (cache[i] == wm8753_reg[i])
+			continue;
+
 		data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
 		data[1] = cache[i] & 0x00ff;
 		codec->hw_write(codec->control_data, data, 2);
@@ -1549,32 +1554,24 @@
 	return 0;
 }
 
-/*
- * initialise the WM8753 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8753_init(struct snd_soc_device *socdev)
+static struct snd_soc_codec *wm8753_codec;
+
+static int wm8753_probe(struct platform_device *pdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
-	int reg, ret = 0;
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
+	int ret = 0;
 
-	codec->name = "WM8753";
-	codec->owner = THIS_MODULE;
-	codec->read = wm8753_read_reg_cache;
-	codec->write = wm8753_write;
-	codec->set_bias_level = wm8753_set_bias_level;
-	codec->dai = wm8753_dai;
-	codec->num_dai = 2;
-	codec->reg_cache_size = ARRAY_SIZE(wm8753_reg);
-	codec->reg_cache = kmemdup(wm8753_reg, sizeof(wm8753_reg), GFP_KERNEL);
+	if (!wm8753_codec) {
+		dev_err(&pdev->dev, "WM8753 codec not yet registered\n");
+		return -EINVAL;
+	}
 
-	if (codec->reg_cache == NULL)
-		return -ENOMEM;
+	socdev->card->codec = wm8753_codec;
+	codec = wm8753_codec;
 
 	wm8753_set_dai_mode(codec, 0);
 
-	wm8753_reset(codec);
-
 	/* register pcms */
 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
 	if (ret < 0) {
@@ -1582,35 +1579,8 @@
 		goto pcm_err;
 	}
 
-	/* charge output caps */
-	wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
-	codec->bias_level = SND_SOC_BIAS_STANDBY;
-	schedule_delayed_work(&codec->delayed_work,
-		msecs_to_jiffies(caps_charge));
-
-	/* set the update bits */
-	reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
-	wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_RDAC);
-	wm8753_write(codec, WM8753_RDAC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_LADC);
-	wm8753_write(codec, WM8753_LADC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_RADC);
-	wm8753_write(codec, WM8753_RADC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V);
-	wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
-	wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
-	wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
-	wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
-	wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
-	wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
-
-	wm8753_add_controls(codec);
+	snd_soc_add_controls(codec, wm8753_snd_controls,
+			     ARRAY_SIZE(wm8753_snd_controls));
 	wm8753_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -1618,215 +1588,13 @@
 		goto card_err;
 	}
 
-	return ret;
+	return 0;
 
 card_err:
 	snd_soc_free_pcms(socdev);
 	snd_soc_dapm_free(socdev);
+
 pcm_err:
-	kfree(codec->reg_cache);
-	return ret;
-}
-
-/* If the i2c layer weren't so broken, we could pass this kind of data
-   around */
-static struct snd_soc_device *wm8753_socdev;
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-/*
- * WM8753 2 wire address is determined by GPIO5
- * state during powerup.
- *    low  = 0x1a
- *    high = 0x1b
- */
-
-static int wm8753_i2c_probe(struct i2c_client *i2c,
-			    const struct i2c_device_id *id)
-{
-	struct snd_soc_device *socdev = wm8753_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
-	int ret;
-
-	i2c_set_clientdata(i2c, codec);
-	codec->control_data = i2c;
-
-	ret = wm8753_init(socdev);
-	if (ret < 0)
-		pr_err("failed to initialise WM8753\n");
-
-	return ret;
-}
-
-static int wm8753_i2c_remove(struct i2c_client *client)
-{
-	struct snd_soc_codec *codec = i2c_get_clientdata(client);
-	kfree(codec->reg_cache);
-	return 0;
-}
-
-static const struct i2c_device_id wm8753_i2c_id[] = {
-	{ "wm8753", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
-
-static struct i2c_driver wm8753_i2c_driver = {
-	.driver = {
-		.name = "WM8753 I2C Codec",
-		.owner = THIS_MODULE,
-	},
-	.probe =    wm8753_i2c_probe,
-	.remove =   wm8753_i2c_remove,
-	.id_table = wm8753_i2c_id,
-};
-
-static int wm8753_add_i2c_device(struct platform_device *pdev,
-				 const struct wm8753_setup_data *setup)
-{
-	struct i2c_board_info info;
-	struct i2c_adapter *adapter;
-	struct i2c_client *client;
-	int ret;
-
-	ret = i2c_add_driver(&wm8753_i2c_driver);
-	if (ret != 0) {
-		dev_err(&pdev->dev, "can't add i2c driver\n");
-		return ret;
-	}
-
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	info.addr = setup->i2c_address;
-	strlcpy(info.type, "wm8753", I2C_NAME_SIZE);
-
-	adapter = i2c_get_adapter(setup->i2c_bus);
-	if (!adapter) {
-		dev_err(&pdev->dev, "can't get i2c adapter %d\n",
-			setup->i2c_bus);
-		goto err_driver;
-	}
-
-	client = i2c_new_device(adapter, &info);
-	i2c_put_adapter(adapter);
-	if (!client) {
-		dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
-			(unsigned int)info.addr);
-		goto err_driver;
-	}
-
-	return 0;
-
-err_driver:
-	i2c_del_driver(&wm8753_i2c_driver);
-	return -ENODEV;
-}
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8753_spi_probe(struct spi_device *spi)
-{
-	struct snd_soc_device *socdev = wm8753_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
-	int ret;
-
-	codec->control_data = spi;
-
-	ret = wm8753_init(socdev);
-	if (ret < 0)
-		dev_err(&spi->dev, "failed to initialise WM8753\n");
-
-	return ret;
-}
-
-static int __devexit wm8753_spi_remove(struct spi_device *spi)
-{
-	return 0;
-}
-
-static struct spi_driver wm8753_spi_driver = {
-	.driver = {
-		.name	= "wm8753",
-		.bus	= &spi_bus_type,
-		.owner	= THIS_MODULE,
-	},
-	.probe		= wm8753_spi_probe,
-	.remove		= __devexit_p(wm8753_spi_remove),
-};
-
-static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
-{
-	struct spi_transfer t;
-	struct spi_message m;
-	u8 msg[2];
-
-	if (len <= 0)
-		return 0;
-
-	msg[0] = data[0];
-	msg[1] = data[1];
-
-	spi_message_init(&m);
-	memset(&t, 0, (sizeof t));
-
-	t.tx_buf = &msg[0];
-	t.len = len;
-
-	spi_message_add_tail(&t, &m);
-	spi_sync(spi, &m);
-
-	return len;
-}
-#endif
-
-
-static int wm8753_probe(struct platform_device *pdev)
-{
-	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct wm8753_setup_data *setup;
-	struct snd_soc_codec *codec;
-	struct wm8753_priv *wm8753;
-	int ret = 0;
-
-	pr_info("WM8753 Audio Codec %s", WM8753_VERSION);
-
-	setup = socdev->codec_data;
-	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-	if (codec == NULL)
-		return -ENOMEM;
-
-	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
-	if (wm8753 == NULL) {
-		kfree(codec);
-		return -ENOMEM;
-	}
-
-	codec->private_data = wm8753;
-	socdev->codec = codec;
-	mutex_init(&codec->mutex);
-	INIT_LIST_HEAD(&codec->dapm_widgets);
-	INIT_LIST_HEAD(&codec->dapm_paths);
-	wm8753_socdev = socdev;
-	INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	if (setup->i2c_address) {
-		codec->hw_write = (hw_write_t)i2c_master_send;
-		ret = wm8753_add_i2c_device(pdev, setup);
-	}
-#endif
-#if defined(CONFIG_SPI_MASTER)
-	if (setup->spi) {
-		codec->hw_write = (hw_write_t)wm8753_spi_write;
-		ret = spi_register_driver(&wm8753_spi_driver);
-		if (ret != 0)
-			printk(KERN_ERR "can't add spi driver");
-	}
-#endif
-
-	if (ret != 0) {
-		kfree(codec->private_data);
-		kfree(codec);
-	}
 	return ret;
 }
 
@@ -1853,22 +1621,9 @@
 static int wm8753_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
 
-	if (codec->control_data)
-		wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
-	run_delayed_work(&codec->delayed_work);
 	snd_soc_free_pcms(socdev);
 	snd_soc_dapm_free(socdev);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	i2c_unregister_device(codec->control_data);
-	i2c_del_driver(&wm8753_i2c_driver);
-#endif
-#if defined(CONFIG_SPI_MASTER)
-	spi_unregister_driver(&wm8753_spi_driver);
-#endif
-	kfree(codec->private_data);
-	kfree(codec);
 
 	return 0;
 }
@@ -1881,15 +1636,240 @@
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
 
+static int wm8753_register(struct wm8753_priv *wm8753)
+{
+	int ret, i;
+	struct snd_soc_codec *codec = &wm8753->codec;
+	u16 reg;
+
+	if (wm8753_codec) {
+		dev_err(codec->dev, "Multiple WM8753 devices not supported\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	codec->name = "WM8753";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8753_read_reg_cache;
+	codec->write = wm8753_write;
+	codec->bias_level = SND_SOC_BIAS_STANDBY;
+	codec->set_bias_level = wm8753_set_bias_level;
+	codec->dai = wm8753_dai;
+	codec->num_dai = 2;
+	codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache);
+	codec->reg_cache = &wm8753->reg_cache;
+	codec->private_data = wm8753;
+
+	memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache));
+	INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
+
+	ret = wm8753_reset(codec);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to issue reset\n");
+		goto err;
+	}
+
+	/* charge output caps */
+	wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+	schedule_delayed_work(&codec->delayed_work,
+			      msecs_to_jiffies(caps_charge));
+
+	/* set the update bits */
+	reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
+	wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_RDAC);
+	wm8753_write(codec, WM8753_RDAC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LADC);
+	wm8753_write(codec, WM8753_LADC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_RADC);
+	wm8753_write(codec, WM8753_RADC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V);
+	wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
+	wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
+	wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
+	wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
+	wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
+	wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
+
+	wm8753_codec = codec;
+
+	for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++)
+		wm8753_dai[i].dev = codec->dev;
+
+	ret = snd_soc_register_codec(codec);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+		goto err;
+	}
+
+	ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
+		goto err_codec;
+	}
+
+	return 0;
+
+err_codec:
+	run_delayed_work(&codec->delayed_work);
+	snd_soc_unregister_codec(codec);
+err:
+	kfree(wm8753);
+	return ret;
+}
+
+static void wm8753_unregister(struct wm8753_priv *wm8753)
+{
+	wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF);
+	run_delayed_work(&wm8753->codec.delayed_work);
+	snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
+	snd_soc_unregister_codec(&wm8753->codec);
+	kfree(wm8753);
+	wm8753_codec = NULL;
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+static int wm8753_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct snd_soc_codec *codec;
+	struct wm8753_priv *wm8753;
+
+	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+	if (wm8753 == NULL)
+		return -ENOMEM;
+
+        codec = &wm8753->codec;
+        codec->hw_write = (hw_write_t)i2c_master_send;
+        codec->control_data = i2c;
+        i2c_set_clientdata(i2c, wm8753);
+
+        codec->dev = &i2c->dev;
+
+	return wm8753_register(wm8753);
+}
+
+static int wm8753_i2c_remove(struct i2c_client *client)
+{
+        struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
+        wm8753_unregister(wm8753);
+        return 0;
+}
+
+static const struct i2c_device_id wm8753_i2c_id[] = {
+	{ "wm8753", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
+
+static struct i2c_driver wm8753_i2c_driver = {
+	.driver = {
+		.name = "wm8753",
+		.owner = THIS_MODULE,
+	},
+	.probe =    wm8753_i2c_probe,
+	.remove =   wm8753_i2c_remove,
+	.id_table = wm8753_i2c_id,
+};
+#endif
+
+#if defined(CONFIG_SPI_MASTER)
+static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
+{
+	struct spi_transfer t;
+	struct spi_message m;
+	u8 msg[2];
+
+	if (len <= 0)
+		return 0;
+
+	msg[0] = data[0];
+	msg[1] = data[1];
+
+	spi_message_init(&m);
+	memset(&t, 0, (sizeof t));
+
+	t.tx_buf = &msg[0];
+	t.len = len;
+
+	spi_message_add_tail(&t, &m);
+	spi_sync(spi, &m);
+
+	return len;
+}
+
+static int __devinit wm8753_spi_probe(struct spi_device *spi)
+{
+	struct snd_soc_codec *codec;
+	struct wm8753_priv *wm8753;
+
+	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+	if (wm8753 == NULL)
+		return -ENOMEM;
+
+	codec = &wm8753->codec;
+	codec->control_data = spi;
+	codec->hw_write = (hw_write_t)wm8753_spi_write;
+	codec->dev = &spi->dev;
+
+	spi->dev.driver_data = wm8753;
+
+	return wm8753_register(wm8753);
+}
+
+static int __devexit wm8753_spi_remove(struct spi_device *spi)
+{
+	struct wm8753_priv *wm8753 = spi->dev.driver_data;
+	wm8753_unregister(wm8753);
+	return 0;
+}
+
+static struct spi_driver wm8753_spi_driver = {
+	.driver = {
+		.name	= "wm8753",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= wm8753_spi_probe,
+	.remove		= __devexit_p(wm8753_spi_remove),
+};
+#endif
+
 static int __init wm8753_modinit(void)
 {
-	return snd_soc_register_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
+	int ret;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	ret = i2c_add_driver(&wm8753_i2c_driver);
+	if (ret != 0)
+		pr_err("Failed to register WM8753 I2C driver: %d\n", ret);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	ret = spi_register_driver(&wm8753_spi_driver);
+	if (ret != 0)
+		pr_err("Failed to register WM8753 SPI driver: %d\n", ret);
+#endif
+	return 0;
 }
 module_init(wm8753_modinit);
 
 static void __exit wm8753_exit(void)
 {
-	snd_soc_unregister_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_driver(&wm8753_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	spi_unregister_driver(&wm8753_spi_driver);
+#endif
 }
 module_exit(wm8753_exit);
 
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h
index f55704c..57b2ba2 100644
--- a/sound/soc/codecs/wm8753.h
+++ b/sound/soc/codecs/wm8753.h
@@ -77,12 +77,6 @@
 #define WM8753_BIASCTL		0x3d
 #define WM8753_ADCTL2		0x3f
 
-struct wm8753_setup_data {
-	int spi;
-	int i2c_bus;
-	unsigned short i2c_address;
-};
-
 #define WM8753_PLL1			0
 #define WM8753_PLL2			1
 
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 6767de1..46c5ea1 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -517,22 +517,6 @@
 
 };
 
-/* add non dapm controls */
-static int wm8900_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8900_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&wm8900_snd_controls[i],
-					       codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 static const struct snd_kcontrol_new wm8900_dapm_loutput2_control =
 SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0);
 
@@ -736,7 +720,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 reg;
 
 	reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60;
@@ -1104,6 +1088,14 @@
 	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
 	 SNDRV_PCM_FORMAT_S24_LE)
 
+static struct snd_soc_dai_ops wm8900_dai_ops = {
+	.hw_params	= wm8900_hw_params,
+	.set_clkdiv	= wm8900_set_dai_clkdiv,
+	.set_pll	= wm8900_set_dai_pll,
+	.set_fmt	= wm8900_set_dai_fmt,
+	.digital_mute	= wm8900_digital_mute,
+};
+
 struct snd_soc_dai wm8900_dai = {
 	.name = "WM8900 HiFi",
 	.playback = {
@@ -1120,13 +1112,7 @@
 		.rates = WM8900_RATES,
 		.formats = WM8900_PCM_FORMATS,
 	 },
-	.ops = {
-		.hw_params = wm8900_hw_params,
-		 .set_clkdiv = wm8900_set_dai_clkdiv,
-		 .set_pll = wm8900_set_dai_pll,
-		 .set_fmt = wm8900_set_dai_fmt,
-		 .digital_mute = wm8900_digital_mute,
-	 },
+	.ops = &wm8900_dai_ops,
 };
 EXPORT_SYMBOL_GPL(wm8900_dai);
 
@@ -1226,7 +1212,7 @@
 static int wm8900_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8900_priv *wm8900 = codec->private_data;
 	int fll_out = wm8900->fll_out;
 	int fll_in  = wm8900->fll_in;
@@ -1250,7 +1236,7 @@
 static int wm8900_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8900_priv *wm8900 = codec->private_data;
 	u16 *cache;
 	int i, ret;
@@ -1288,8 +1274,8 @@
 
 static struct snd_soc_codec *wm8900_codec;
 
-static int wm8900_i2c_probe(struct i2c_client *i2c,
-			    const struct i2c_device_id *id)
+static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
 {
 	struct wm8900_priv *wm8900;
 	struct snd_soc_codec *codec;
@@ -1388,7 +1374,7 @@
 	return ret;
 }
 
-static int wm8900_i2c_remove(struct i2c_client *client)
+static __devexit int wm8900_i2c_remove(struct i2c_client *client)
 {
 	snd_soc_unregister_dai(&wm8900_dai);
 	snd_soc_unregister_codec(wm8900_codec);
@@ -1414,7 +1400,7 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = wm8900_i2c_probe,
-	.remove = wm8900_i2c_remove,
+	.remove = __devexit_p(wm8900_i2c_remove),
 	.id_table = wm8900_i2c_id,
 };
 
@@ -1430,7 +1416,7 @@
 	}
 
 	codec = wm8900_codec;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 
 	/* Register pcms */
 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
@@ -1439,7 +1425,8 @@
 		goto pcm_err;
 	}
 
-	wm8900_add_controls(codec);
+	snd_soc_add_controls(codec, wm8900_snd_controls,
+				ARRAY_SIZE(wm8900_snd_controls));
 	wm8900_add_widgets(codec);
 
 	ret = snd_soc_init_card(socdev);
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index bde7454..8cf571f 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -744,21 +744,6 @@
 		 0, 63, 0, out_tlv),
 };
 
-static int wm8903_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8903_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&wm8903_snd_controls[i],
-					       codec, NULL));
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 static const struct snd_kcontrol_new linput_mode_mux =
 	SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum);
 
@@ -1276,7 +1261,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8903_priv *wm8903 = codec->private_data;
 	struct i2c_client *i2c = codec->control_data;
 	struct snd_pcm_runtime *master_runtime;
@@ -1318,7 +1303,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8903_priv *wm8903 = codec->private_data;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -1338,7 +1323,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8903_priv *wm8903 = codec->private_data;
 	struct i2c_client *i2c = codec->control_data;
 	int fs = params_rate(params);
@@ -1512,6 +1497,15 @@
 			SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE)
 
+static struct snd_soc_dai_ops wm8903_dai_ops = {
+	.startup	= wm8903_startup,
+	.shutdown	= wm8903_shutdown,
+	.hw_params	= wm8903_hw_params,
+	.digital_mute	= wm8903_digital_mute,
+	.set_fmt	= wm8903_set_dai_fmt,
+	.set_sysclk	= wm8903_set_dai_sysclk,
+};
+
 struct snd_soc_dai wm8903_dai = {
 	.name = "WM8903",
 	.playback = {
@@ -1528,21 +1522,14 @@
 		 .rates = WM8903_CAPTURE_RATES,
 		 .formats = WM8903_FORMATS,
 	 },
-	.ops = {
-		 .startup = wm8903_startup,
-		 .shutdown = wm8903_shutdown,
-		 .hw_params = wm8903_hw_params,
-		 .digital_mute = wm8903_digital_mute,
-		 .set_fmt = wm8903_set_dai_fmt,
-		 .set_sysclk = wm8903_set_dai_sysclk
-	}
+	.ops = &wm8903_dai_ops,
 };
 EXPORT_SYMBOL_GPL(wm8903_dai);
 
 static int wm8903_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1552,7 +1539,7 @@
 static int wm8903_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct i2c_client *i2c = codec->control_data;
 	int i;
 	u16 *reg_cache = codec->reg_cache;
@@ -1577,8 +1564,8 @@
 
 static struct snd_soc_codec *wm8903_codec;
 
-static int wm8903_i2c_probe(struct i2c_client *i2c,
-			    const struct i2c_device_id *id)
+static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
 {
 	struct wm8903_priv *wm8903;
 	struct snd_soc_codec *codec;
@@ -1684,7 +1671,7 @@
 	return ret;
 }
 
-static int wm8903_i2c_remove(struct i2c_client *client)
+static __devexit int wm8903_i2c_remove(struct i2c_client *client)
 {
 	struct snd_soc_codec *codec = i2c_get_clientdata(client);
 
@@ -1714,7 +1701,7 @@
 		.owner = THIS_MODULE,
 	},
 	.probe    = wm8903_i2c_probe,
-	.remove   = wm8903_i2c_remove,
+	.remove   = __devexit_p(wm8903_i2c_remove),
 	.id_table = wm8903_i2c_id,
 };
 
@@ -1728,7 +1715,7 @@
 		goto err;
 	}
 
-	socdev->codec = wm8903_codec;
+	socdev->card->codec = wm8903_codec;
 
 	/* register pcms */
 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
@@ -1737,8 +1724,9 @@
 		goto err;
 	}
 
-	wm8903_add_controls(socdev->codec);
-	wm8903_add_widgets(socdev->codec);
+	snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls,
+				ARRAY_SIZE(wm8903_snd_controls));
+	wm8903_add_widgets(socdev->card->codec);
 
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -1759,7 +1747,7 @@
 static int wm8903_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec->control_data)
 		wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 88ead7f..032dca2 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -195,21 +195,6 @@
 	SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0),
 };
 
-/* add non-DAPM controls */
-static int wm8971_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8971_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&wm8971_snd_controls[i],
-					     codec, NULL));
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
 /*
  * DAPM Controls
  */
@@ -546,7 +531,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	struct wm8971_priv *wm8971 = codec->private_data;
 	u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3;
 	u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0;
@@ -619,6 +604,13 @@
 #define WM8971_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
+static struct snd_soc_dai_ops wm8971_dai_ops = {
+	.hw_params	= wm8971_pcm_hw_params,
+	.digital_mute	= wm8971_mute,
+	.set_fmt	= wm8971_set_dai_fmt,
+	.set_sysclk	= wm8971_set_dai_sysclk,
+};
+
 struct snd_soc_dai wm8971_dai = {
 	.name = "WM8971",
 	.playback = {
@@ -633,12 +625,7 @@
 		.channels_max = 2,
 		.rates = WM8971_RATES,
 		.formats = WM8971_FORMATS,},
-	.ops = {
-		.hw_params = wm8971_pcm_hw_params,
-		.digital_mute = wm8971_mute,
-		.set_fmt = wm8971_set_dai_fmt,
-		.set_sysclk = wm8971_set_dai_sysclk,
-	},
+	.ops = &wm8971_dai_ops,
 };
 EXPORT_SYMBOL_GPL(wm8971_dai);
 
@@ -652,7 +639,7 @@
 static int wm8971_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -661,7 +648,7 @@
 static int wm8971_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u8 data[2];
 	u16 *cache = codec->reg_cache;
@@ -692,7 +679,7 @@
 
 static int wm8971_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int reg, ret = 0;
 
 	codec->name = "WM8971";
@@ -745,7 +732,8 @@
 	reg = wm8971_read_reg_cache(codec, WM8971_RINVOL);
 	wm8971_write(codec, WM8971_RINVOL, reg | 0x0100);
 
-	wm8971_add_controls(codec);
+	snd_soc_add_controls(codec, wm8971_snd_controls,
+				ARRAY_SIZE(wm8971_snd_controls));
 	wm8971_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -772,7 +760,7 @@
 			    const struct i2c_device_id *id)
 {
 	struct snd_soc_device *socdev = wm8971_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	i2c_set_clientdata(i2c, codec);
@@ -873,7 +861,7 @@
 	}
 
 	codec->private_data = wm8971;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -908,7 +896,7 @@
 static int wm8971_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec->control_data)
 		wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index a5731fa..c518c3e 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -115,7 +115,7 @@
 	unsigned int reg)
 {
 	u16 *cache = codec->reg_cache;
-	BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
+	BUG_ON(reg >= ARRAY_SIZE(wm8990_reg));
 	return cache[reg];
 }
 
@@ -128,7 +128,7 @@
 	u16 *cache = codec->reg_cache;
 
 	/* Reset register and reserved registers are uncached */
-	if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1)
+	if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg))
 		return;
 
 	cache[reg] = value;
@@ -418,21 +418,6 @@
 
 };
 
-/* add non dapm controls */
-static int wm8990_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8990_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&wm8990_snd_controls[i], codec,
-					NULL));
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
 /*
  * _DAPM_ Controls
  */
@@ -1178,7 +1163,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
 
 	audio1 &= ~WM8990_AIF_WL_MASK;
@@ -1347,6 +1332,15 @@
  * 1. ADC/DAC on Primary Interface
  * 2. ADC on Primary Interface/DAC on secondary
  */
+static struct snd_soc_dai_ops wm8990_dai_ops = {
+	.hw_params	= wm8990_hw_params,
+	.digital_mute	= wm8990_mute,
+	.set_fmt	= wm8990_set_dai_fmt,
+	.set_clkdiv	= wm8990_set_dai_clkdiv,
+	.set_pll	= wm8990_set_dai_pll,
+	.set_sysclk	= wm8990_set_dai_sysclk,
+};
+
 struct snd_soc_dai wm8990_dai = {
 /* ADC/DAC on primary */
 	.name = "WM8990 ADC/DAC Primary",
@@ -1363,21 +1357,14 @@
 		.channels_max = 2,
 		.rates = WM8990_RATES,
 		.formats = WM8990_FORMATS,},
-	.ops = {
-		.hw_params = wm8990_hw_params,
-		.digital_mute = wm8990_mute,
-		.set_fmt = wm8990_set_dai_fmt,
-		.set_clkdiv = wm8990_set_dai_clkdiv,
-		.set_pll = wm8990_set_dai_pll,
-		.set_sysclk = wm8990_set_dai_sysclk,
-	},
+	.ops = &wm8990_dai_ops,
 };
 EXPORT_SYMBOL_GPL(wm8990_dai);
 
 static int wm8990_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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	/* we only need to suspend if we are a valid card */
 	if (!codec->card)
@@ -1390,7 +1377,7 @@
 static int wm8990_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i;
 	u8 data[2];
 	u16 *cache = codec->reg_cache;
@@ -1418,7 +1405,7 @@
  */
 static int wm8990_init(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 reg;
 	int ret = 0;
 
@@ -1461,7 +1448,8 @@
 	wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
 	wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
-	wm8990_add_controls(codec);
+	snd_soc_add_controls(codec, wm8990_snd_controls,
+				ARRAY_SIZE(wm8990_snd_controls));
 	wm8990_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -1495,7 +1483,7 @@
 			    const struct i2c_device_id *id)
 {
 	struct snd_soc_device *socdev = wm8990_socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret;
 
 	i2c_set_clientdata(i2c, codec);
@@ -1594,7 +1582,7 @@
 	}
 
 	codec->private_data = wm8990;
-	socdev->codec = codec;
+	socdev->card->codec = codec;
 	mutex_init(&codec->mutex);
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -1620,7 +1608,7 @@
 static int wm8990_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec->control_data)
 		wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
new file mode 100644
index 0000000..3265817
--- /dev/null
+++ b/sound/soc/codecs/wm9705.c
@@ -0,0 +1,415 @@
+/*
+ * wm9705.c  --  ALSA Soc WM9705 codec support
+ *
+ * Copyright 2008 Ian Molton <spyro@f2s.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 only.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "wm9705.h"
+
+/*
+ * WM9705 register cache
+ */
+static const u16 wm9705_reg[] = {
+	0x6150, 0x8000, 0x8000, 0x8000, /* 0x0  */
+	0x0000, 0x8000, 0x8008, 0x8008, /* 0x8  */
+	0x8808, 0x8808, 0x8808, 0x8808, /* 0x10 */
+	0x8808, 0x0000, 0x8000, 0x0000, /* 0x18 */
+	0x0000, 0x0000, 0x0000, 0x000f, /* 0x20 */
+	0x0605, 0x0000, 0xbb80, 0x0000, /* 0x28 */
+	0x0000, 0xbb80, 0x0000, 0x0000, /* 0x30 */
+	0x0000, 0x2000, 0x0000, 0x0000, /* 0x38 */
+	0x0000, 0x0000, 0x0000, 0x0000, /* 0x40 */
+	0x0000, 0x0000, 0x0000, 0x0000, /* 0x48 */
+	0x0000, 0x0000, 0x0000, 0x0000, /* 0x50 */
+	0x0000, 0x0000, 0x0000, 0x0000, /* 0x58 */
+	0x0000, 0x0000, 0x0000, 0x0000, /* 0x60 */
+	0x0000, 0x0000, 0x0000, 0x0000, /* 0x68 */
+	0x0000, 0x0808, 0x0000, 0x0006, /* 0x70 */
+	0x0000, 0x0000, 0x574d, 0x4c05, /* 0x78 */
+};
+
+static const struct snd_kcontrol_new wm9705_snd_ac97_controls[] = {
+	SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1),
+	SOC_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1),
+	SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
+	SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1),
+	SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1),
+	SOC_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1),
+	SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1),
+	SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
+	SOC_SINGLE("PCBeep Playback Volume", AC97_PC_BEEP, 1, 15, 1),
+	SOC_SINGLE("Phone Playback Volume", AC97_PHONE, 0, 31, 1),
+	SOC_DOUBLE("Line Playback Volume", AC97_LINE, 8, 0, 31, 1),
+	SOC_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1),
+	SOC_SINGLE("Mic Playback Volume", AC97_MIC, 0, 31, 1),
+	SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 6, 1, 0),
+	SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0),
+	SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1),
+};
+
+static const char *wm9705_mic[] = {"Mic 1", "Mic 2"};
+static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC",
+	"Line", "Stereo Mix", "Mono Mix", "Phone"};
+
+static const struct soc_enum wm9705_enum_mic =
+	SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic);
+static const struct soc_enum wm9705_enum_rec_l =
+	SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel);
+static const struct soc_enum wm9705_enum_rec_r =
+	SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel);
+
+/* Headphone Mixer */
+static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = {
+	SOC_DAPM_SINGLE("PCBeep Playback Switch", AC97_PC_BEEP, 15, 1, 1),
+	SOC_DAPM_SINGLE("CD Playback Switch", AC97_CD, 15, 1, 1),
+	SOC_DAPM_SINGLE("Mic Playback Switch", AC97_MIC, 15, 1, 1),
+	SOC_DAPM_SINGLE("Phone Playback Switch", AC97_PHONE, 15, 1, 1),
+	SOC_DAPM_SINGLE("Line Playback Switch", AC97_LINE, 15, 1, 1),
+};
+
+/* Mic source */
+static const struct snd_kcontrol_new wm9705_mic_src_controls =
+	SOC_DAPM_ENUM("Route", wm9705_enum_mic);
+
+/* Capture source */
+static const struct snd_kcontrol_new wm9705_capture_selectl_controls =
+	SOC_DAPM_ENUM("Route", wm9705_enum_rec_l);
+static const struct snd_kcontrol_new wm9705_capture_selectr_controls =
+	SOC_DAPM_ENUM("Route", wm9705_enum_rec_r);
+
+/* DAPM widgets */
+static const struct snd_soc_dapm_widget wm9705_dapm_widgets[] = {
+	SND_SOC_DAPM_MUX("Mic Source", SND_SOC_NOPM, 0, 0,
+		&wm9705_mic_src_controls),
+	SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0,
+		&wm9705_capture_selectl_controls),
+	SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0,
+		&wm9705_capture_selectr_controls),
+	SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback",
+		SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback",
+		SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_MIXER_NAMED_CTL("HP Mixer", SND_SOC_NOPM, 0, 0,
+		&wm9705_hp_mixer_controls[0],
+		ARRAY_SIZE(wm9705_hp_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_PGA("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Speaker PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Line PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Line out PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Mono PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Phone PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Mic PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("PCBEEP PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("CD PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("ADC PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_OUTPUT("HPOUTL"),
+	SND_SOC_DAPM_OUTPUT("HPOUTR"),
+	SND_SOC_DAPM_OUTPUT("LOUT"),
+	SND_SOC_DAPM_OUTPUT("ROUT"),
+	SND_SOC_DAPM_OUTPUT("MONOOUT"),
+	SND_SOC_DAPM_INPUT("PHONE"),
+	SND_SOC_DAPM_INPUT("LINEINL"),
+	SND_SOC_DAPM_INPUT("LINEINR"),
+	SND_SOC_DAPM_INPUT("CDINL"),
+	SND_SOC_DAPM_INPUT("CDINR"),
+	SND_SOC_DAPM_INPUT("PCBEEP"),
+	SND_SOC_DAPM_INPUT("MIC1"),
+	SND_SOC_DAPM_INPUT("MIC2"),
+};
+
+/* Audio map
+ * WM9705 has no switches to disable the route from the inputs to the HP mixer
+ * so in order to prevent active inputs from forcing the audio outputs to be
+ * constantly enabled, we use the mutes on those inputs to simulate such
+ * controls.
+ */
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* HP mixer */
+	{"HP Mixer", "PCBeep Playback Switch", "PCBEEP PGA"},
+	{"HP Mixer", "CD Playback Switch", "CD PGA"},
+	{"HP Mixer", "Mic Playback Switch", "Mic PGA"},
+	{"HP Mixer", "Phone Playback Switch", "Phone PGA"},
+	{"HP Mixer", "Line Playback Switch", "Line PGA"},
+	{"HP Mixer", NULL, "Left DAC"},
+	{"HP Mixer", NULL, "Right DAC"},
+
+	/* mono mixer */
+	{"Mono Mixer", NULL, "HP Mixer"},
+
+	/* outputs */
+	{"Headphone PGA", NULL, "HP Mixer"},
+	{"HPOUTL", NULL, "Headphone PGA"},
+	{"HPOUTR", NULL, "Headphone PGA"},
+	{"Line out PGA", NULL, "HP Mixer"},
+	{"LOUT", NULL, "Line out PGA"},
+	{"ROUT", NULL, "Line out PGA"},
+	{"Mono PGA", NULL, "Mono Mixer"},
+	{"MONOOUT", NULL, "Mono PGA"},
+
+	/* inputs */
+	{"CD PGA", NULL, "CDINL"},
+	{"CD PGA", NULL, "CDINR"},
+	{"Line PGA", NULL, "LINEINL"},
+	{"Line PGA", NULL, "LINEINR"},
+	{"Phone PGA", NULL, "PHONE"},
+	{"Mic Source", "Mic 1", "MIC1"},
+	{"Mic Source", "Mic 2", "MIC2"},
+	{"Mic PGA", NULL, "Mic Source"},
+	{"PCBEEP PGA", NULL, "PCBEEP"},
+
+	/* Left capture selector */
+	{"Left Capture Source", "Mic", "Mic Source"},
+	{"Left Capture Source", "CD", "CDINL"},
+	{"Left Capture Source", "Line", "LINEINL"},
+	{"Left Capture Source", "Stereo Mix", "HP Mixer"},
+	{"Left Capture Source", "Mono Mix", "HP Mixer"},
+	{"Left Capture Source", "Phone", "PHONE"},
+
+	/* Right capture source */
+	{"Right Capture Source", "Mic", "Mic Source"},
+	{"Right Capture Source", "CD", "CDINR"},
+	{"Right Capture Source", "Line", "LINEINR"},
+	{"Right Capture Source", "Stereo Mix", "HP Mixer"},
+	{"Right Capture Source", "Mono Mix", "HP Mixer"},
+	{"Right Capture Source", "Phone", "PHONE"},
+
+	{"ADC PGA", NULL, "Left Capture Source"},
+	{"ADC PGA", NULL, "Right Capture Source"},
+
+	/* ADC's */
+	{"Left ADC",  NULL, "ADC PGA"},
+	{"Right ADC", NULL, "ADC PGA"},
+};
+
+static int wm9705_add_widgets(struct snd_soc_codec *codec)
+{
+	snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets,
+					ARRAY_SIZE(wm9705_dapm_widgets));
+	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+	snd_soc_dapm_new_widgets(codec);
+
+	return 0;
+}
+
+/* We use a register cache to enhance read performance. */
+static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+	u16 *cache = codec->reg_cache;
+
+	switch (reg) {
+	case AC97_RESET:
+	case AC97_VENDOR_ID1:
+	case AC97_VENDOR_ID2:
+		return soc_ac97_ops.read(codec->ac97, reg);
+	default:
+		reg = reg >> 1;
+
+		if (reg >= (ARRAY_SIZE(wm9705_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;
+
+	soc_ac97_ops.write(codec->ac97, reg, val);
+	reg = reg >> 1;
+	if (reg < (ARRAY_SIZE(wm9705_reg)))
+		cache[reg] = val;
+
+	return 0;
+}
+
+static int ac97_prepare(struct snd_pcm_substream *substream,
+			struct snd_soc_dai *dai)
+{
+	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->card->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);
+}
+
+#define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \
+			SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
+			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+			SNDRV_PCM_RATE_48000)
+
+static struct snd_soc_dai_ops wm9705_dai_ops = {
+	.prepare	= ac97_prepare,
+};
+
+struct snd_soc_dai wm9705_dai[] = {
+	{
+		.name = "AC97 HiFi",
+		.ac97_control = 1,
+		.playback = {
+			.stream_name = "HiFi Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = WM9705_AC97_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.capture = {
+			.stream_name = "HiFi Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = WM9705_AC97_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.ops = &wm9705_dai_ops,
+	},
+	{
+		.name = "AC97 Aux",
+		.playback = {
+			.stream_name = "Aux Playback",
+			.channels_min = 1,
+			.channels_max = 1,
+			.rates = WM9705_AC97_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+	}
+};
+EXPORT_SYMBOL_GPL(wm9705_dai);
+
+static int wm9705_reset(struct snd_soc_codec *codec)
+{
+	if (soc_ac97_ops.reset) {
+		soc_ac97_ops.reset(codec->ac97);
+		if (ac97_read(codec, 0) == wm9705_reg[0])
+			return 0; /* Success */
+	}
+
+	return -EIO;
+}
+
+static int wm9705_soc_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
+	int ret = 0;
+
+	printk(KERN_INFO "WM9705 SoC Audio Codec\n");
+
+	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
+				      GFP_KERNEL);
+	if (socdev->card->codec == NULL)
+		return -ENOMEM;
+	codec = socdev->card->codec;
+	mutex_init(&codec->mutex);
+
+	codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL);
+	if (codec->reg_cache == NULL) {
+		ret = -ENOMEM;
+		goto cache_err;
+	}
+	codec->reg_cache_size = sizeof(wm9705_reg);
+	codec->reg_cache_step = 2;
+
+	codec->name = "WM9705";
+	codec->owner = THIS_MODULE;
+	codec->dai = wm9705_dai;
+	codec->num_dai = ARRAY_SIZE(wm9705_dai);
+	codec->write = ac97_write;
+	codec->read = ac97_read;
+	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) {
+		printk(KERN_ERR "wm9705: failed to register AC97 codec\n");
+		goto codec_err;
+	}
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0)
+		goto pcm_err;
+
+	ret = wm9705_reset(codec);
+	if (ret)
+		goto reset_err;
+
+	snd_soc_add_controls(codec, wm9705_snd_ac97_controls,
+				ARRAY_SIZE(wm9705_snd_ac97_controls));
+	wm9705_add_widgets(codec);
+
+	ret = snd_soc_init_card(socdev);
+	if (ret < 0) {
+		printk(KERN_ERR "wm9705: failed to register card\n");
+		goto pcm_err;
+	}
+
+	return 0;
+
+reset_err:
+	snd_soc_free_pcms(socdev);
+pcm_err:
+	snd_soc_free_ac97_codec(codec);
+codec_err:
+	kfree(codec->reg_cache);
+cache_err:
+	kfree(socdev->card->codec);
+	socdev->card->codec = NULL;
+	return ret;
+}
+
+static int wm9705_soc_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->card->codec;
+
+	if (codec == NULL)
+		return 0;
+
+	snd_soc_dapm_free(socdev);
+	snd_soc_free_pcms(socdev);
+	snd_soc_free_ac97_codec(codec);
+	kfree(codec->reg_cache);
+	kfree(codec);
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm9705 = {
+	.probe = 	wm9705_soc_probe,
+	.remove = 	wm9705_soc_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705);
+
+MODULE_DESCRIPTION("ASoC WM9705 driver");
+MODULE_AUTHOR("Ian Molton");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h
new file mode 100644
index 0000000..d380f11
--- /dev/null
+++ b/sound/soc/codecs/wm9705.h
@@ -0,0 +1,14 @@
+/*
+ * wm9705.h  --  WM9705 Soc Audio driver
+ */
+
+#ifndef _WM9705_H
+#define _WM9705_H
+
+#define WM9705_DAI_AC97_HIFI	0
+#define WM9705_DAI_AC97_AUX	1
+
+extern struct snd_soc_dai wm9705_dai[2];
+extern struct snd_soc_codec_device soc_codec_dev_wm9705;
+
+#endif
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index af83d62..765cf1e 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -154,21 +154,6 @@
 SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
 };
 
-/* add non dapm controls */
-static int wm9712_add_controls(struct snd_soc_codec *codec)
-{
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				  snd_soc_cnew(&wm9712_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.
@@ -467,7 +452,7 @@
 	else {
 		reg = reg >> 1;
 
-		if (reg > (ARRAY_SIZE(wm9712_reg)))
+		if (reg >= (ARRAY_SIZE(wm9712_reg)))
 			return -EIO;
 
 		return cache[reg];
@@ -481,7 +466,7 @@
 
 	soc_ac97_ops.write(codec->ac97, reg, val);
 	reg = reg >> 1;
-	if (reg <= (ARRAY_SIZE(wm9712_reg)))
+	if (reg < (ARRAY_SIZE(wm9712_reg)))
 		cache[reg] = val;
 
 	return 0;
@@ -493,7 +478,7 @@
 	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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int reg;
 	u16 vra;
 
@@ -514,7 +499,7 @@
 	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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 vra, xsle;
 
 	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
@@ -532,6 +517,14 @@
 		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
 		SNDRV_PCM_RATE_48000)
 
+static struct snd_soc_dai_ops wm9712_dai_ops_hifi = {
+	.prepare	= ac97_prepare,
+};
+
+static struct snd_soc_dai_ops wm9712_dai_ops_aux = {
+	.prepare	= ac97_aux_prepare,
+};
+
 struct snd_soc_dai wm9712_dai[] = {
 {
 	.name = "AC97 HiFi",
@@ -548,8 +541,7 @@
 		.channels_max = 2,
 		.rates = WM9712_AC97_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.prepare = ac97_prepare,},
+	.ops = &wm9712_dai_ops_hifi,
 },
 {
 	.name = "AC97 Aux",
@@ -559,8 +551,7 @@
 		.channels_max = 1,
 		.rates = WM9712_AC97_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.prepare = ac97_aux_prepare,},
+	.ops = &wm9712_dai_ops_aux,
 }
 };
 EXPORT_SYMBOL_GPL(wm9712_dai);
@@ -607,7 +598,7 @@
 	pm_message_t state)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -616,7 +607,7 @@
 static int wm9712_soc_resume(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int i, ret;
 	u16 *cache = codec->reg_cache;
 
@@ -652,10 +643,11 @@
 
 	printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
 
-	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-	if (socdev->codec == NULL)
+	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
+				      GFP_KERNEL);
+	if (socdev->card->codec == NULL)
 		return -ENOMEM;
-	codec = socdev->codec;
+	codec = socdev->card->codec;
 	mutex_init(&codec->mutex);
 
 	codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL);
@@ -698,7 +690,8 @@
 	ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
 
 	wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-	wm9712_add_controls(codec);
+	snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
+				ARRAY_SIZE(wm9712_snd_ac97_controls));
 	wm9712_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0) {
@@ -718,15 +711,15 @@
 	kfree(codec->reg_cache);
 
 cache_err:
-	kfree(socdev->codec);
-	socdev->codec = NULL;
+	kfree(socdev->card->codec);
+	socdev->card->codec = NULL;
 	return ret;
 }
 
 static int wm9712_soc_remove(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec == NULL)
 		return 0;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index f3ca8aa..523bad0 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -32,7 +32,6 @@
 
 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,
@@ -190,21 +189,6 @@
 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
@@ -636,7 +620,7 @@
 	else {
 		reg = reg >> 1;
 
-		if (reg > (ARRAY_SIZE(wm9713_reg)))
+		if (reg >= (ARRAY_SIZE(wm9713_reg)))
 			return -EIO;
 
 		return cache[reg];
@@ -650,7 +634,7 @@
 	if (reg < 0x7c)
 		soc_ac97_ops.write(codec->ac97, reg, val);
 	reg = reg >> 1;
-	if (reg <= (ARRAY_SIZE(wm9713_reg)))
+	if (reg < (ARRAY_SIZE(wm9713_reg)))
 		cache[reg] = val;
 
 	return 0;
@@ -738,13 +722,13 @@
 	struct _pll_div pll_div;
 
 	/* turn PLL off ? */
-	if (freq_in == 0 || freq_out == 0) {
+	if (freq_in == 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;
+		wm9713->pll_in = 0;
 		return 0;
 	}
 
@@ -788,7 +772,6 @@
 	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 */
@@ -957,13 +940,14 @@
 				 struct snd_soc_dai *dai)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	u16 status;
+	u16 status, rate;
 
 	/* Gracefully shut down the voice interface. */
 	status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
-	ac97_write(codec, AC97_HANDSET_RATE, 0x0280);
+	rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF;
+	ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200);
 	schedule_timeout_interruptible(msecs_to_jiffies(1));
-	ac97_write(codec, AC97_HANDSET_RATE, 0x0F80);
+	ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00);
 	ac97_write(codec, AC97_EXTENDED_MID, status);
 }
 
@@ -1021,6 +1005,27 @@
 	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
 	 SNDRV_PCM_FORMAT_S24_LE)
 
+static struct snd_soc_dai_ops wm9713_dai_ops_hifi = {
+	.prepare	= ac97_hifi_prepare,
+	.set_clkdiv	= wm9713_set_dai_clkdiv,
+	.set_pll	= wm9713_set_dai_pll,
+};
+
+static struct snd_soc_dai_ops wm9713_dai_ops_aux = {
+	.prepare	= ac97_aux_prepare,
+	.set_clkdiv	= wm9713_set_dai_clkdiv,
+	.set_pll	= wm9713_set_dai_pll,
+};
+
+static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
+	.hw_params	= wm9713_pcm_hw_params,
+	.shutdown	= wm9713_voiceshutdown,
+	.set_clkdiv	= wm9713_set_dai_clkdiv,
+	.set_pll	= wm9713_set_dai_pll,
+	.set_fmt	= wm9713_set_dai_fmt,
+	.set_tristate	= wm9713_set_dai_tristate,
+};
+
 struct snd_soc_dai wm9713_dai[] = {
 {
 	.name = "AC97 HiFi",
@@ -1037,10 +1042,7 @@
 		.channels_max = 2,
 		.rates = WM9713_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.prepare = ac97_hifi_prepare,
-		.set_clkdiv = wm9713_set_dai_clkdiv,
-		.set_pll = wm9713_set_dai_pll,},
+	.ops = &wm9713_dai_ops_hifi,
 	},
 	{
 	.name = "AC97 Aux",
@@ -1050,10 +1052,7 @@
 		.channels_max = 1,
 		.rates = WM9713_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.prepare = ac97_aux_prepare,
-		.set_clkdiv = wm9713_set_dai_clkdiv,
-		.set_pll = wm9713_set_dai_pll,},
+	.ops = &wm9713_dai_ops_aux,
 	},
 	{
 	.name = "WM9713 Voice",
@@ -1069,14 +1068,7 @@
 		.channels_max = 2,
 		.rates = WM9713_PCM_RATES,
 		.formats = WM9713_PCM_FORMATS,},
-	.ops = {
-		.hw_params = wm9713_pcm_hw_params,
-		.shutdown = wm9713_voiceshutdown,
-		.set_clkdiv = wm9713_set_dai_clkdiv,
-		.set_pll = wm9713_set_dai_pll,
-		.set_fmt = wm9713_set_dai_fmt,
-		.set_tristate = wm9713_set_dai_tristate,
-	},
+	.ops = &wm9713_dai_ops_voice,
 	},
 };
 EXPORT_SYMBOL_GPL(wm9713_dai);
@@ -1132,7 +1124,7 @@
 	pm_message_t state)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	u16 reg;
 
 	/* Disable everything except touchpanel - that will be handled
@@ -1150,7 +1142,7 @@
 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 snd_soc_codec *codec = socdev->card->codec;
 	struct wm9713_priv *wm9713 = codec->private_data;
 	int i, ret;
 	u16 *cache = codec->reg_cache;
@@ -1164,8 +1156,8 @@
 	wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	/* do we need to re-start the PLL ? */
-	if (wm9713->pll_out)
-		wm9713_set_pll(codec, 0, wm9713->pll_in, wm9713->pll_out);
+	if (wm9713->pll_in)
+		wm9713_set_pll(codec, 0, wm9713->pll_in, 0);
 
 	/* only synchronise the codec if warm reset failed */
 	if (ret == 0) {
@@ -1191,10 +1183,11 @@
 
 	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)
+	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
+				      GFP_KERNEL);
+	if (socdev->card->codec == NULL)
 		return -ENOMEM;
-	codec = socdev->codec;
+	codec = socdev->card->codec;
 	mutex_init(&codec->mutex);
 
 	codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL);
@@ -1245,7 +1238,8 @@
 	reg = ac97_read(codec, AC97_CD) & 0x7fff;
 	ac97_write(codec, AC97_CD, reg);
 
-	wm9713_add_controls(codec);
+	snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
+				ARRAY_SIZE(wm9713_snd_ac97_controls));
 	wm9713_add_widgets(codec);
 	ret = snd_soc_init_card(socdev);
 	if (ret < 0)
@@ -1265,15 +1259,15 @@
 	kfree(codec->reg_cache);
 
 cache_err:
-	kfree(socdev->codec);
-	socdev->codec = NULL;
+	kfree(socdev->card->codec);
+	socdev->card->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;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	if (codec == NULL)
 		return 0;
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index b502741..bd7392c 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -20,7 +20,7 @@
 
 config SND_DAVINCI_SOC_SFFSDR
 	tristate "SoC Audio support for SFFSDR"
-	depends on SND_DAVINCI_SOC && MACH_DAVINCI_SFFSDR
+	depends on SND_DAVINCI_SOC && MACH_SFFSDR
 	select SND_DAVINCI_SOC_I2S
 	select SND_SOC_PCM3008
 	select SFFSDR_FPGA
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 54851f3..9b90b34 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -186,7 +186,8 @@
 
 	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;
+	platform_device_add_data(evm_snd_device, &evm_snd_data,
+				 sizeof(evm_snd_data));
 
 	ret = platform_device_add_resources(evm_snd_device, evm_snd_resources,
 					    ARRAY_SIZE(evm_snd_resources));
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 0fee779..ffdb943 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -499,6 +499,13 @@
 
 #define DAVINCI_I2S_RATES	SNDRV_PCM_RATE_8000_96000
 
+static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
+	.startup	= davinci_i2s_startup,
+	.trigger	= davinci_i2s_trigger,
+	.hw_params	= davinci_i2s_hw_params,
+	.set_fmt	= davinci_i2s_set_dai_fmt,
+};
+
 struct snd_soc_dai davinci_i2s_dai = {
 	.name = "davinci-i2s",
 	.id = 0,
@@ -514,12 +521,7 @@
 		.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,
-		.set_fmt = davinci_i2s_set_dai_fmt,
-	},
+	.ops = &davinci_i2s_dai_ops,
 };
 EXPORT_SYMBOL_GPL(davinci_i2s_dai);
 
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 366049d..7af3b5b 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -286,7 +286,7 @@
 				     runtime->dma_bytes);
 }
 
-struct snd_pcm_ops davinci_pcm_ops = {
+static struct snd_pcm_ops davinci_pcm_ops = {
 	.open = 	davinci_pcm_open,
 	.close = 	davinci_pcm_close,
 	.ioctl = 	snd_pcm_lib_ioctl,
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
index 4935d1b..40eccfe 100644
--- a/sound/soc/davinci/davinci-sffsdr.c
+++ b/sound/soc/davinci/davinci-sffsdr.c
@@ -25,7 +25,9 @@
 
 #include <asm/dma.h>
 #include <asm/mach-types.h>
+#ifdef CONFIG_SFFSDR_FPGA
 #include <asm/plat-sffsdr/sffsdr-fpga.h>
+#endif
 
 #include <mach/mcbsp.h>
 #include <mach/edma.h>
@@ -34,31 +36,45 @@
 #include "davinci-pcm.h"
 #include "davinci-i2s.h"
 
+/*
+ * CLKX and CLKR are the inputs for the Sample Rate Generator.
+ * FSX and FSR are outputs, driven by the sample Rate Generator.
+ */
+#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B |	\
+		      SND_SOC_DAIFMT_CBM_CFS |	\
+		      SND_SOC_DAIFMT_IB_NF)
+
 static int sffsdr_hw_params(struct snd_pcm_substream *substream,
-			    struct snd_pcm_hw_params *params,
-			    struct snd_soc_dai *dai)
+			    struct snd_pcm_hw_params *params)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	int fs;
 	int ret = 0;
 
-	/* Set cpu DAI configuration:
-	 * CLKX and CLKR are the inputs for the Sample Rate Generator.
-	 * FSX and FSR are outputs, driven by the sample Rate Generator. */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_RIGHT_J |
-				  SND_SOC_DAIFMT_CBM_CFS |
-				  SND_SOC_DAIFMT_IB_NF);
-	if (ret < 0)
-		return ret;
-
 	/* Fsref can be 32000, 44100 or 48000. */
 	fs = params_rate(params);
 
+#ifndef CONFIG_SFFSDR_FPGA
+	/* Without the FPGA module, the Fs is fixed at 44100 Hz */
+	if (fs != 44100) {
+		pr_debug("warning: only 44.1 kHz is supported without SFFSDR FPGA module\n");
+		return -EINVAL;
+	}
+#endif
+
+	/* set cpu DAI configuration */
+	ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
+	if (ret < 0)
+		return ret;
+
 	pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs);
 
+#ifndef CONFIG_SFFSDR_FPGA
+	return 0;
+#else
 	return sffsdr_fpga_set_codec_fs(fs);
+#endif
 }
 
 static struct snd_soc_ops sffsdr_ops = {
@@ -127,7 +143,8 @@
 
 	platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata);
 	sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev;
-	sffsdr_snd_device->dev.platform_data = &sffsdr_snd_data;
+	platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data,
+				 sizeof(sffsdr_snd_data));
 
 	ret = platform_device_add_resources(sffsdr_snd_device,
 					    sffsdr_snd_resources,
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 95c12b2..9fc9082 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,17 +1,18 @@
 config SND_SOC_OF_SIMPLE
 	tristate
 
+# ASoC platform support for the Freescale MPC8610 SOC.  This compiles drivers
+# for the SSI and the Elo DMA controller.  You will still need to select
+# a platform driver and a codec driver.
 config SND_SOC_MPC8610
-	bool "ALSA SoC support for the MPC8610 SOC"
-	depends on MPC8610_HPCD
-	default y if MPC8610
-	help
-	  Say Y if you want to add support for codecs attached to the SSI
-          device on an MPC8610.
+	tristate
+	depends on MPC8610
 
 config SND_SOC_MPC8610_HPCD
-	bool "ALSA SoC support for the Freescale MPC8610 HPCD board"
-	depends on SND_SOC_MPC8610
+	tristate "ALSA SoC support for the Freescale MPC8610 HPCD board"
+	# I2C is necessary for the CS4270 driver
+	depends on MPC8610_HPCD && I2C
+	select SND_SOC_MPC8610
 	select SND_SOC_CS4270
 	select SND_SOC_CS4270_VD33_ERRATA
 	default y if MPC8610_HPCD
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 035da4a..f85134c 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -2,10 +2,13 @@
 obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o
 
 # MPC8610 HPCD Machine Support
-obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o
+snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o
+obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o
 
 # MPC8610 Platform Support
-obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o
+snd-soc-fsl-ssi-objs := fsl_ssi.o
+snd-soc-fsl-dma-objs := fsl_dma.o
+obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o
 
 obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o
 
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 64993ed..b3eb857 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -142,7 +142,8 @@
 	.info   		= SNDRV_PCM_INFO_INTERLEAVED |
 				  SNDRV_PCM_INFO_MMAP |
 				  SNDRV_PCM_INFO_MMAP_VALID |
-				  SNDRV_PCM_INFO_JOINT_DUPLEX,
+				  SNDRV_PCM_INFO_JOINT_DUPLEX |
+				  SNDRV_PCM_INFO_PAUSE,
 	.formats		= FSLDMA_PCM_FORMATS,
 	.rates  		= FSLDMA_PCM_RATES,
 	.rate_min       	= 5512,
@@ -464,11 +465,7 @@
 		sizeof(struct fsl_dma_link_descriptor);
 
 	for (i = 0; i < NUM_DMA_LINKS; i++) {
-		struct fsl_dma_link_descriptor *link = &dma_private->link[i];
-
-		link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
-		link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
-		link->next = cpu_to_be64(temp_link);
+		dma_private->link[i].next = cpu_to_be64(temp_link);
 
 		temp_link += sizeof(struct fsl_dma_link_descriptor);
 	}
@@ -525,79 +522,9 @@
  * This function obtains hardware parameters about the opened stream and
  * programs the DMA controller accordingly.
  *
- * Note that due to a quirk of the SSI's STX register, the target address
- * for the DMA operations depends on the sample size.  So we don't program
- * the dest_addr (for playback -- source_addr for capture) fields in the
- * link descriptors here.  We do that in fsl_dma_prepare()
- */
-static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *hw_params)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct fsl_dma_private *dma_private = runtime->private_data;
-
-	dma_addr_t temp_addr;   /* Pointer to next period */
-
-	unsigned int i;
-
-	/* Get all the parameters we need */
-	size_t buffer_size = params_buffer_bytes(hw_params);
-	size_t period_size = params_period_bytes(hw_params);
-
-	/* Initialize our DMA tracking variables */
-	dma_private->period_size = period_size;
-	dma_private->num_periods = params_periods(hw_params);
-	dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size;
-	dma_private->dma_buf_next = dma_private->dma_buf_phys +
-		(NUM_DMA_LINKS * period_size);
-	if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
-		dma_private->dma_buf_next = dma_private->dma_buf_phys;
-
-	/*
-	 * The actual address in STX0 (destination for playback, source for
-	 * capture) is based on the sample size, but we don't know the sample
-	 * size in this function, so we'll have to adjust that later.  See
-	 * comments in fsl_dma_prepare().
-	 *
-	 * The DMA controller does not have a cache, so the CPU does not
-	 * need to tell it to flush its cache.  However, the DMA
-	 * controller does need to tell the CPU to flush its cache.
-	 * That's what the SNOOP bit does.
-	 *
-	 * Also, even though the DMA controller supports 36-bit addressing, for
-	 * simplicity we currently support only 32-bit addresses for the audio
-	 * buffer itself.
-	 */
-	temp_addr = substream->dma_buffer.addr;
-
-	for (i = 0; i < NUM_DMA_LINKS; i++) {
-		struct fsl_dma_link_descriptor *link = &dma_private->link[i];
-
-		link->count = cpu_to_be32(period_size);
-
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			link->source_addr = cpu_to_be32(temp_addr);
-		else
-			link->dest_addr = cpu_to_be32(temp_addr);
-
-		temp_addr += period_size;
-	}
-
-	return 0;
-}
-
-/**
- * fsl_dma_prepare - prepare the DMA registers for playback.
- *
- * This function is called after the specifics of the audio data are known,
- * i.e. snd_pcm_runtime is initialized.
- *
- * In this function, we finish programming the registers of the DMA
- * controller that are dependent on the sample size.
- *
- * One of the drawbacks with big-endian is that when copying integers of
- * different sizes to a fixed-sized register, the address to which the
- * integer must be copied is dependent on the size of the integer.
+ * One drawback of big-endian is that when copying integers of different
+ * sizes to a fixed-sized register, the address to which the integer must be
+ * copied is dependent on the size of the integer.
  *
  * For example, if P is the address of a 32-bit register, and X is a 32-bit
  * integer, then X should be copied to address P.  However, if X is a 16-bit
@@ -613,22 +540,58 @@
  * and 8 bytes at a time).  So we do not support packed 24-bit samples.
  * 24-bit data must be padded to 32 bits.
  */
-static int fsl_dma_prepare(struct snd_pcm_substream *substream)
+static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *hw_params)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct fsl_dma_private *dma_private = runtime->private_data;
-	struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
-	u32 mr;
-	unsigned int i;
-	dma_addr_t ssi_sxx_phys;	/* Bus address of SSI STX register */
-	unsigned int frame_size;	/* Number of bytes per frame */
 
-	ssi_sxx_phys = dma_private->ssi_sxx_phys;
+	/* Number of bits per sample */
+	unsigned int sample_size =
+		snd_pcm_format_physical_width(params_format(hw_params));
+
+	/* Number of bytes per frame */
+	unsigned int frame_size = 2 * (sample_size / 8);
+
+	/* Bus address of SSI STX register */
+	dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys;
+
+	/* Size of the DMA buffer, in bytes */
+	size_t buffer_size = params_buffer_bytes(hw_params);
+
+	/* Number of bytes per period */
+	size_t period_size = params_period_bytes(hw_params);
+
+	/* Pointer to next period */
+	dma_addr_t temp_addr = substream->dma_buffer.addr;
+
+	/* Pointer to DMA controller */
+	struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
+
+	u32 mr; /* DMA Mode Register */
+
+	unsigned int i;
+
+	/* Initialize our DMA tracking variables */
+	dma_private->period_size = period_size;
+	dma_private->num_periods = params_periods(hw_params);
+	dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size;
+	dma_private->dma_buf_next = dma_private->dma_buf_phys +
+		(NUM_DMA_LINKS * period_size);
+
+	if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
+		/* This happens if the number of periods == NUM_DMA_LINKS */
+		dma_private->dma_buf_next = dma_private->dma_buf_phys;
 
 	mr = in_be32(&dma_channel->mr) & ~(CCSR_DMA_MR_BWC_MASK |
 		  CCSR_DMA_MR_SAHTS_MASK | CCSR_DMA_MR_DAHTS_MASK);
 
-	switch (runtime->sample_bits) {
+	/* Due to a quirk of the SSI's STX register, the target address
+	 * for the DMA operations depends on the sample size.  So we calculate
+	 * that offset here.  While we're at it, also tell the DMA controller
+	 * how much data to transfer per sample.
+	 */
+	switch (sample_size) {
 	case 8:
 		mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1;
 		ssi_sxx_phys += 3;
@@ -641,12 +604,12 @@
 		mr |= CCSR_DMA_MR_DAHTS_4 | CCSR_DMA_MR_SAHTS_4;
 		break;
 	default:
+		/* We should never get here */
 		dev_err(substream->pcm->card->dev,
-			"unsupported sample size %u\n", runtime->sample_bits);
+			"unsupported sample size %u\n", sample_size);
 		return -EINVAL;
 	}
 
-	frame_size = runtime->frame_bits / 8;
 	/*
 	 * BWC should always be a multiple of the frame size.  BWC determines
 	 * how many bytes are sent/received before the DMA controller checks the
@@ -655,7 +618,6 @@
 	 * capture, the receive FIFO is triggered when it contains one frame, so
 	 * we want to receive one frame at a time.
 	 */
-
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		mr |= CCSR_DMA_MR_BWC(2 * frame_size);
 	else
@@ -663,16 +625,48 @@
 
 	out_be32(&dma_channel->mr, mr);
 
-	/*
-	 * Program the address of the DMA transfer to/from the SSI.
-	 */
 	for (i = 0; i < NUM_DMA_LINKS; i++) {
 		struct fsl_dma_link_descriptor *link = &dma_private->link[i];
 
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		link->count = cpu_to_be32(period_size);
+
+		/* Even though the DMA controller supports 36-bit addressing,
+		 * for simplicity we allow only 32-bit addresses for the audio
+		 * buffer itself.  This was enforced in fsl_dma_new() with the
+		 * DMA mask.
+		 *
+		 * The snoop bit tells the DMA controller whether it should tell
+		 * the ECM to snoop during a read or write to an address. For
+		 * audio, we use DMA to transfer data between memory and an I/O
+		 * device (the SSI's STX0 or SRX0 register). Snooping is only
+		 * needed if there is a cache, so we need to snoop memory
+		 * addresses only.  For playback, that means we snoop the source
+		 * but not the destination.  For capture, we snoop the
+		 * destination but not the source.
+		 *
+		 * Note that failing to snoop properly is unlikely to cause
+		 * cache incoherency if the period size is larger than the
+		 * size of L1 cache.  This is because filling in one period will
+		 * flush out the data for the previous period.  So if you
+		 * increased period_bytes_min to a large enough size, you might
+		 * get more performance by not snooping, and you'll still be
+		 * okay.
+		 */
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			link->source_addr = cpu_to_be32(temp_addr);
+			link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
+
 			link->dest_addr = cpu_to_be32(ssi_sxx_phys);
-		else
+			link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP);
+		} else {
 			link->source_addr = cpu_to_be32(ssi_sxx_phys);
+			link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP);
+
+			link->dest_addr = cpu_to_be32(temp_addr);
+			link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
+		}
+
+		temp_addr += period_size;
 	}
 
 	return 0;
@@ -808,7 +802,6 @@
 	.ioctl  	= snd_pcm_lib_ioctl,
 	.hw_params      = fsl_dma_hw_params,
 	.hw_free	= fsl_dma_hw_free,
-	.prepare	= fsl_dma_prepare,
 	.pointer	= fsl_dma_pointer,
 };
 
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c6d6eb7..169bca2 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -72,6 +72,7 @@
  * @dev: struct device pointer
  * @playback: the number of playback streams opened
  * @capture: the number of capture streams opened
+ * @asynchronous: 0=synchronous mode, 1=asynchronous mode
  * @cpu_dai: the CPU DAI for this device
  * @dev_attr: the sysfs device attribute structure
  * @stats: SSI statistics
@@ -86,6 +87,7 @@
 	struct device *dev;
 	unsigned int playback;
 	unsigned int capture;
+	int asynchronous;
 	struct snd_soc_dai cpu_dai;
 	struct device_attribute dev_attr;
 
@@ -301,9 +303,10 @@
 		 *
 		 * FIXME: Little-endian samples require a different shift dir
 		 */
-		clrsetbits_be32(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK,
-			CCSR_SSI_SCR_TFR_CLK_DIS |
-			CCSR_SSI_SCR_I2S_MODE_SLAVE | CCSR_SSI_SCR_SYN);
+		clrsetbits_be32(&ssi->scr,
+			CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
+			CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE
+			| (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN));
 
 		out_be32(&ssi->stcr,
 			 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
@@ -382,10 +385,15 @@
 			SNDRV_PCM_HW_PARAM_RATE,
 			first_runtime->rate, first_runtime->rate);
 
-		snd_pcm_hw_constraint_minmax(substream->runtime,
-			SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
-			first_runtime->sample_bits,
-			first_runtime->sample_bits);
+		/* If we're in synchronous mode, then we need to constrain
+		 * the sample size as well.  We don't support independent sample
+		 * rates in asynchronous mode.
+		 */
+		if (!ssi_private->asynchronous)
+			snd_pcm_hw_constraint_minmax(substream->runtime,
+				SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+				first_runtime->sample_bits,
+				first_runtime->sample_bits);
 
 		ssi_private->second_stream = substream;
 	}
@@ -400,7 +408,7 @@
 }
 
 /**
- * fsl_ssi_prepare: prepare the SSI.
+ * fsl_ssi_hw_params - program the sample size
  *
  * Most of the SSI registers have been programmed in the startup function,
  * but the word length must be programmed here.  Unfortunately, programming
@@ -412,23 +420,27 @@
  * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
  * clock master.
  */
-static int fsl_ssi_prepare(struct snd_pcm_substream *substream,
-			   struct snd_soc_dai *dai)
+static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
-
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct fsl_ssi_private *ssi_private = cpu_dai->private_data;
 
 	if (substream == ssi_private->first_stream) {
-		u32 wl;
+		struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+		unsigned int sample_size =
+			snd_pcm_format_width(params_format(hw_params));
+		u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
 
 		/* The SSI should always be disabled at this points (SSIEN=0) */
-		wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format));
 
 		/* In synchronous mode, the SSI uses STCCR for capture */
-		clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
+		if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
+		    !ssi_private->asynchronous)
+			clrsetbits_be32(&ssi->stccr,
+					CCSR_SSI_SxCCR_WL_MASK, wl);
+		else
+			clrsetbits_be32(&ssi->srccr,
+					CCSR_SSI_SxCCR_WL_MASK, wl);
 	}
 
 	return 0;
@@ -452,28 +464,33 @@
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
+		clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
 			setbits32(&ssi->scr,
 				CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
 		} else {
-			clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
+			long timeout = jiffies + 10;
+
 			setbits32(&ssi->scr,
 				CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
 
-			/*
-			 * I think we need this delay to allow time for the SSI
-			 * to put data into its FIFO.  Without it, ALSA starts
-			 * to complain about overruns.
+			/* Wait until the SSI has filled its FIFO. Without this
+			 * delay, ALSA complains about overruns.  When the FIFO
+			 * is full, the DMA controller initiates its first
+			 * transfer.  Until then, however, the DMA's DAR
+			 * register is zero, which translates to an
+			 * out-of-bounds pointer.  This makes ALSA think an
+			 * overrun has occurred.
 			 */
-			mdelay(1);
+			while (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0) &&
+			       (jiffies < timeout));
+			if (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0))
+				return -EIO;
 		}
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 			clrbits32(&ssi->scr, CCSR_SSI_SCR_TE);
@@ -563,6 +580,15 @@
 /**
  * fsl_ssi_dai_template: template CPU DAI for the SSI
  */
+static struct snd_soc_dai_ops fsl_ssi_dai_ops = {
+	.startup	= fsl_ssi_startup,
+	.hw_params	= fsl_ssi_hw_params,
+	.shutdown	= fsl_ssi_shutdown,
+	.trigger	= fsl_ssi_trigger,
+	.set_sysclk	= fsl_ssi_set_sysclk,
+	.set_fmt	= fsl_ssi_set_fmt,
+};
+
 static struct snd_soc_dai fsl_ssi_dai_template = {
 	.playback = {
 		/* The SSI does not support monaural audio. */
@@ -577,14 +603,7 @@
 		.rates = FSLSSI_I2S_RATES,
 		.formats = FSLSSI_I2S_FORMATS,
 	},
-	.ops = {
-		.startup = fsl_ssi_startup,
-		.prepare = fsl_ssi_prepare,
-		.shutdown = fsl_ssi_shutdown,
-		.trigger = fsl_ssi_trigger,
-		.set_sysclk = fsl_ssi_set_sysclk,
-		.set_fmt = fsl_ssi_set_fmt,
-	},
+	.ops = &fsl_ssi_dai_ops,
 };
 
 /**
@@ -654,6 +673,7 @@
 	ssi_private->ssi_phys = ssi_info->ssi_phys;
 	ssi_private->irq = ssi_info->irq;
 	ssi_private->dev = ssi_info->dev;
+	ssi_private->asynchronous = ssi_info->asynchronous;
 
 	ssi_private->dev->driver_data = fsl_ssi_dai;
 
@@ -704,6 +724,14 @@
 }
 EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai);
 
+static int __init fsl_ssi_init(void)
+{
+	printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
+
+	return 0;
+}
+module_init(fsl_ssi_init);
+
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
 MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index 83b44d7..eade01f 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -208,6 +208,7 @@
  * ssi_phys: physical address of the SSI registers
  * irq: IRQ of this SSI
  * dev: struct device, used to create the sysfs statistics file
+ * asynchronous: 0=synchronous mode, 1=asynchronous mode
 */
 struct fsl_ssi_info {
 	unsigned int id;
@@ -215,6 +216,7 @@
 	dma_addr_t ssi_phys;
 	unsigned int irq;
 	struct device *dev;
+	int asynchronous;
 };
 
 struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info);
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 9eb1ce1..3aa729d 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -468,6 +468,16 @@
 /**
  * psc_i2s_dai_template: template CPU Digital Audio Interface
  */
+static struct snd_soc_dai_ops psc_i2s_dai_ops = {
+	.startup	= psc_i2s_startup,
+	.hw_params	= psc_i2s_hw_params,
+	.hw_free	= psc_i2s_hw_free,
+	.shutdown	= psc_i2s_shutdown,
+	.trigger	= psc_i2s_trigger,
+	.set_sysclk	= psc_i2s_set_sysclk,
+	.set_fmt	= psc_i2s_set_fmt,
+};
+
 static struct snd_soc_dai psc_i2s_dai_template = {
 	.playback = {
 		.channels_min = 2,
@@ -481,15 +491,7 @@
 		.rates = PSC_I2S_RATES,
 		.formats = PSC_I2S_FORMATS,
 	},
-	.ops = {
-		.startup = psc_i2s_startup,
-		.hw_params = psc_i2s_hw_params,
-		.hw_free = psc_i2s_hw_free,
-		.shutdown = psc_i2s_shutdown,
-		.trigger = psc_i2s_trigger,
-		.set_sysclk = psc_i2s_set_sysclk,
-		.set_fmt = psc_i2s_set_fmt,
-	},
+	.ops = &psc_i2s_dai_ops,
 };
 
 /* ---------------------------------------------------------------------
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index acf39a6..ef67d1c 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -353,6 +353,11 @@
 	}
 	ssi_info.irq = machine_data->ssi_irq;
 
+	/* Do we want to use asynchronous mode? */
+	ssi_info.asynchronous =
+		of_find_property(np, "fsl,ssi-asynchronous", NULL) ? 1 : 0;
+	if (ssi_info.asynchronous)
+		dev_info(&ofdev->dev, "using asynchronous mode\n");
 
 	/* Map the global utilities registers. */
 	guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 4f7f040..675732e 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -8,7 +8,7 @@
 
 config SND_OMAP_SOC_N810
 	tristate "SoC Audio support for Nokia N810"
-	depends on SND_OMAP_SOC && MACH_NOKIA_N810
+	depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C
 	select SND_OMAP_SOC_MCBSP
 	select OMAP_MUX
 	select SND_SOC_TLV320AIC3X
@@ -17,7 +17,7 @@
 
 config SND_OMAP_SOC_OSK5912
 	tristate "SoC Audio support for omap osk5912"
-	depends on SND_OMAP_SOC && MACH_OMAP_OSK
+	depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C
 	select SND_OMAP_SOC_MCBSP
 	select SND_SOC_TLV320AIC23
 	help
@@ -55,3 +55,13 @@
 	select SND_SOC_TWL4030
 	help
 	  Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
+
+config SND_OMAP_SOC_OMAP3_BEAGLE
+	tristate "SoC Audio support for OMAP3 Beagle"
+	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_BEAGLE
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TWL4030
+	help
+	  Say Y if you want to add support for SoC audio on the Beagleboard.
+
+
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 76fedd9..0c9e4ac 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -12,6 +12,7 @@
 snd-soc-omap2evm-objs := omap2evm.o
 snd-soc-sdp3430-objs := sdp3430.o
 snd-soc-omap3pandora-objs := omap3pandora.o
+snd-soc-omap3beagle-objs := omap3beagle.o
 
 obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
 obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
@@ -19,3 +20,4 @@
 obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
 obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 25593fe..a6d1178 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -40,6 +40,13 @@
 #define N810_HEADSET_AMP_GPIO	10
 #define N810_SPEAKER_AMP_GPIO	101
 
+enum {
+	N810_JACK_DISABLED,
+	N810_JACK_HP,
+	N810_JACK_HS,
+	N810_JACK_MIC,
+};
+
 static struct clk *sys_clkout2;
 static struct clk *sys_clkout2_src;
 static struct clk *func96m_clk;
@@ -50,15 +57,32 @@
 
 static void n810_ext_control(struct snd_soc_codec *codec)
 {
+	int hp = 0, line1l = 0;
+
+	switch (n810_jack_func) {
+	case N810_JACK_HS:
+		line1l = 1;
+	case N810_JACK_HP:
+		hp = 1;
+		break;
+	case N810_JACK_MIC:
+		line1l = 1;
+		break;
+	}
+
 	if (n810_spk_func)
 		snd_soc_dapm_enable_pin(codec, "Ext Spk");
 	else
 		snd_soc_dapm_disable_pin(codec, "Ext Spk");
 
-	if (n810_jack_func)
+	if (hp)
 		snd_soc_dapm_enable_pin(codec, "Headphone Jack");
 	else
 		snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+	if (line1l)
+		snd_soc_dapm_enable_pin(codec, "LINE1L");
+	else
+		snd_soc_dapm_disable_pin(codec, "LINE1L");
 
 	if (n810_dmic_func)
 		snd_soc_dapm_enable_pin(codec, "DMic");
@@ -72,7 +96,7 @@
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_codec *codec = rtd->socdev->codec;
+	struct snd_soc_codec *codec = rtd->socdev->card->codec;
 
 	snd_pcm_hw_constraint_minmax(runtime,
 				     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
@@ -229,7 +253,7 @@
 };
 
 static const char *spk_function[] = {"Off", "On"};
-static const char *jack_function[] = {"Off", "Headphone"};
+static const char *jack_function[] = {"Off", "Headphone", "Headset", "Mic"};
 static const char *input_function[] = {"ADC", "Digital Mic"};
 static const struct soc_enum n810_enum[] = {
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
@@ -248,20 +272,23 @@
 
 static int n810_aic33_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	/* Not connected */
 	snd_soc_dapm_nc_pin(codec, "MONO_LOUT");
 	snd_soc_dapm_nc_pin(codec, "HPLCOM");
 	snd_soc_dapm_nc_pin(codec, "HPRCOM");
+	snd_soc_dapm_nc_pin(codec, "MIC3L");
+	snd_soc_dapm_nc_pin(codec, "MIC3R");
+	snd_soc_dapm_nc_pin(codec, "LINE1R");
+	snd_soc_dapm_nc_pin(codec, "LINE2L");
+	snd_soc_dapm_nc_pin(codec, "LINE2R");
 
 	/* Add N810 specific controls */
-	for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
-		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&aic33_n810_controls[i], codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, aic33_n810_controls,
+				ARRAY_SIZE(aic33_n810_controls));
+	if (err < 0)
+		return err;
 
 	/* Add N810 specific widgets */
 	snd_soc_dapm_new_controls(codec, aic33_dapm_widgets,
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 05dd5ab..d6882be 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -461,6 +461,16 @@
 	return err;
 }
 
+static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
+	.startup	= omap_mcbsp_dai_startup,
+	.shutdown	= omap_mcbsp_dai_shutdown,
+	.trigger	= omap_mcbsp_dai_trigger,
+	.hw_params	= omap_mcbsp_dai_hw_params,
+	.set_fmt	= omap_mcbsp_dai_set_dai_fmt,
+	.set_clkdiv	= omap_mcbsp_dai_set_clkdiv,
+	.set_sysclk	= omap_mcbsp_dai_set_dai_sysclk,
+};
+
 #define OMAP_MCBSP_DAI_BUILDER(link_id)				\
 {								\
 	.name = "omap-mcbsp-dai-"#link_id,			\
@@ -477,15 +487,7 @@
 		.rates = OMAP_MCBSP_RATES,			\
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,		\
 	},							\
-	.ops = {						\
-		.startup = omap_mcbsp_dai_startup,		\
-		.shutdown = omap_mcbsp_dai_shutdown,		\
-		.trigger = omap_mcbsp_dai_trigger,		\
-		.hw_params = omap_mcbsp_dai_hw_params,		\
-		.set_fmt = omap_mcbsp_dai_set_dai_fmt,		\
-		.set_clkdiv = omap_mcbsp_dai_set_clkdiv,	\
-		.set_sysclk = omap_mcbsp_dai_set_dai_sysclk,	\
-	},							\
+	.ops = &omap_mcbsp_dai_ops,				\
 	.private_data = &mcbsp_data[(link_id)].bus_id,		\
 }
 
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index dd3bb29..8e1431c 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -265,7 +265,7 @@
 				     runtime->dma_bytes);
 }
 
-struct snd_pcm_ops omap_pcm_ops = {
+static struct snd_pcm_ops omap_pcm_ops = {
 	.open		= omap_pcm_open,
 	.close		= omap_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index fcc2f5d..fe282d4 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -143,7 +143,7 @@
 };
 
 static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = {
-	SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
+	SND_SOC_DAPM_MIC("Mic (internal)", NULL),
 	SND_SOC_DAPM_MIC("Mic (external)", NULL),
 	SND_SOC_DAPM_LINE("Line In", NULL),
 };
@@ -155,16 +155,33 @@
 };
 
 static const struct snd_soc_dapm_route omap3pandora_in_map[] = {
-	{"INL", NULL, "Line In"},
-	{"INR", NULL, "Line In"},
-	{"INL", NULL, "Mic (Internal)"},
-	{"INR", NULL, "Mic (external)"},
+	{"AUXL", NULL, "Line In"},
+	{"AUXR", NULL, "Line In"},
+
+	{"MAINMIC", NULL, "Mic Bias 1"},
+	{"Mic Bias 1", NULL, "Mic (internal)"},
+
+	{"SUBMIC", NULL, "Mic Bias 2"},
+	{"Mic Bias 2", NULL, "Mic (external)"},
 };
 
 static int omap3pandora_out_init(struct snd_soc_codec *codec)
 {
 	int ret;
 
+	/* All TWL4030 output pins are floating */
+	snd_soc_dapm_nc_pin(codec, "OUTL");
+	snd_soc_dapm_nc_pin(codec, "OUTR");
+	snd_soc_dapm_nc_pin(codec, "EARPIECE");
+	snd_soc_dapm_nc_pin(codec, "PREDRIVEL");
+	snd_soc_dapm_nc_pin(codec, "PREDRIVER");
+	snd_soc_dapm_nc_pin(codec, "HSOL");
+	snd_soc_dapm_nc_pin(codec, "HSOR");
+	snd_soc_dapm_nc_pin(codec, "CARKITL");
+	snd_soc_dapm_nc_pin(codec, "CARKITR");
+	snd_soc_dapm_nc_pin(codec, "HFL");
+	snd_soc_dapm_nc_pin(codec, "HFR");
+
 	ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets,
 				ARRAY_SIZE(omap3pandora_out_dapm_widgets));
 	if (ret < 0)
@@ -180,18 +197,11 @@
 {
 	int ret;
 
-	/* All TWL4030 output pins are floating */
-	snd_soc_dapm_nc_pin(codec, "OUTL"),
-	snd_soc_dapm_nc_pin(codec, "OUTR"),
-	snd_soc_dapm_nc_pin(codec, "EARPIECE"),
-	snd_soc_dapm_nc_pin(codec, "PREDRIVEL"),
-	snd_soc_dapm_nc_pin(codec, "PREDRIVER"),
-	snd_soc_dapm_nc_pin(codec, "HSOL"),
-	snd_soc_dapm_nc_pin(codec, "HSOR"),
-	snd_soc_dapm_nc_pin(codec, "CARKITL"),
-	snd_soc_dapm_nc_pin(codec, "CARKITR"),
-	snd_soc_dapm_nc_pin(codec, "HFL"),
-	snd_soc_dapm_nc_pin(codec, "HFR"),
+	/* Not comnnected */
+	snd_soc_dapm_nc_pin(codec, "HSMIC");
+	snd_soc_dapm_nc_pin(codec, "CARKITMIC");
+	snd_soc_dapm_nc_pin(codec, "DIGIMIC0");
+	snd_soc_dapm_nc_pin(codec, "DIGIMIC1");
 
 	ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets,
 				ARRAY_SIZE(omap3pandora_in_dapm_widgets));
@@ -251,10 +261,9 @@
 {
 	int ret;
 
-	if (!machine_is_omap3_pandora()) {
-		pr_debug(PREFIX "Not OMAP3 Pandora\n");
+	if (!machine_is_omap3_pandora())
 		return -ENODEV;
-	}
+
 	pr_info("OMAP3 Pandora SoC init\n");
 
 	ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power");
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index cd41a94..a952a4e 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -186,13 +186,6 @@
 		return -ENODEV;
 	}
 
-	if (clk_get_usecount(tlv320aic23_mclk) > 0) {
-		/* MCLK is already in use */
-		printk(KERN_WARNING
-		       "MCLK in use at %d Hz. We change it to %d Hz\n",
-		       (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK);
-	}
-
 	/*
 	 * Configure 12 MHz output on MCLK.
 	 */
@@ -205,9 +198,8 @@
 		}
 	}
 
-	printk(KERN_INFO "MCLK = %d [%d], usecount = %d\n",
-	       (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK,
-	       clk_get_usecount(tlv320aic23_mclk));
+	printk(KERN_INFO "MCLK = %d [%d]\n",
+	       (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK);
 
 	return 0;
 err1:
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index e226fa7..10f1c86 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -28,6 +28,7 @@
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/jack.h>
 
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
@@ -38,6 +39,8 @@
 #include "omap-pcm.h"
 #include "../codecs/twl4030.h"
 
+static struct snd_soc_card snd_soc_sdp3430;
+
 static int sdp3430_hw_params(struct snd_pcm_substream *substream,
 	struct snd_pcm_hw_params *params)
 {
@@ -81,12 +84,121 @@
 	.hw_params = sdp3430_hw_params,
 };
 
+/* Headset jack */
+static struct snd_soc_jack hs_jack;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+	{
+		.pin = "Headset Mic",
+		.mask = SND_JACK_MICROPHONE,
+	},
+	{
+		.pin = "Headset Stereophone",
+		.mask = SND_JACK_HEADPHONE,
+	},
+};
+
+/* Headset jack detection gpios */
+static struct snd_soc_jack_gpio hs_jack_gpios[] = {
+	{
+		.gpio = (OMAP_MAX_GPIO_LINES + 2),
+		.name = "hsdet-gpio",
+		.report = SND_JACK_HEADSET,
+		.debounce_time = 200,
+	},
+};
+
+/* SDP3430 machine DAPM */
+static const struct snd_soc_dapm_widget sdp3430_twl4030_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Ext Mic", NULL),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* External Mics: MAINMIC, SUBMIC with bias*/
+	{"MAINMIC", NULL, "Mic Bias 1"},
+	{"SUBMIC", NULL, "Mic Bias 2"},
+	{"Mic Bias 1", NULL, "Ext Mic"},
+	{"Mic Bias 2", NULL, "Ext Mic"},
+
+	/* External Speakers: HFL, HFR */
+	{"Ext Spk", NULL, "HFL"},
+	{"Ext Spk", NULL, "HFR"},
+
+	/* Headset Mic: HSMIC with bias */
+	{"HSMIC", NULL, "Headset Mic Bias"},
+	{"Headset Mic Bias", NULL, "Headset Mic"},
+
+	/* Headset Stereophone (Headphone): HSOL, HSOR */
+	{"Headset Stereophone", NULL, "HSOL"},
+	{"Headset Stereophone", NULL, "HSOR"},
+};
+
+static int sdp3430_twl4030_init(struct snd_soc_codec *codec)
+{
+	int ret;
+
+	/* Add SDP3430 specific widgets */
+	ret = snd_soc_dapm_new_controls(codec, sdp3430_twl4030_dapm_widgets,
+				ARRAY_SIZE(sdp3430_twl4030_dapm_widgets));
+	if (ret)
+		return ret;
+
+	/* Set up SDP3430 specific audio path audio_map */
+	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+	/* SDP3430 connected pins */
+	snd_soc_dapm_enable_pin(codec, "Ext Mic");
+	snd_soc_dapm_enable_pin(codec, "Ext Spk");
+	snd_soc_dapm_disable_pin(codec, "Headset Mic");
+	snd_soc_dapm_disable_pin(codec, "Headset Stereophone");
+
+	/* TWL4030 not connected pins */
+	snd_soc_dapm_nc_pin(codec, "AUXL");
+	snd_soc_dapm_nc_pin(codec, "AUXR");
+	snd_soc_dapm_nc_pin(codec, "CARKITMIC");
+	snd_soc_dapm_nc_pin(codec, "DIGIMIC0");
+	snd_soc_dapm_nc_pin(codec, "DIGIMIC1");
+
+	snd_soc_dapm_nc_pin(codec, "OUTL");
+	snd_soc_dapm_nc_pin(codec, "OUTR");
+	snd_soc_dapm_nc_pin(codec, "EARPIECE");
+	snd_soc_dapm_nc_pin(codec, "PREDRIVEL");
+	snd_soc_dapm_nc_pin(codec, "PREDRIVER");
+	snd_soc_dapm_nc_pin(codec, "CARKITL");
+	snd_soc_dapm_nc_pin(codec, "CARKITR");
+
+	ret = snd_soc_dapm_sync(codec);
+	if (ret)
+		return ret;
+
+	/* Headset jack detection */
+	ret = snd_soc_jack_new(&snd_soc_sdp3430, "Headset Jack",
+				SND_JACK_HEADSET, &hs_jack);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+				hs_jack_pins);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
+				hs_jack_gpios);
+
+	return ret;
+}
+
 /* Digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link sdp3430_dai = {
 	.name = "TWL4030",
 	.stream_name = "TWL4030",
 	.cpu_dai = &omap_mcbsp_dai[0],
 	.codec_dai = &twl4030_dai,
+	.init = sdp3430_twl4030_init,
 	.ops = &sdp3430_ops,
 };
 
@@ -142,6 +254,9 @@
 
 static void __exit sdp3430_soc_exit(void)
 {
+	snd_soc_jack_free_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
+				hs_jack_gpios);
+
 	platform_device_unregister(sdp3430_snd_device);
 }
 module_exit(sdp3430_soc_exit);
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index f82e106..5998ab3 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -61,6 +61,24 @@
 	  Say Y if you want to add support for SoC audio on Sharp
 	  Zaurus SL-C6000x models (Tosa).
 
+config SND_PXA2XX_SOC_E740
+	tristate "SoC AC97 Audio support for e740"
+	depends on SND_PXA2XX_SOC && MACH_E740
+	select SND_SOC_WM9705
+	select SND_PXA2XX_SOC_AC97
+	help
+	  Say Y if you want to add support for SoC audio on the
+	  toshiba e740 PDA
+
+config SND_PXA2XX_SOC_E750
+	tristate "SoC AC97 Audio support for e750"
+	depends on SND_PXA2XX_SOC && MACH_E750
+	select SND_SOC_WM9705
+	select SND_PXA2XX_SOC_AC97
+	help
+	  Say Y if you want to add support for SoC audio on the
+	  toshiba e750 PDA
+
 config SND_PXA2XX_SOC_E800
 	tristate "SoC AC97 Audio support for e800"
 	depends on SND_PXA2XX_SOC && MACH_E800
@@ -97,3 +115,12 @@
 	help
 	  Say Y if you want to add support for SoC audio on the
 	  Marvell Zylonite reference platform.
+
+config SND_PXA2XX_SOC_MIOA701
+        tristate "SoC Audio support for MIO A701"
+        depends on SND_PXA2XX_SOC && MACH_MIOA701
+        select SND_PXA2XX_SOC_AC97
+        select SND_SOC_WM9713
+        help
+          Say Y if you want to add support for SoC audio on the
+          MIO A701.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 08a9f27..8ed881c 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -13,17 +13,23 @@
 snd-soc-corgi-objs := corgi.o
 snd-soc-poodle-objs := poodle.o
 snd-soc-tosa-objs := tosa.o
+snd-soc-e740-objs := e740_wm9705.o
+snd-soc-e750-objs := e750_wm9705.o
 snd-soc-e800-objs := e800_wm9712.o
 snd-soc-spitz-objs := spitz.o
 snd-soc-em-x270-objs := em-x270.o
 snd-soc-palm27x-objs := palm27x.o
 snd-soc-zylonite-objs := zylonite.o
+snd-soc-mioa701-objs := mioa701_wm9713.o
 
 obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
 obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
 obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
+obj-$(CONFIG_SND_PXA2XX_SOC_E740) += snd-soc-e740.o
+obj-$(CONFIG_SND_PXA2XX_SOC_E750) += snd-soc-e750.o
 obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
 obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
 obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
 obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
+obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
 obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 1ba25a5..02263e5 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/timer.h>
+#include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
@@ -100,7 +101,7 @@
 static int corgi_startup(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_codec *codec = rtd->socdev->codec;
+	struct snd_soc_codec *codec = rtd->socdev->card->codec;
 
 	/* check the jack status at stream startup */
 	corgi_ext_control(codec);
@@ -275,18 +276,16 @@
  */
 static int corgi_wm8731_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	snd_soc_dapm_nc_pin(codec, "LLINEIN");
 	snd_soc_dapm_nc_pin(codec, "RLINEIN");
 
 	/* 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));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, wm8731_corgi_controls,
+				ARRAY_SIZE(wm8731_corgi_controls));
+	if (err < 0)
+		return err;
 
 	/* Add corgi specific widgets */
 	snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
@@ -317,19 +316,44 @@
 	.num_links = 1,
 };
 
-/* corgi audio private data */
-static struct wm8731_setup_data corgi_wm8731_setup = {
-	.i2c_bus = 0,
-	.i2c_address = 0x1b,
-};
-
 /* corgi audio subsystem */
 static struct snd_soc_device corgi_snd_devdata = {
 	.card = &snd_soc_corgi,
 	.codec_dev = &soc_codec_dev_wm8731,
-	.codec_data = &corgi_wm8731_setup,
 };
 
+/*
+ * FIXME: This is a temporary bodge to avoid cross-tree merge issues.
+ * New drivers should register the wm8731 I2C device in the machine
+ * setup code (under arch/arm for ARM systems).
+ */
+static int wm8731_i2c_register(void)
+{
+	struct i2c_board_info info;
+	struct i2c_adapter *adapter;
+	struct i2c_client *client;
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	info.addr = 0x1b;
+	strlcpy(info.type, "wm8731", I2C_NAME_SIZE);
+
+	adapter = i2c_get_adapter(0);
+	if (!adapter) {
+		printk(KERN_ERR "can't get i2c adapter 0\n");
+		return -ENODEV;
+	}
+
+	client = i2c_new_device(adapter, &info);
+	i2c_put_adapter(adapter);
+	if (!client) {
+		printk(KERN_ERR "can't add i2c device at 0x%x\n",
+			(unsigned int)info.addr);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static struct platform_device *corgi_snd_device;
 
 static int __init corgi_init(void)
@@ -340,6 +364,10 @@
 	      machine_is_husky()))
 		return -ENODEV;
 
+	ret = wm8731_i2c_register();
+	if (ret != 0)
+		return ret;
+
 	corgi_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!corgi_snd_device)
 		return -ENOMEM;
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c
new file mode 100644
index 0000000..7cd2f89
--- /dev/null
+++ b/sound/soc/pxa/e740_wm9705.c
@@ -0,0 +1,211 @@
+/*
+ * e740-wm9705.c  --  SoC audio for e740
+ *
+ * Copyright 2007 (c) Ian Molton <spyro@f2s.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 ONLY.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/gpio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <mach/audio.h>
+#include <mach/eseries-gpio.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/wm9705.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+
+
+#define E740_AUDIO_OUT 1
+#define E740_AUDIO_IN  2
+
+static int e740_audio_power;
+
+static void e740_sync_audio_power(int status)
+{
+	gpio_set_value(GPIO_E740_WM9705_nAVDD2, !status);
+	gpio_set_value(GPIO_E740_AMP_ON, (status & E740_AUDIO_OUT) ? 1 : 0);
+	gpio_set_value(GPIO_E740_MIC_ON, (status & E740_AUDIO_IN) ? 1 : 0);
+}
+
+static int e740_mic_amp_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	if (event & SND_SOC_DAPM_PRE_PMU)
+		e740_audio_power |= E740_AUDIO_IN;
+	else if (event & SND_SOC_DAPM_POST_PMD)
+		e740_audio_power &= ~E740_AUDIO_IN;
+
+	e740_sync_audio_power(e740_audio_power);
+
+	return 0;
+}
+
+static int e740_output_amp_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	if (event & SND_SOC_DAPM_PRE_PMU)
+		e740_audio_power |= E740_AUDIO_OUT;
+	else if (event & SND_SOC_DAPM_POST_PMD)
+		e740_audio_power &= ~E740_AUDIO_OUT;
+
+	e740_sync_audio_power(e740_audio_power);
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget e740_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
+	SND_SOC_DAPM_PGA_E("Output Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+			e740_output_amp_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("Mic Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+			e740_mic_amp_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	{"Output Amp", NULL, "LOUT"},
+	{"Output Amp", NULL, "ROUT"},
+	{"Output Amp", NULL, "MONOOUT"},
+
+	{"Speaker", NULL, "Output Amp"},
+	{"Headphone Jack", NULL, "Output Amp"},
+
+	{"MIC1", NULL, "Mic Amp"},
+	{"Mic Amp", NULL, "Mic (Internal)"},
+};
+
+static int e740_ac97_init(struct snd_soc_codec *codec)
+{
+	snd_soc_dapm_nc_pin(codec, "HPOUTL");
+	snd_soc_dapm_nc_pin(codec, "HPOUTR");
+	snd_soc_dapm_nc_pin(codec, "PHONE");
+	snd_soc_dapm_nc_pin(codec, "LINEINL");
+	snd_soc_dapm_nc_pin(codec, "LINEINR");
+	snd_soc_dapm_nc_pin(codec, "CDINL");
+	snd_soc_dapm_nc_pin(codec, "CDINR");
+	snd_soc_dapm_nc_pin(codec, "PCBEEP");
+	snd_soc_dapm_nc_pin(codec, "MIC2");
+
+	snd_soc_dapm_new_controls(codec, e740_dapm_widgets,
+					ARRAY_SIZE(e740_dapm_widgets));
+
+	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+	snd_soc_dapm_sync(codec);
+
+	return 0;
+}
+
+static struct snd_soc_dai_link e740_dai[] = {
+	{
+		.name = "AC97",
+		.stream_name = "AC97 HiFi",
+		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+		.codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI],
+		.init = e740_ac97_init,
+	},
+	{
+		.name = "AC97 Aux",
+		.stream_name = "AC97 Aux",
+		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+		.codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX],
+	},
+};
+
+static struct snd_soc_card e740 = {
+	.name = "Toshiba e740",
+	.platform = &pxa2xx_soc_platform,
+	.dai_link = e740_dai,
+	.num_links = ARRAY_SIZE(e740_dai),
+};
+
+static struct snd_soc_device e740_snd_devdata = {
+	.card = &e740,
+	.codec_dev = &soc_codec_dev_wm9705,
+};
+
+static struct platform_device *e740_snd_device;
+
+static int __init e740_init(void)
+{
+	int ret;
+
+	if (!machine_is_e740())
+		return -ENODEV;
+
+	ret = gpio_request(GPIO_E740_MIC_ON,  "Mic amp");
+	if (ret)
+		return ret;
+
+	ret = gpio_request(GPIO_E740_AMP_ON, "Output amp");
+	if (ret)
+		goto free_mic_amp_gpio;
+
+	ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power");
+	if (ret)
+		goto free_op_amp_gpio;
+
+	/* Disable audio */
+	ret = gpio_direction_output(GPIO_E740_MIC_ON, 0);
+	if (ret)
+		goto free_apwr_gpio;
+	ret = gpio_direction_output(GPIO_E740_AMP_ON, 0);
+	if (ret)
+		goto free_apwr_gpio;
+	ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1);
+	if (ret)
+		goto free_apwr_gpio;
+
+	e740_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!e740_snd_device) {
+		ret = -ENOMEM;
+		goto free_apwr_gpio;
+	}
+
+	platform_set_drvdata(e740_snd_device, &e740_snd_devdata);
+	e740_snd_devdata.dev = &e740_snd_device->dev;
+	ret = platform_device_add(e740_snd_device);
+
+	if (!ret)
+		return 0;
+
+/* Fail gracefully */
+	platform_device_put(e740_snd_device);
+free_apwr_gpio:
+	gpio_free(GPIO_E740_WM9705_nAVDD2);
+free_op_amp_gpio:
+	gpio_free(GPIO_E740_AMP_ON);
+free_mic_amp_gpio:
+	gpio_free(GPIO_E740_MIC_ON);
+
+	return ret;
+}
+
+static void __exit e740_exit(void)
+{
+	platform_device_unregister(e740_snd_device);
+}
+
+module_init(e740_init);
+module_exit(e740_exit);
+
+/* Module information */
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("ALSA SoC driver for e740");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c
new file mode 100644
index 0000000..8dceccc
--- /dev/null
+++ b/sound/soc/pxa/e750_wm9705.c
@@ -0,0 +1,187 @@
+/*
+ * e750-wm9705.c  --  SoC audio for e750
+ *
+ * Copyright 2007 (c) Ian Molton <spyro@f2s.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 ONLY.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/gpio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <mach/audio.h>
+#include <mach/eseries-gpio.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/wm9705.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+
+static int e750_spk_amp_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	if (event & SND_SOC_DAPM_PRE_PMU)
+		gpio_set_value(GPIO_E750_SPK_AMP_OFF, 0);
+	else if (event & SND_SOC_DAPM_POST_PMD)
+		gpio_set_value(GPIO_E750_SPK_AMP_OFF, 1);
+
+	return 0;
+}
+
+static int e750_hp_amp_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	if (event & SND_SOC_DAPM_PRE_PMU)
+		gpio_set_value(GPIO_E750_HP_AMP_OFF, 0);
+	else if (event & SND_SOC_DAPM_POST_PMD)
+		gpio_set_value(GPIO_E750_HP_AMP_OFF, 1);
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget e750_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
+	SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+			e750_hp_amp_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+			e750_spk_amp_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	{"Headphone Amp", NULL, "HPOUTL"},
+	{"Headphone Amp", NULL, "HPOUTR"},
+	{"Headphone Jack", NULL, "Headphone Amp"},
+
+	{"Speaker Amp", NULL, "MONOOUT"},
+	{"Speaker", NULL, "Speaker Amp"},
+
+	{"MIC1", NULL, "Mic (Internal)"},
+};
+
+static int e750_ac97_init(struct snd_soc_codec *codec)
+{
+	snd_soc_dapm_nc_pin(codec, "LOUT");
+	snd_soc_dapm_nc_pin(codec, "ROUT");
+	snd_soc_dapm_nc_pin(codec, "PHONE");
+	snd_soc_dapm_nc_pin(codec, "LINEINL");
+	snd_soc_dapm_nc_pin(codec, "LINEINR");
+	snd_soc_dapm_nc_pin(codec, "CDINL");
+	snd_soc_dapm_nc_pin(codec, "CDINR");
+	snd_soc_dapm_nc_pin(codec, "PCBEEP");
+	snd_soc_dapm_nc_pin(codec, "MIC2");
+
+	snd_soc_dapm_new_controls(codec, e750_dapm_widgets,
+					ARRAY_SIZE(e750_dapm_widgets));
+
+	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+	snd_soc_dapm_sync(codec);
+
+	return 0;
+}
+
+static struct snd_soc_dai_link e750_dai[] = {
+	{
+		.name = "AC97",
+		.stream_name = "AC97 HiFi",
+		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+		.codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI],
+		.init = e750_ac97_init,
+		/* use ops to check startup state */
+	},
+	{
+		.name = "AC97 Aux",
+		.stream_name = "AC97 Aux",
+		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+		.codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX],
+	},
+};
+
+static struct snd_soc_card e750 = {
+	.name = "Toshiba e750",
+	.platform = &pxa2xx_soc_platform,
+	.dai_link = e750_dai,
+	.num_links = ARRAY_SIZE(e750_dai),
+};
+
+static struct snd_soc_device e750_snd_devdata = {
+	.card = &e750,
+	.codec_dev = &soc_codec_dev_wm9705,
+};
+
+static struct platform_device *e750_snd_device;
+
+static int __init e750_init(void)
+{
+	int ret;
+
+	if (!machine_is_e750())
+		return -ENODEV;
+
+	ret = gpio_request(GPIO_E750_HP_AMP_OFF,  "Headphone amp");
+	if (ret)
+		return ret;
+
+	ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp");
+	if (ret)
+		goto free_hp_amp_gpio;
+
+	ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1);
+	if (ret)
+		goto free_spk_amp_gpio;
+
+	ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1);
+	if (ret)
+		goto free_spk_amp_gpio;
+
+	e750_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!e750_snd_device) {
+		ret = -ENOMEM;
+		goto free_spk_amp_gpio;
+	}
+
+	platform_set_drvdata(e750_snd_device, &e750_snd_devdata);
+	e750_snd_devdata.dev = &e750_snd_device->dev;
+	ret = platform_device_add(e750_snd_device);
+
+	if (!ret)
+		return 0;
+
+/* Fail gracefully */
+	platform_device_put(e750_snd_device);
+free_spk_amp_gpio:
+	gpio_free(GPIO_E750_SPK_AMP_OFF);
+free_hp_amp_gpio:
+	gpio_free(GPIO_E750_HP_AMP_OFF);
+
+	return ret;
+}
+
+static void __exit e750_exit(void)
+{
+	platform_device_unregister(e750_snd_device);
+	gpio_free(GPIO_E750_SPK_AMP_OFF);
+	gpio_free(GPIO_E750_HP_AMP_OFF);
+}
+
+module_init(e750_init);
+module_exit(e750_exit);
+
+/* Module information */
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("ALSA SoC driver for e750");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index 2e3386d..bc019cd 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -1,8 +1,6 @@
 /*
  * e800-wm9712.c  --  SoC audio for e800
  *
- * Based on tosa.c
- *
  * Copyright 2007 (c) Ian Molton <spyro@f2s.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -13,7 +11,7 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/device.h>
+#include <linux/gpio.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -21,23 +19,85 @@
 #include <sound/soc-dapm.h>
 
 #include <asm/mach-types.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
 #include <mach/audio.h>
+#include <mach/eseries-gpio.h>
 
 #include "../codecs/wm9712.h"
 #include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 
-static struct snd_soc_card e800;
+static int e800_spk_amp_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	if (event & SND_SOC_DAPM_PRE_PMU)
+		gpio_set_value(GPIO_E800_SPK_AMP_ON, 1);
+	else if (event & SND_SOC_DAPM_POST_PMD)
+		gpio_set_value(GPIO_E800_SPK_AMP_ON, 0);
+
+	return 0;
+}
+
+static int e800_hp_amp_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	if (event & SND_SOC_DAPM_PRE_PMU)
+		gpio_set_value(GPIO_E800_HP_AMP_OFF, 0);
+	else if (event & SND_SOC_DAPM_POST_PMD)
+		gpio_set_value(GPIO_E800_HP_AMP_OFF, 1);
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget e800_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Mic (Internal1)", NULL),
+	SND_SOC_DAPM_MIC("Mic (Internal2)", NULL),
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+			e800_hp_amp_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+			e800_spk_amp_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	{"Headphone Jack", NULL, "HPOUTL"},
+	{"Headphone Jack", NULL, "HPOUTR"},
+	{"Headphone Jack", NULL, "Headphone Amp"},
+
+	{"Speaker Amp", NULL, "MONOOUT"},
+	{"Speaker", NULL, "Speaker Amp"},
+
+	{"MIC1", NULL, "Mic (Internal1)"},
+	{"MIC2", NULL, "Mic (Internal2)"},
+};
+
+static int e800_ac97_init(struct snd_soc_codec *codec)
+{
+	snd_soc_dapm_new_controls(codec, e800_dapm_widgets,
+					ARRAY_SIZE(e800_dapm_widgets));
+
+	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+	snd_soc_dapm_sync(codec);
+
+	return 0;
+}
 
 static struct snd_soc_dai_link e800_dai[] = {
-{
-	.name = "AC97 Aux",
-	.stream_name = "AC97 Aux",
-	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
-	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
-},
+	{
+		.name = "AC97",
+		.stream_name = "AC97 HiFi",
+		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+		.codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+		.init = e800_ac97_init,
+	},
+	{
+		.name = "AC97 Aux",
+		.stream_name = "AC97 Aux",
+		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+		.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
+	},
 };
 
 static struct snd_soc_card e800 = {
@@ -61,6 +121,22 @@
 	if (!machine_is_e800())
 		return -ENODEV;
 
+	ret = gpio_request(GPIO_E800_HP_AMP_OFF,  "Headphone amp");
+	if (ret)
+		return ret;
+
+	ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp");
+	if (ret)
+		goto free_hp_amp_gpio;
+
+	ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1);
+	if (ret)
+		goto free_spk_amp_gpio;
+
+	ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1);
+	if (ret)
+		goto free_spk_amp_gpio;
+
 	e800_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!e800_snd_device)
 		return -ENOMEM;
@@ -69,8 +145,15 @@
 	e800_snd_devdata.dev = &e800_snd_device->dev;
 	ret = platform_device_add(e800_snd_device);
 
-	if (ret)
-		platform_device_put(e800_snd_device);
+	if (!ret)
+		return 0;
+
+/* Fail gracefully */
+	platform_device_put(e800_snd_device);
+free_spk_amp_gpio:
+	gpio_free(GPIO_E800_SPK_AMP_ON);
+free_hp_amp_gpio:
+	gpio_free(GPIO_E800_HP_AMP_OFF);
 
 	return ret;
 }
@@ -78,6 +161,8 @@
 static void __exit e800_exit(void)
 {
 	platform_device_unregister(e800_snd_device);
+	gpio_free(GPIO_E800_SPK_AMP_ON);
+	gpio_free(GPIO_E800_HP_AMP_OFF);
 }
 
 module_init(e800_init);
@@ -86,4 +171,4 @@
 /* Module information */
 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
 MODULE_DESCRIPTION("ALSA SoC driver for e800");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
new file mode 100644
index 0000000..19eda8b
--- /dev/null
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -0,0 +1,250 @@
+/*
+ * Handles the Mitac mioa701 SoC system
+ *
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation in 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
+ *
+ * This is a little schema of the sound interconnections :
+ *
+ *    Sagem X200                 Wolfson WM9713
+ *    +--------+             +-------------------+      Rear Speaker
+ *    |        |             |                   |           /-+
+ *    |        +--->----->---+MONOIN         SPKL+--->----+-+  |
+ *    |  GSM   |             |                   |        | |  |
+ *    |        +--->----->---+PCBEEP         SPKR+--->----+-+  |
+ *    |  CHIP  |             |                   |           \-+
+ *    |        +---<-----<---+MONO               |
+ *    |        |             |                   |      Front Speaker
+ *    +--------+             |                   |           /-+
+ *                           |                HPL+--->----+-+  |
+ *                           |                   |        | |  |
+ *                           |               OUT3+--->----+-+  |
+ *                           |                   |           \-+
+ *                           |                   |
+ *                           |                   |     Front Micro
+ *                           |                   |         +
+ *                           |               MIC1+-----<--+o+
+ *                           |                   |         +
+ *                           +-------------------+        ---
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <mach/audio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+#include "../codecs/wm9713.h"
+
+#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
+
+#define AC97_GPIO_PULL		0x58
+
+/* Use GPIO8 for rear speaker amplifier */
+static int rear_amp_power(struct snd_soc_codec *codec, int power)
+{
+	unsigned short reg;
+
+	if (power) {
+		reg = snd_soc_read(codec, AC97_GPIO_CFG);
+		snd_soc_write(codec, AC97_GPIO_CFG, reg | 0x0100);
+		reg = snd_soc_read(codec, AC97_GPIO_PULL);
+		snd_soc_write(codec, AC97_GPIO_PULL, reg | (1<<15));
+	} else {
+		reg = snd_soc_read(codec, AC97_GPIO_CFG);
+		snd_soc_write(codec, AC97_GPIO_CFG, reg & ~0x0100);
+		reg = snd_soc_read(codec, AC97_GPIO_PULL);
+		snd_soc_write(codec, AC97_GPIO_PULL, reg & ~(1<<15));
+	}
+
+	return 0;
+}
+
+static int rear_amp_event(struct snd_soc_dapm_widget *widget,
+			  struct snd_kcontrol *kctl, int event)
+{
+	struct snd_soc_codec *codec = widget->codec;
+
+	return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event));
+}
+
+/* mioa701 machine dapm widgets */
+static const struct snd_soc_dapm_widget mioa701_dapm_widgets[] = {
+	SND_SOC_DAPM_SPK("Front Speaker", NULL),
+	SND_SOC_DAPM_SPK("Rear Speaker", rear_amp_event),
+	SND_SOC_DAPM_MIC("Headset", NULL),
+	SND_SOC_DAPM_LINE("GSM Line Out", NULL),
+	SND_SOC_DAPM_LINE("GSM Line In", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Front Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* Call Mic */
+	{"Mic Bias", NULL, "Front Mic"},
+	{"MIC1", NULL, "Mic Bias"},
+
+	/* Headset Mic */
+	{"LINEL", NULL, "Headset Mic"},
+	{"LINER", NULL, "Headset Mic"},
+
+	/* GSM Module */
+	{"MONOIN", NULL, "GSM Line Out"},
+	{"PCBEEP", NULL, "GSM Line Out"},
+	{"GSM Line In", NULL, "MONO"},
+
+	/* headphone connected to HPL, HPR */
+	{"Headset", NULL, "HPL"},
+	{"Headset", NULL, "HPR"},
+
+	/* front speaker connected to HPL, OUT3 */
+	{"Front Speaker", NULL, "HPL"},
+	{"Front Speaker", NULL, "OUT3"},
+
+	/* rear speaker connected to SPKL, SPKR */
+	{"Rear Speaker", NULL, "SPKL"},
+	{"Rear Speaker", NULL, "SPKR"},
+};
+
+static int mioa701_wm9713_init(struct snd_soc_codec *codec)
+{
+	unsigned short reg;
+
+	/* Add mioa701 specific widgets */
+	snd_soc_dapm_new_controls(codec, ARRAY_AND_SIZE(mioa701_dapm_widgets));
+
+	/* Set up mioa701 specific audio path audio_mapnects */
+	snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map));
+
+	/* Prepare GPIO8 for rear speaker amplifier */
+	reg = codec->read(codec, AC97_GPIO_CFG);
+	codec->write(codec, AC97_GPIO_CFG, reg | 0x0100);
+
+	/* Prepare MIC input */
+	reg = codec->read(codec, AC97_3D_CONTROL);
+	codec->write(codec, AC97_3D_CONTROL, reg | 0xc000);
+
+	snd_soc_dapm_enable_pin(codec, "Front Speaker");
+	snd_soc_dapm_enable_pin(codec, "Rear Speaker");
+	snd_soc_dapm_enable_pin(codec, "Front Mic");
+	snd_soc_dapm_enable_pin(codec, "GSM Line In");
+	snd_soc_dapm_enable_pin(codec, "GSM Line Out");
+	snd_soc_dapm_sync(codec);
+
+	return 0;
+}
+
+static struct snd_soc_ops mioa701_ops;
+
+static struct snd_soc_dai_link mioa701_dai[] = {
+	{
+		.name = "AC97",
+		.stream_name = "AC97 HiFi",
+		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+		.codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
+		.init = mioa701_wm9713_init,
+		.ops = &mioa701_ops,
+	},
+	{
+		.name = "AC97 Aux",
+		.stream_name = "AC97 Aux",
+		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+		.codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
+		.ops = &mioa701_ops,
+	},
+};
+
+static struct snd_soc_card mioa701 = {
+	.name = "MioA701",
+	.platform = &pxa2xx_soc_platform,
+	.dai_link = mioa701_dai,
+	.num_links = ARRAY_SIZE(mioa701_dai),
+};
+
+static struct snd_soc_device mioa701_snd_devdata = {
+	.card = &mioa701,
+	.codec_dev = &soc_codec_dev_wm9713,
+};
+
+static struct platform_device *mioa701_snd_device;
+
+static int mioa701_wm9713_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	if (!machine_is_mioa701())
+		return -ENODEV;
+
+	dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will"
+		 "lead to overheating and possible destruction of your device."
+		 "Do not use without a good knowledge of mio's board design!\n");
+
+	mioa701_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!mioa701_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(mioa701_snd_device, &mioa701_snd_devdata);
+	mioa701_snd_devdata.dev = &mioa701_snd_device->dev;
+
+	ret = platform_device_add(mioa701_snd_device);
+	if (!ret)
+		return 0;
+
+	platform_device_put(mioa701_snd_device);
+	return ret;
+}
+
+static int __devexit mioa701_wm9713_remove(struct platform_device *pdev)
+{
+	platform_device_unregister(mioa701_snd_device);
+	return 0;
+}
+
+static struct platform_driver mioa701_wm9713_driver = {
+	.probe		= mioa701_wm9713_probe,
+	.remove		= __devexit_p(mioa701_wm9713_remove),
+	.driver		= {
+		.name		= "mioa701-wm9713",
+		.owner		= THIS_MODULE,
+	},
+};
+
+static int __init mioa701_asoc_init(void)
+{
+	return platform_driver_register(&mioa701_wm9713_driver);
+}
+
+static void __exit mioa701_asoc_exit(void)
+{
+	platform_driver_unregister(&mioa701_wm9713_driver);
+}
+
+module_init(mioa701_asoc_init);
+module_exit(mioa701_asoc_exit);
+
+/* Module information */
+MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)");
+MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 4a9cf30..48a73f6 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -55,7 +55,7 @@
 static int palm27x_startup(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_codec *codec = rtd->socdev->codec;
+	struct snd_soc_codec *codec = rtd->socdev->card->codec;
 
 	/* check the jack status at stream startup */
 	palm27x_ext_control(codec);
@@ -146,19 +146,16 @@
 
 static int palm27x_ac97_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	snd_soc_dapm_nc_pin(codec, "OUT3");
 	snd_soc_dapm_nc_pin(codec, "MONOOUT");
 
 	/* add palm27x specific controls */
-	for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&palm27x_controls[i],
-						codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, palm27x_controls,
+				ARRAY_SIZE(palm27x_controls));
+	if (err < 0)
+		return err;
 
 	/* add palm27x specific widgets */
 	snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index 6e98271..ef7c6c8 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/timer.h>
+#include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <sound/core.h>
@@ -77,7 +78,7 @@
 static int poodle_startup(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_codec *codec = rtd->socdev->codec;
+	struct snd_soc_codec *codec = rtd->socdev->card->codec;
 
 	/* check the jack status at stream startup */
 	poodle_ext_control(codec);
@@ -240,19 +241,17 @@
  */
 static int poodle_wm8731_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	snd_soc_dapm_nc_pin(codec, "LLINEIN");
 	snd_soc_dapm_nc_pin(codec, "RLINEIN");
 	snd_soc_dapm_enable_pin(codec, "MICIN");
 
 	/* 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));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, wm8731_poodle_controls,
+				ARRAY_SIZE(wm8731_poodle_controls));
+	if (err < 0)
+		return err;
 
 	/* Add poodle specific widgets */
 	snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
@@ -283,17 +282,42 @@
 	.num_links = 1,
 };
 
-/* poodle audio private data */
-static struct wm8731_setup_data poodle_wm8731_setup = {
-	.i2c_bus = 0,
-	.i2c_address = 0x1b,
-};
+/*
+ * FIXME: This is a temporary bodge to avoid cross-tree merge issues.
+ * New drivers should register the wm8731 I2C device in the machine
+ * setup code (under arch/arm for ARM systems).
+ */
+static int wm8731_i2c_register(void)
+{
+	struct i2c_board_info info;
+	struct i2c_adapter *adapter;
+	struct i2c_client *client;
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	info.addr = 0x1b;
+	strlcpy(info.type, "wm8731", I2C_NAME_SIZE);
+
+	adapter = i2c_get_adapter(0);
+	if (!adapter) {
+		printk(KERN_ERR "can't get i2c adapter 0\n");
+		return -ENODEV;
+	}
+
+	client = i2c_new_device(adapter, &info);
+	i2c_put_adapter(adapter);
+	if (!client) {
+		printk(KERN_ERR "can't add i2c device at 0x%x\n",
+			(unsigned int)info.addr);
+		return -ENODEV;
+	}
+
+	return 0;
+}
 
 /* poodle audio subsystem */
 static struct snd_soc_device poodle_snd_devdata = {
 	.card = &snd_soc_poodle,
 	.codec_dev = &soc_codec_dev_wm8731,
-	.codec_data = &poodle_wm8731_setup,
 };
 
 static struct platform_device *poodle_snd_device;
@@ -305,6 +329,10 @@
 	if (!machine_is_poodle())
 		return -ENODEV;
 
+	ret = wm8731_i2c_register();
+	if (ret != 0)
+		return ret;
+
 	locomo_gpio_set_dir(&poodle_locomo_device.dev,
 		POODLE_LOCOMO_GPIO_AMP_ON, 0);
 	/* should we mute HP at startup - burning power ?*/
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 73cb6b4..b0bf409 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -1,4 +1,3 @@
-#define DEBUG
 /*
  * pxa-ssp.c  --  ALSA Soc Audio Layer
  *
@@ -21,6 +20,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
+#include <asm/irq.h>
+
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
@@ -221,9 +222,9 @@
 	int ret = 0;
 
 	if (!cpu_dai->active) {
-		ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ);
-		if (ret < 0)
-			return ret;
+		priv->dev.port = cpu_dai->id + 1;
+		priv->dev.irq = NO_IRQ;
+		clk_enable(priv->dev.ssp->clk);
 		ssp_disable(&priv->dev);
 	}
 	return ret;
@@ -238,7 +239,7 @@
 
 	if (!cpu_dai->active) {
 		ssp_disable(&priv->dev);
-		ssp_exit(&priv->dev);
+		clk_disable(priv->dev.ssp->clk);
 	}
 }
 
@@ -298,7 +299,7 @@
 	int val;
 
 	u32 sscr0 = ssp_read_reg(ssp, SSCR0) &
-		~(SSCR0_ECS |  SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
+		~(SSCR0_ECS |  SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
 
 	dev_dbg(&ssp->pdev->dev,
 		"pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n",
@@ -326,7 +327,7 @@
 	case PXA_SSP_CLK_AUDIO:
 		priv->sysclk = 0;
 		ssp_set_scr(&priv->dev, 1);
-		sscr0 |= SSCR0_ADC;
+		sscr0 |= SSCR0_ACS;
 		break;
 	default:
 		return -ENODEV;
@@ -520,9 +521,20 @@
 	u32 sscr1;
 	u32 sspsp;
 
+	/* check if we need to change anything at all */
+	if (priv->dai_fmt == fmt)
+		return 0;
+
+	/* we can only change the settings if the port is not in use */
+	if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) {
+		dev_err(&ssp->pdev->dev,
+			"can't change hardware dai format: stream is in use");
+		return -EINVAL;
+	}
+
 	/* reset port settings */
 	sscr0 = ssp_read_reg(ssp, SSCR0) &
-		(SSCR0_ECS |  SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
+		(SSCR0_ECS |  SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
 	sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
 	sspsp = 0;
 
@@ -545,18 +557,18 @@
 
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
-		sscr0 |= SSCR0_MOD | SSCR0_PSP;
+		sscr0 |= SSCR0_PSP;
 		sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
 
+		/* See hw_params() */
 		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 		case SND_SOC_DAIFMT_NB_NF:
-			sspsp |= SSPSP_FSRT;
+			sspsp |= SSPSP_SFRMP;
 			break;
 		case SND_SOC_DAIFMT_NB_IF:
-			sspsp |= SSPSP_SFRMP | SSPSP_FSRT;
 			break;
 		case SND_SOC_DAIFMT_IB_IF:
-			sspsp |= SSPSP_SFRMP;
+			sspsp |= SSPSP_SCMODE(3);
 			break;
 		default:
 			return -EINVAL;
@@ -642,34 +654,65 @@
 			sscr0 |= SSCR0_FPCKE;
 #endif
 		sscr0 |= SSCR0_DataSize(16);
-		if (params_channels(params) > 1)
-			sscr0 |= SSCR0_EDSS;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
 		sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
-		/* we must be in network mode (2 slots) for 24 bit stereo */
 		break;
 	case SNDRV_PCM_FORMAT_S32_LE:
 		sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
-		/* we must be in network mode (2 slots) for 32 bit stereo */
 		break;
 	}
 	ssp_write_reg(ssp, SSCR0, sscr0);
 
 	switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
-		/* Cleared when the DAI format is set */
-		sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width);
+	       sspsp = ssp_read_reg(ssp, SSPSP);
+
+		if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) &&
+		     (width == 16)) {
+			/* This is a special case where the bitclk is 64fs
+			* and we're not dealing with 2*32 bits of audio
+			* samples.
+			*
+			* The SSP values used for that are all found out by
+			* trying and failing a lot; some of the registers
+			* needed for that mode are only available on PXA3xx.
+			*/
+
+#ifdef CONFIG_PXA3xx
+			if (!cpu_is_pxa3xx())
+				return -EINVAL;
+
+			sspsp |= SSPSP_SFRMWDTH(width * 2);
+			sspsp |= SSPSP_SFRMDLY(width * 4);
+			sspsp |= SSPSP_EDMYSTOP(3);
+			sspsp |= SSPSP_DMYSTOP(3);
+			sspsp |= SSPSP_DMYSTRT(1);
+#else
+			return -EINVAL;
+#endif
+		} else {
+			/* The frame width is the width the LRCLK is
+			 * asserted for; the delay is expressed in
+			 * half cycle units.  We need the extra cycle
+			 * because the data starts clocking out one BCLK
+			 * after LRCLK changes polarity.
+			 */
+			sspsp |= SSPSP_SFRMWDTH(width + 1);
+			sspsp |= SSPSP_SFRMDLY((width + 1) * 2);
+			sspsp |= SSPSP_DMYSTRT(1);
+		}
+
 		ssp_write_reg(ssp, SSPSP, sspsp);
 		break;
 	default:
 		break;
 	}
 
-	/* We always use a network mode so we always require TDM slots
+	/* When we use a network mode, we always require TDM slots
 	 * - complain loudly and fail if they've not been set up yet.
 	 */
-	if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) {
+	if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) {
 		dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
 		return -EINVAL;
 	}
@@ -751,7 +794,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	priv->dev.ssp = ssp_request(dai->id, "SoC audio");
+	priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio");
 	if (priv->dev.ssp == NULL) {
 		ret = -ENODEV;
 		goto err_priv;
@@ -782,6 +825,19 @@
 			    SNDRV_PCM_FMTBIT_S24_LE |	\
 			    SNDRV_PCM_FMTBIT_S32_LE)
 
+static struct snd_soc_dai_ops pxa_ssp_dai_ops = {
+	.startup	= pxa_ssp_startup,
+	.shutdown	= pxa_ssp_shutdown,
+	.trigger	= pxa_ssp_trigger,
+	.hw_params	= pxa_ssp_hw_params,
+	.set_sysclk	= pxa_ssp_set_dai_sysclk,
+	.set_clkdiv	= pxa_ssp_set_dai_clkdiv,
+	.set_pll	= pxa_ssp_set_dai_pll,
+	.set_fmt	= pxa_ssp_set_dai_fmt,
+	.set_tdm_slot	= pxa_ssp_set_dai_tdm_slot,
+	.set_tristate	= pxa_ssp_set_dai_tristate,
+};
+
 struct snd_soc_dai pxa_ssp_dai[] = {
 	{
 		.name = "pxa2xx-ssp1",
@@ -802,18 +858,7 @@
 			.rates = PXA_SSP_RATES,
 			.formats = PXA_SSP_FORMATS,
 		 },
-		.ops = {
-			.startup = pxa_ssp_startup,
-			.shutdown = pxa_ssp_shutdown,
-			.trigger = pxa_ssp_trigger,
-			.hw_params = pxa_ssp_hw_params,
-			.set_sysclk = pxa_ssp_set_dai_sysclk,
-			.set_clkdiv = pxa_ssp_set_dai_clkdiv,
-			.set_pll = pxa_ssp_set_dai_pll,
-			.set_fmt = pxa_ssp_set_dai_fmt,
-			.set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
-			.set_tristate = pxa_ssp_set_dai_tristate,
-		},
+		.ops = &pxa_ssp_dai_ops,
 	},
 	{	.name = "pxa2xx-ssp2",
 		.id = 1,
@@ -833,18 +878,7 @@
 			.rates = PXA_SSP_RATES,
 			.formats = PXA_SSP_FORMATS,
 		 },
-		.ops = {
-			.startup = pxa_ssp_startup,
-			.shutdown = pxa_ssp_shutdown,
-			.trigger = pxa_ssp_trigger,
-			.hw_params = pxa_ssp_hw_params,
-			.set_sysclk = pxa_ssp_set_dai_sysclk,
-			.set_clkdiv = pxa_ssp_set_dai_clkdiv,
-			.set_pll = pxa_ssp_set_dai_pll,
-			.set_fmt = pxa_ssp_set_dai_fmt,
-			.set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
-			.set_tristate = pxa_ssp_set_dai_tristate,
-		},
+		.ops = &pxa_ssp_dai_ops,
 	},
 	{
 		.name = "pxa2xx-ssp3",
@@ -865,18 +899,7 @@
 			.rates = PXA_SSP_RATES,
 			.formats = PXA_SSP_FORMATS,
 		 },
-		.ops = {
-			.startup = pxa_ssp_startup,
-			.shutdown = pxa_ssp_shutdown,
-			.trigger = pxa_ssp_trigger,
-			.hw_params = pxa_ssp_hw_params,
-			.set_sysclk = pxa_ssp_set_dai_sysclk,
-			.set_clkdiv = pxa_ssp_set_dai_clkdiv,
-			.set_pll = pxa_ssp_set_dai_pll,
-			.set_fmt = pxa_ssp_set_dai_fmt,
-			.set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
-			.set_tristate = pxa_ssp_set_dai_tristate,
-		},
+		.ops = &pxa_ssp_dai_ops,
 	},
 	{
 		.name = "pxa2xx-ssp4",
@@ -897,18 +920,7 @@
 			.rates = PXA_SSP_RATES,
 			.formats = PXA_SSP_FORMATS,
 		 },
-		.ops = {
-			.startup = pxa_ssp_startup,
-			.shutdown = pxa_ssp_shutdown,
-			.trigger = pxa_ssp_trigger,
-			.hw_params = pxa_ssp_hw_params,
-			.set_sysclk = pxa_ssp_set_dai_sysclk,
-			.set_clkdiv = pxa_ssp_set_dai_clkdiv,
-			.set_pll = pxa_ssp_set_dai_pll,
-			.set_fmt = pxa_ssp_set_dai_fmt,
-			.set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
-			.set_tristate = pxa_ssp_set_dai_tristate,
-		},
+		.ops = &pxa_ssp_dai_ops,
 	},
 };
 EXPORT_SYMBOL_GPL(pxa_ssp_dai);
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 812c2b4..01c21c6 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -106,13 +106,13 @@
 static int pxa2xx_ac97_probe(struct platform_device *pdev,
 			     struct snd_soc_dai *dai)
 {
-	return pxa2xx_ac97_hw_probe(pdev);
+	return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
 }
 
 static void pxa2xx_ac97_remove(struct platform_device *pdev,
 			       struct snd_soc_dai *dai)
 {
-	pxa2xx_ac97_hw_remove(pdev);
+	pxa2xx_ac97_hw_remove(to_platform_device(dai->dev));
 }
 
 static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
@@ -164,6 +164,18 @@
 		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
 		SNDRV_PCM_RATE_48000)
 
+static struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = {
+	.hw_params	= pxa2xx_ac97_hw_params,
+};
+
+static struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = {
+	.hw_params	= pxa2xx_ac97_hw_aux_params,
+};
+
+static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
+	.hw_params	= pxa2xx_ac97_hw_mic_params,
+};
+
 /*
  * There is only 1 physical AC97 interface for pxa2xx, but it
  * has extra fifo's that can be used for aux DACs and ADCs.
@@ -189,8 +201,7 @@
 		.channels_max = 2,
 		.rates = PXA2XX_AC97_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.hw_params = pxa2xx_ac97_hw_params,},
+	.ops = &pxa_ac97_hifi_dai_ops,
 },
 {
 	.name = "pxa2xx-ac97-aux",
@@ -208,8 +219,7 @@
 		.channels_max = 1,
 		.rates = PXA2XX_AC97_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.hw_params = pxa2xx_ac97_hw_aux_params,},
+	.ops = &pxa_ac97_aux_dai_ops,
 },
 {
 	.name = "pxa2xx-ac97-mic",
@@ -221,23 +231,52 @@
 		.channels_max = 1,
 		.rates = PXA2XX_AC97_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.hw_params = pxa2xx_ac97_hw_mic_params,},
+	.ops = &pxa_ac97_mic_dai_ops,
 },
 };
 
 EXPORT_SYMBOL_GPL(pxa_ac97_dai);
 EXPORT_SYMBOL_GPL(soc_ac97_ops);
 
+static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++)
+		pxa_ac97_dai[i].dev = &pdev->dev;
+
+	/* Punt most of the init to the SoC probe; we may need the machine
+	 * driver to do interesting things with the clocking to get us up
+	 * and running.
+	 */
+	return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
+}
+
+static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
+
+	return 0;
+}
+
+static struct platform_driver pxa2xx_ac97_driver = {
+	.probe		= pxa2xx_ac97_dev_probe,
+	.remove		= __devexit_p(pxa2xx_ac97_dev_remove),
+	.driver		= {
+		.name	= "pxa2xx-ac97",
+		.owner	= THIS_MODULE,
+	},
+};
+
 static int __init pxa_ac97_init(void)
 {
-	return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
+	return platform_driver_register(&pxa2xx_ac97_driver);
 }
 module_init(pxa_ac97_init);
 
 static void __exit pxa_ac97_exit(void)
 {
-	snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
+	platform_driver_unregister(&pxa2xx_ac97_driver);
 }
 module_exit(pxa_ac97_exit);
 
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 517991f..e6c2440 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -25,20 +25,11 @@
 
 #include <mach/hardware.h>
 #include <mach/pxa-regs.h>
-#include <mach/pxa2xx-gpio.h>
 #include <mach/audio.h>
 
 #include "pxa2xx-pcm.h"
 #include "pxa2xx-i2s.h"
 
-struct pxa2xx_gpio {
-	u32 sys;
-	u32	rx;
-	u32 tx;
-	u32 clk;
-	u32 frm;
-};
-
 /*
  * I2S Controller Register and Bit Definitions
  */
@@ -106,21 +97,6 @@
 				  DCMD_BURST32 | DCMD_WIDTH4,
 };
 
-static struct pxa2xx_gpio gpio_bus[] = {
-	{ /* I2S SoC Slave */
-		.rx = GPIO29_SDATA_IN_I2S_MD,
-		.tx = GPIO30_SDATA_OUT_I2S_MD,
-		.clk = GPIO28_BITCLK_IN_I2S_MD,
-		.frm = GPIO31_SYNC_I2S_MD,
-	},
-	{ /* I2S SoC Master */
-		.rx = GPIO29_SDATA_IN_I2S_MD,
-		.tx = GPIO30_SDATA_OUT_I2S_MD,
-		.clk = GPIO28_BITCLK_OUT_I2S_MD,
-		.frm = GPIO31_SYNC_I2S_MD,
-	},
-};
-
 static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
 			      struct snd_soc_dai *dai)
 {
@@ -181,9 +157,6 @@
 	if (clk_id != PXA2XX_I2S_SYSCLK)
 		return -ENODEV;
 
-	if (pxa_i2s.master && dir == SND_SOC_CLOCK_OUT)
-		pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
-
 	return 0;
 }
 
@@ -194,10 +167,6 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
-	pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
-	pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
-	pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
-	pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
 	BUG_ON(IS_ERR(clk_i2s));
 	clk_enable(clk_i2s);
 	pxa_i2s_wait();
@@ -335,6 +304,15 @@
 		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
 		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
 
+static struct snd_soc_dai_ops pxa_i2s_dai_ops = {
+	.startup	= pxa2xx_i2s_startup,
+	.shutdown	= pxa2xx_i2s_shutdown,
+	.trigger	= pxa2xx_i2s_trigger,
+	.hw_params	= pxa2xx_i2s_hw_params,
+	.set_fmt	= pxa2xx_i2s_set_dai_fmt,
+	.set_sysclk	= pxa2xx_i2s_set_dai_sysclk,
+};
+
 struct snd_soc_dai pxa_i2s_dai = {
 	.name = "pxa2xx-i2s",
 	.id = 0,
@@ -350,14 +328,7 @@
 		.channels_max = 2,
 		.rates = PXA2XX_I2S_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.startup = pxa2xx_i2s_startup,
-		.shutdown = pxa2xx_i2s_shutdown,
-		.trigger = pxa2xx_i2s_trigger,
-		.hw_params = pxa2xx_i2s_hw_params,
-		.set_fmt = pxa2xx_i2s_set_dai_fmt,
-		.set_sysclk = pxa2xx_i2s_set_dai_sysclk,
-	},
+	.ops = &pxa_i2s_dai_ops,
 };
 
 EXPORT_SYMBOL_GPL(pxa_i2s_dai);
@@ -398,11 +369,6 @@
 
 static int __init pxa2xx_i2s_init(void)
 {
-	if (cpu_is_pxa27x())
-		gpio_bus[1].sys = GPIO113_I2S_SYSCLK_MD;
-	else
-		gpio_bus[1].sys = GPIO32_SYSCLK_I2S_MD;
-
 	clk_i2s = ERR_PTR(-ENOENT);
 	return platform_driver_register(&pxa2xx_i2s_driver);
 }
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index a3b9e6b..6ca9f53 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -109,7 +109,7 @@
 static int spitz_startup(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_codec *codec = rtd->socdev->codec;
+	struct snd_soc_codec *codec = rtd->socdev->card->codec;
 
 	/* check the jack status at stream startup */
 	spitz_ext_control(codec);
@@ -278,7 +278,7 @@
  */
 static int spitz_wm8750_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	/* NC codec pins */
 	snd_soc_dapm_nc_pin(codec, "RINPUT1");
@@ -290,12 +290,10 @@
 	snd_soc_dapm_nc_pin(codec, "MONO1");
 
 	/* Add spitz specific controls */
-	for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
-		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&wm8750_spitz_controls[i], codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, wm8750_spitz_controls,
+				ARRAY_SIZE(wm8750_spitz_controls));
+	if (err < 0)
+		return err;
 
 	/* Add spitz specific widgets */
 	snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index c77194f..fc78137 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -82,7 +82,7 @@
 static int tosa_startup(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_codec *codec = rtd->socdev->codec;
+	struct snd_soc_codec *codec = rtd->socdev->card->codec;
 
 	/* check the jack status at stream startup */
 	tosa_ext_control(codec);
@@ -188,18 +188,16 @@
 
 static int tosa_ac97_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	snd_soc_dapm_nc_pin(codec, "OUT3");
 	snd_soc_dapm_nc_pin(codec, "MONOOUT");
 
 	/* add tosa specific controls */
-	for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&tosa_controls[i],codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, tosa_controls,
+				ARRAY_SIZE(tosa_controls));
+	if (err < 0)
+		return err;
 
 	/* add tosa specific widgets */
 	snd_soc_dapm_new_controls(codec, tosa_dapm_widgets,
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index f8e9ecd..9a386b4 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/device.h>
+#include <linux/clk.h>
 #include <linux/i2c.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -26,6 +27,17 @@
 #include "pxa2xx-ac97.h"
 #include "pxa-ssp.h"
 
+/*
+ * There is a physical switch SW15 on the board which changes the MCLK
+ * for the WM9713 between the standard AC97 master clock and the
+ * output of the CLK_POUT signal from the PXA.
+ */
+static int clk_pout;
+module_param(clk_pout, int, 0);
+MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board).");
+
+static struct clk *pout;
+
 static struct snd_soc_card zylonite;
 
 static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = {
@@ -61,10 +73,8 @@
 
 static int zylonite_wm9713_init(struct snd_soc_codec *codec)
 {
-	/* Currently we only support use of the AC97 clock here.  If
-	 * CLK_POUT is selected by SW15 then the clock API will need
-	 * to be used to request and enable it here.
-	 */
+	if (clk_pout)
+		snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0);
 
 	snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
 				  ARRAY_SIZE(zylonite_dapm_widgets));
@@ -86,27 +96,51 @@
 	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	unsigned int pll_out = 0;
-	unsigned int acds = 0;
 	unsigned int wm9713_div = 0;
 	int ret = 0;
+	int rate = params_rate(params);
+	int width = snd_pcm_format_physical_width(params_format(params));
 
-	switch (params_rate(params)) {
+	/* Only support ratios that we can generate neatly from the AC97
+	 * based master clock - in particular, this excludes 44.1kHz.
+	 * In most applications the voice DAC will be used for telephony
+	 * data so multiples of 8kHz will be the common case.
+	 */
+	switch (rate) {
 	case 8000:
 		wm9713_div = 12;
-		pll_out = 2048000;
 		break;
 	case 16000:
 		wm9713_div = 6;
-		pll_out = 4096000;
 		break;
 	case 48000:
-	default:
 		wm9713_div = 2;
-		pll_out = 12288000;
-		acds = 1;
 		break;
+	default:
+		/* Don't support OSS emulation */
+		return -EINVAL;
 	}
 
+	/* Add 1 to the width for the leading clock cycle */
+	pll_out = rate * (width + 1) * 8;
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out);
+	if (ret < 0)
+		return ret;
+
+	if (clk_pout)
+		ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV,
+					     WM9713_PCMDIV(wm9713_div));
+	else
+		ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV,
+					     WM9713_PCMDIV(wm9713_div));
+	if (ret < 0)
+		return ret;
+
 	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
 		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
 	if (ret < 0)
@@ -117,32 +151,6 @@
 	if (ret < 0)
 		return ret;
 
-	ret = snd_soc_dai_set_tdm_slot(cpu_dai,
-				       params_channels(params),
-				       params_channels(params));
-	if (ret < 0)
-		return ret;
-
-	ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out);
-	if (ret < 0)
-		return ret;
-
-	ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds);
-	if (ret < 0)
-		return ret;
-
-	ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1);
-	if (ret < 0)
-		return ret;
-
-	/* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs
-	 * to be set instead.
-	 */
-	ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV,
-				     WM9713_PCMDIV(wm9713_div));
-	if (ret < 0)
-		return ret;
-
 	return 0;
 }
 
@@ -173,8 +181,72 @@
 },
 };
 
+static int zylonite_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	if (clk_pout) {
+		pout = clk_get(NULL, "CLK_POUT");
+		if (IS_ERR(pout)) {
+			dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n",
+				PTR_ERR(pout));
+			return PTR_ERR(pout);
+		}
+
+		ret = clk_enable(pout);
+		if (ret != 0) {
+			dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
+				ret);
+			clk_put(pout);
+			return ret;
+		}
+
+		dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n",
+			clk_get_rate(pout));
+	}
+
+	return 0;
+}
+
+static int zylonite_remove(struct platform_device *pdev)
+{
+	if (clk_pout) {
+		clk_disable(pout);
+		clk_put(pout);
+	}
+
+	return 0;
+}
+
+static int zylonite_suspend_post(struct platform_device *pdev,
+				 pm_message_t state)
+{
+	if (clk_pout)
+		clk_disable(pout);
+
+	return 0;
+}
+
+static int zylonite_resume_pre(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	if (clk_pout) {
+		ret = clk_enable(pout);
+		if (ret != 0)
+			dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
+				ret);
+	}
+
+	return ret;
+}
+
 static struct snd_soc_card zylonite = {
 	.name = "Zylonite",
+	.probe = &zylonite_probe,
+	.remove = &zylonite_remove,
+	.suspend_post = &zylonite_suspend_post,
+	.resume_pre = &zylonite_resume_pre,
 	.platform = &pxa2xx_soc_platform,
 	.dai_link = zylonite_dai,
 	.num_links = ARRAY_SIZE(zylonite_dai),
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index fcd03ac..2f3a21e 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -1,19 +1,31 @@
 config SND_S3C24XX_SOC
-	tristate "SoC Audio for the Samsung S3C24XX chips"
-	depends on ARCH_S3C2410
+	tristate "SoC Audio for the Samsung S3CXXXX chips"
+	depends on ARCH_S3C2410 || ARCH_S3C64XX
 	help
 	  Say Y or M if you want to add support for codecs attached to
-	  the S3C24XX AC97, I2S or SSP interface. You will also need
-	  to select the audio interfaces to support below.
+	  the S3C24XX and S3C64XX AC97, I2S or SSP interface. You will
+	  also need to select the audio interfaces to support below.
 
 config SND_S3C24XX_SOC_I2S
 	tristate
+	select S3C2410_DMA
+
+config SND_S3C_I2SV2_SOC
+	tristate
 
 config SND_S3C2412_SOC_I2S
 	tristate
+	select SND_S3C_I2SV2_SOC
+	select S3C2410_DMA
+
+config SND_S3C64XX_SOC_I2S
+	tristate
+	select SND_S3C_I2SV2_SOC
+	select S3C64XX_DMA
 
 config SND_S3C2443_SOC_AC97
 	tristate
+	select S3C2410_DMA
 	select AC97_BUS
 	select SND_SOC_AC97_BUS
 	
@@ -26,6 +38,14 @@
 	  Say Y if you want to add support for SoC audio on smdk2440
 	  with the WM8753.
 
+config SND_S3C24XX_SOC_JIVE_WM8750
+	tristate "SoC I2S Audio support for Jive"
+	depends on SND_S3C24XX_SOC && MACH_JIVE
+	select SND_SOC_WM8750
+	select SND_S3C2412_SOC_I2S
+	help
+	  Sat Y if you want to add support for SoC audio on the Jive.
+
 config SND_S3C24XX_SOC_SMDK2443_WM9710
 	tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
 	depends on SND_S3C24XX_SOC && MACH_SMDK2443
@@ -48,4 +68,5 @@
 	tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
        	depends on SND_S3C24XX_SOC
        	select SND_S3C24XX_SOC_I2S
+	select SND_SOC_L3
        	select SND_SOC_UDA134X
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 96b3f3f..07a93a2 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -2,19 +2,25 @@
 snd-soc-s3c24xx-objs := s3c24xx-pcm.o
 snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
 snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
+snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o
 snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o
+snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o
 
 obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
 obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
 obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o
 obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
+obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o
+obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
 
 # S3C24XX Machine Support
+snd-soc-jive-wm8750-objs := jive_wm8750.o
 snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
 snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
 snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
 snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
 
+obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
 obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
 obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
 obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c
new file mode 100644
index 0000000..3206379
--- /dev/null
+++ b/sound/soc/s3c24xx/jive_wm8750.c
@@ -0,0 +1,201 @@
+/* sound/soc/s3c24xx/jive_wm8750.c
+ *
+ * Copyright 2007,2008 Simtec Electronics
+ *
+ * Based on sound/soc/pxa/spitz.c
+ *	Copyright 2005 Wolfson Microelectronics PLC.
+ *	Copyright 2005 Openedhand 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/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+
+#include "s3c24xx-pcm.h"
+#include "s3c2412-i2s.h"
+
+#include "../codecs/wm8750.h"
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	{ "Headphone Jack", NULL, "LOUT1" },
+	{ "Headphone Jack", NULL, "ROUT1" },
+	{ "Internal Speaker", NULL, "LOUT2" },
+	{ "Internal Speaker", NULL, "ROUT2" },
+	{ "LINPUT1", NULL, "Line Input" },
+	{ "RINPUT1", NULL, "Line Input" },
+};
+
+static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_SPK("Internal Speaker", NULL),
+	SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static int jive_hw_params(struct snd_pcm_substream *substream,
+			  struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+	struct s3c_i2sv2_rate_calc div;
+	unsigned int clk = 0;
+	int ret = 0;
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 48000:
+	case 96000:
+		clk = 12288000;
+		break;
+	case 11025:
+	case 22050:
+	case 44100:
+		clk = 11289600;
+		break;
+	}
+
+	s3c_i2sv2_calc_rate(&div, NULL, params_rate(params),
+			    s3c2412_get_iisclk());
+
+	/* set codec DAI configuration */
+	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+				  SND_SOC_DAIFMT_NB_NF |
+				  SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set cpu DAI configuration */
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+				  SND_SOC_DAIFMT_NB_NF |
+				  SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_RCLK, div.fs_div);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_PRESCALER,
+				     div.clk_div - 1);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops jive_ops = {
+	.hw_params	= jive_hw_params,
+};
+
+static int jive_wm8750_init(struct snd_soc_codec *codec)
+{
+	int err;
+
+	/* These endpoints are not being used. */
+	snd_soc_dapm_nc_pin(codec, "LINPUT2");
+	snd_soc_dapm_nc_pin(codec, "RINPUT2");
+	snd_soc_dapm_nc_pin(codec, "LINPUT3");
+	snd_soc_dapm_nc_pin(codec, "RINPUT3");
+	snd_soc_dapm_nc_pin(codec, "OUT3");
+	snd_soc_dapm_nc_pin(codec, "MONO");
+
+	/* Add jive specific widgets */
+	err = snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
+					ARRAY_SIZE(wm8750_dapm_widgets));
+	if (err) {
+		printk(KERN_ERR "%s: failed to add widgets (%d)\n",
+		       __func__, err);
+		return err;
+	}
+
+	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+	snd_soc_dapm_sync(codec);
+
+	return 0;
+}
+
+static struct snd_soc_dai_link jive_dai = {
+	.name		= "wm8750",
+	.stream_name	= "WM8750",
+	.cpu_dai	= &s3c2412_i2s_dai,
+	.codec_dai	= &wm8750_dai,
+	.init		= jive_wm8750_init,
+	.ops		= &jive_ops,
+};
+
+/* jive audio machine driver */
+static struct snd_soc_machine snd_soc_machine_jive = {
+	.name		= "Jive",
+	.dai_link	= &jive_dai,
+	.num_links	= 1,
+};
+
+/* jive audio private data */
+static struct wm8750_setup_data jive_wm8750_setup = {
+};
+
+/* jive audio subsystem */
+static struct snd_soc_device jive_snd_devdata = {
+	.machine	= &snd_soc_machine_jive,
+	.platform	= &s3c24xx_soc_platform,
+	.codec_dev	= &soc_codec_dev_wm8750_spi,
+	.codec_data	= &jive_wm8750_setup,
+};
+
+static struct platform_device *jive_snd_device;
+
+static int __init jive_init(void)
+{
+	int ret;
+
+	if (!machine_is_jive())
+		return 0;
+
+	printk("JIVE WM8750 Audio support\n");
+
+	jive_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!jive_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(jive_snd_device, &jive_snd_devdata);
+	jive_snd_devdata.dev = &jive_snd_device->dev;
+	ret = platform_device_add(jive_snd_device);
+
+	if (ret)
+		platform_device_put(jive_snd_device);
+
+	return ret;
+}
+
+static void __exit jive_exit(void)
+{
+	platform_device_unregister(jive_snd_device);
+}
+
+module_init(jive_init);
+module_exit(jive_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("ALSA SoC Jive Audio support");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 45bb12e..289fadf 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -29,25 +29,17 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 #include <mach/hardware.h>
-#include <mach/audio.h>
+#include <plat/audio.h>
 #include <linux/io.h>
 #include <mach/spi-gpio.h>
 
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-iis.h>
 
 #include "../codecs/wm8753.h"
 #include "lm4857.h"
 #include "s3c24xx-pcm.h"
 #include "s3c24xx-i2s.h"
 
-/* Debugging stuff */
-#define S3C24XX_SOC_NEO1973_WM8753_DEBUG 0
-#if S3C24XX_SOC_NEO1973_WM8753_DEBUG
-#define DBG(x...) printk(KERN_DEBUG "s3c24xx-soc-neo1973-wm8753: " x)
-#else
-#define DBG(x...)
-#endif
-
 /* define the scenarios */
 #define NEO_AUDIO_OFF			0
 #define NEO_GSM_CALL_AUDIO_HANDSET	1
@@ -72,7 +64,7 @@
 	int ret = 0;
 	unsigned long iis_clkrate;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	iis_clkrate = s3c24xx_i2s_get_clockrate();
 
@@ -158,7 +150,7 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	/* disable the PLL */
 	return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
@@ -181,7 +173,7 @@
 	int ret = 0;
 	unsigned long iis_clkrate;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	iis_clkrate = s3c24xx_i2s_get_clockrate();
 
@@ -224,7 +216,7 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	/* disable the PLL */
 	return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
@@ -246,7 +238,7 @@
 
 static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	switch (neo1973_scenario) {
 	case NEO_AUDIO_OFF:
@@ -330,7 +322,7 @@
 {
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (neo1973_scenario == ucontrol->value.integer.value[0])
 		return 0;
@@ -344,7 +336,7 @@
 
 static void lm4857_write_regs(void)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (i2c_master_send(i2c, lm4857_regs, 4) != 4)
 		printk(KERN_ERR "lm4857: i2c write failed\n");
@@ -357,7 +349,7 @@
 	int shift = (kcontrol->private_value >> 8) & 0x0F;
 	int mask = (kcontrol->private_value >> 16) & 0xFF;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
 	return 0;
@@ -385,7 +377,7 @@
 {
 	u8 value = lm4857_regs[LM4857_CTRL] & 0x0F;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (value)
 		value -= 5;
@@ -399,7 +391,7 @@
 {
 	u8 value = ucontrol->value.integer.value[0];
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (value)
 		value += 5;
@@ -506,9 +498,9 @@
  */
 static int neo1973_wm8753_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	/* set up NC codec pins */
 	snd_soc_dapm_nc_pin(codec, "LOUT2");
@@ -526,13 +518,10 @@
 	set_scenario_endpoints(codec, NEO_AUDIO_OFF);
 
 	/* add neo1973 specific controls */
-	for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&wm8753_neo1973_controls[i],
-				codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, wm8753_neo1973_controls,
+				ARRAY_SIZE(8753_neo1973_controls));
+	if (err < 0)
+		return err;
 
 	/* set up neo1973 specific audio routes */
 	err = snd_soc_dapm_add_routes(codec, dapm_routes,
@@ -585,21 +574,15 @@
 	.num_links = ARRAY_SIZE(neo1973_dai),
 };
 
-static struct wm8753_setup_data neo1973_wm8753_setup = {
-	.i2c_bus = 0,
-	.i2c_address = 0x1a,
-};
-
 static struct snd_soc_device neo1973_snd_devdata = {
 	.card = &neo1973,
 	.codec_dev = &soc_codec_dev_wm8753,
-	.codec_data = &neo1973_wm8753_setup,
 };
 
 static int lm4857_i2c_probe(struct i2c_client *client,
 			    const struct i2c_device_id *id)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	i2c = client;
 
@@ -609,7 +592,7 @@
 
 static int lm4857_i2c_remove(struct i2c_client *client)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	i2c = NULL;
 
@@ -620,7 +603,7 @@
 
 static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	dev_dbg(&dev->dev, "lm4857_suspend\n");
 	lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
@@ -633,7 +616,7 @@
 
 static int lm4857_resume(struct i2c_client *dev)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (lm4857_state) {
 		lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
@@ -644,7 +627,7 @@
 
 static void lm4857_shutdown(struct i2c_client *dev)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	dev_dbg(&dev->dev, "lm4857_shutdown\n");
 	lm4857_regs[LM4857_CTRL] &= 0xf0;
@@ -675,7 +658,7 @@
 {
 	int ret;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (!machine_is_neo1973_gta01()) {
 		printk(KERN_INFO
@@ -706,7 +689,7 @@
 
 static void __exit neo1973_exit(void)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	i2c_del_driver(&lm4857_i2c_driver);
 	platform_device_unregister(neo1973_snd_device);
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
new file mode 100644
index 0000000..295a4c9
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -0,0 +1,638 @@
+/* sound/soc/s3c24xx/s3c-i2c-v2.c
+ *
+ * ALSA Soc Audio Layer - I2S core for newer Samsung SoCs.
+ *
+ * Copyright (c) 2006 Wolfson Microelectronics PLC.
+ *	Graeme Gregory graeme.gregory@wolfsonmicro.com
+ *	linux@wolfsonmicro.com
+ *
+ * Copyright (c) 2008, 2007, 2004-2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <plat/regs-s3c2412-iis.h>
+
+#include <plat/audio.h>
+#include <mach/dma.h>
+
+#include "s3c-i2s-v2.h"
+
+#define S3C2412_I2S_DEBUG_CON 0
+
+static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
+{
+	return cpu_dai->private_data;
+}
+
+#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
+
+#if S3C2412_I2S_DEBUG_CON
+static void dbg_showcon(const char *fn, u32 con)
+{
+	printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d, RXFFULL=%d\n", fn,
+	       bit_set(con, S3C2412_IISCON_LRINDEX),
+	       bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY),
+	       bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY),
+	       bit_set(con, S3C2412_IISCON_TXFIFO_FULL),
+	       bit_set(con, S3C2412_IISCON_RXFIFO_FULL));
+
+	printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n",
+	       fn,
+	       bit_set(con, S3C2412_IISCON_TXDMA_PAUSE),
+	       bit_set(con, S3C2412_IISCON_RXDMA_PAUSE),
+	       bit_set(con, S3C2412_IISCON_TXCH_PAUSE),
+	       bit_set(con, S3C2412_IISCON_RXCH_PAUSE));
+	printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn,
+	       bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE),
+	       bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE),
+	       bit_set(con, S3C2412_IISCON_IIS_ACTIVE));
+}
+#else
+static inline void dbg_showcon(const char *fn, u32 con)
+{
+}
+#endif
+
+
+/* Turn on or off the transmission path. */
+void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
+{
+	void __iomem *regs = i2s->regs;
+	u32 fic, con, mod;
+
+	pr_debug("%s(%d)\n", __func__, on);
+
+	fic = readl(regs + S3C2412_IISFIC);
+	con = readl(regs + S3C2412_IISCON);
+	mod = readl(regs + S3C2412_IISMOD);
+
+	pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+
+	if (on) {
+		con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
+		con &= ~S3C2412_IISCON_TXDMA_PAUSE;
+		con &= ~S3C2412_IISCON_TXCH_PAUSE;
+
+		switch (mod & S3C2412_IISMOD_MODE_MASK) {
+		case S3C2412_IISMOD_MODE_TXONLY:
+		case S3C2412_IISMOD_MODE_TXRX:
+			/* do nothing, we are in the right mode */
+			break;
+
+		case S3C2412_IISMOD_MODE_RXONLY:
+			mod &= ~S3C2412_IISMOD_MODE_MASK;
+			mod |= S3C2412_IISMOD_MODE_TXRX;
+			break;
+
+		default:
+			dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n");
+		}
+
+		writel(con, regs + S3C2412_IISCON);
+		writel(mod, regs + S3C2412_IISMOD);
+	} else {
+		/* Note, we do not have any indication that the FIFO problems
+		 * tha the S3C2410/2440 had apply here, so we should be able
+		 * to disable the DMA and TX without resetting the FIFOS.
+		 */
+
+		con |=  S3C2412_IISCON_TXDMA_PAUSE;
+		con |=  S3C2412_IISCON_TXCH_PAUSE;
+		con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
+
+		switch (mod & S3C2412_IISMOD_MODE_MASK) {
+		case S3C2412_IISMOD_MODE_TXRX:
+			mod &= ~S3C2412_IISMOD_MODE_MASK;
+			mod |= S3C2412_IISMOD_MODE_RXONLY;
+			break;
+
+		case S3C2412_IISMOD_MODE_TXONLY:
+			mod &= ~S3C2412_IISMOD_MODE_MASK;
+			con &= ~S3C2412_IISCON_IIS_ACTIVE;
+			break;
+
+		default:
+			dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n");
+		}
+
+		writel(mod, regs + S3C2412_IISMOD);
+		writel(con, regs + S3C2412_IISCON);
+	}
+
+	fic = readl(regs + S3C2412_IISFIC);
+	dbg_showcon(__func__, con);
+	pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+}
+EXPORT_SYMBOL_GPL(s3c2412_snd_txctrl);
+
+void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
+{
+	void __iomem *regs = i2s->regs;
+	u32 fic, con, mod;
+
+	pr_debug("%s(%d)\n", __func__, on);
+
+	fic = readl(regs + S3C2412_IISFIC);
+	con = readl(regs + S3C2412_IISCON);
+	mod = readl(regs + S3C2412_IISMOD);
+
+	pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+
+	if (on) {
+		con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
+		con &= ~S3C2412_IISCON_RXDMA_PAUSE;
+		con &= ~S3C2412_IISCON_RXCH_PAUSE;
+
+		switch (mod & S3C2412_IISMOD_MODE_MASK) {
+		case S3C2412_IISMOD_MODE_TXRX:
+		case S3C2412_IISMOD_MODE_RXONLY:
+			/* do nothing, we are in the right mode */
+			break;
+
+		case S3C2412_IISMOD_MODE_TXONLY:
+			mod &= ~S3C2412_IISMOD_MODE_MASK;
+			mod |= S3C2412_IISMOD_MODE_TXRX;
+			break;
+
+		default:
+			dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
+		}
+
+		writel(mod, regs + S3C2412_IISMOD);
+		writel(con, regs + S3C2412_IISCON);
+	} else {
+		/* See txctrl notes on FIFOs. */
+
+		con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
+		con |=  S3C2412_IISCON_RXDMA_PAUSE;
+		con |=  S3C2412_IISCON_RXCH_PAUSE;
+
+		switch (mod & S3C2412_IISMOD_MODE_MASK) {
+		case S3C2412_IISMOD_MODE_RXONLY:
+			con &= ~S3C2412_IISCON_IIS_ACTIVE;
+			mod &= ~S3C2412_IISMOD_MODE_MASK;
+			break;
+
+		case S3C2412_IISMOD_MODE_TXRX:
+			mod &= ~S3C2412_IISMOD_MODE_MASK;
+			mod |= S3C2412_IISMOD_MODE_TXONLY;
+			break;
+
+		default:
+			dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
+		}
+
+		writel(con, regs + S3C2412_IISCON);
+		writel(mod, regs + S3C2412_IISMOD);
+	}
+
+	fic = readl(regs + S3C2412_IISFIC);
+	pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+}
+EXPORT_SYMBOL_GPL(s3c2412_snd_rxctrl);
+
+/*
+ * Wait for the LR signal to allow synchronisation to the L/R clock
+ * from the codec. May only be needed for slave mode.
+ */
+static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s)
+{
+	u32 iiscon;
+	unsigned long timeout = jiffies + msecs_to_jiffies(5);
+
+	pr_debug("Entered %s\n", __func__);
+
+	while (1) {
+		iiscon = readl(i2s->regs + S3C2412_IISCON);
+		if (iiscon & S3C2412_IISCON_LRINDEX)
+			break;
+
+		if (timeout < jiffies) {
+			printk(KERN_ERR "%s: timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Set S3C2412 I2S DAI format
+ */
+static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+			       unsigned int fmt)
+{
+	struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+	u32 iismod;
+
+	pr_debug("Entered %s\n", __func__);
+
+	iismod = readl(i2s->regs + S3C2412_IISMOD);
+	pr_debug("hw_params r: IISMOD: %x \n", iismod);
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#define IISMOD_MASTER_MASK S3C2412_IISMOD_MASTER_MASK
+#define IISMOD_SLAVE S3C2412_IISMOD_SLAVE
+#define IISMOD_MASTER S3C2412_IISMOD_MASTER_INTERNAL
+#endif
+
+#if defined(CONFIG_PLAT_S3C64XX)
+/* From Rev1.1 datasheet, we have two master and two slave modes:
+ * IMS[11:10]:
+ *	00 = master mode, fed from PCLK
+ *	01 = master mode, fed from CLKAUDIO
+ *	10 = slave mode, using PCLK
+ *	11 = slave mode, using I2SCLK
+ */
+#define IISMOD_MASTER_MASK (1 << 11)
+#define IISMOD_SLAVE (1 << 11)
+#define IISMOD_MASTER (0x0)
+#endif
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		i2s->master = 0;
+		iismod &= ~IISMOD_MASTER_MASK;
+		iismod |= IISMOD_SLAVE;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		i2s->master = 1;
+		iismod &= ~IISMOD_MASTER_MASK;
+		iismod |= IISMOD_MASTER;
+		break;
+	default:
+		pr_debug("unknwon master/slave format\n");
+		return -EINVAL;
+	}
+
+	iismod &= ~S3C2412_IISMOD_SDF_MASK;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_RIGHT_J:
+		iismod |= S3C2412_IISMOD_SDF_MSB;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iismod |= S3C2412_IISMOD_SDF_LSB;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		iismod |= S3C2412_IISMOD_SDF_IIS;
+		break;
+	default:
+		pr_debug("Unknown data format\n");
+		return -EINVAL;
+	}
+
+	writel(iismod, i2s->regs + S3C2412_IISMOD);
+	pr_debug("hw_params w: IISMOD: %x \n", iismod);
+	return 0;
+}
+
+static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *params,
+				 struct snd_soc_dai *socdai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai_link *dai = rtd->dai;
+	struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai);
+	u32 iismod;
+
+	pr_debug("Entered %s\n", __func__);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dai->cpu_dai->dma_data = i2s->dma_playback;
+	else
+		dai->cpu_dai->dma_data = i2s->dma_capture;
+
+	/* Working copies of register */
+	iismod = readl(i2s->regs + S3C2412_IISMOD);
+	pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		iismod |= S3C2412_IISMOD_8BIT;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		iismod &= ~S3C2412_IISMOD_8BIT;
+		break;
+	}
+
+	writel(iismod, i2s->regs + S3C2412_IISMOD);
+	pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
+	return 0;
+}
+
+static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+			       struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai);
+	int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+	unsigned long irqs;
+	int ret = 0;
+
+	pr_debug("Entered %s\n", __func__);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* On start, ensure that the FIFOs are cleared and reset. */
+
+		writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH,
+		       i2s->regs + S3C2412_IISFIC);
+
+		/* clear again, just in case */
+		writel(0x0, i2s->regs + S3C2412_IISFIC);
+
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (!i2s->master) {
+			ret = s3c2412_snd_lrsync(i2s);
+			if (ret)
+				goto exit_err;
+		}
+
+		local_irq_save(irqs);
+
+		if (capture)
+			s3c2412_snd_rxctrl(i2s, 1);
+		else
+			s3c2412_snd_txctrl(i2s, 1);
+
+		local_irq_restore(irqs);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		local_irq_save(irqs);
+
+		if (capture)
+			s3c2412_snd_rxctrl(i2s, 0);
+		else
+			s3c2412_snd_txctrl(i2s, 0);
+
+		local_irq_restore(irqs);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+exit_err:
+	return ret;
+}
+
+/*
+ * Set S3C2412 Clock dividers
+ */
+static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
+				  int div_id, int div)
+{
+	struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+	u32 reg;
+
+	pr_debug("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div);
+
+	switch (div_id) {
+	case S3C_I2SV2_DIV_BCLK:
+		reg = readl(i2s->regs + S3C2412_IISMOD);
+		reg &= ~S3C2412_IISMOD_BCLK_MASK;
+		writel(reg | div, i2s->regs + S3C2412_IISMOD);
+
+		pr_debug("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
+		break;
+
+	case S3C_I2SV2_DIV_RCLK:
+		if (div > 3) {
+			/* convert value to bit field */
+
+			switch (div) {
+			case 256:
+				div = S3C2412_IISMOD_RCLK_256FS;
+				break;
+
+			case 384:
+				div = S3C2412_IISMOD_RCLK_384FS;
+				break;
+
+			case 512:
+				div = S3C2412_IISMOD_RCLK_512FS;
+				break;
+
+			case 768:
+				div = S3C2412_IISMOD_RCLK_768FS;
+				break;
+
+			default:
+				return -EINVAL;
+			}
+		}
+
+		reg = readl(i2s->regs + S3C2412_IISMOD);
+		reg &= ~S3C2412_IISMOD_RCLK_MASK;
+		writel(reg | div, i2s->regs + S3C2412_IISMOD);
+		pr_debug("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
+		break;
+
+	case S3C_I2SV2_DIV_PRESCALER:
+		if (div >= 0) {
+			writel((div << 8) | S3C2412_IISPSR_PSREN,
+			       i2s->regs + S3C2412_IISPSR);
+		} else {
+			writel(0x0, i2s->regs + S3C2412_IISPSR);
+		}
+		pr_debug("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR));
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* default table of all avaialable root fs divisors */
+static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 };
+
+int s3c2412_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
+			  unsigned int *fstab,
+			  unsigned int rate, struct clk *clk)
+{
+	unsigned long clkrate = clk_get_rate(clk);
+	unsigned int div;
+	unsigned int fsclk;
+	unsigned int actual;
+	unsigned int fs;
+	unsigned int fsdiv;
+	signed int deviation = 0;
+	unsigned int best_fs = 0;
+	unsigned int best_div = 0;
+	unsigned int best_rate = 0;
+	unsigned int best_deviation = INT_MAX;
+
+	if (fstab == NULL)
+		fstab = iis_fs_tab;
+
+	for (fs = 0; fs < ARRAY_SIZE(iis_fs_tab); fs++) {
+		fsdiv = iis_fs_tab[fs];
+
+		fsclk = clkrate / fsdiv;
+		div = fsclk / rate;
+
+		if ((fsclk % rate) > (rate / 2))
+			div++;
+
+		if (div <= 1)
+			continue;
+
+		actual = clkrate / (fsdiv * div);
+		deviation = actual - rate;
+
+		printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n",
+		       fsdiv, div, actual, deviation);
+
+		deviation = abs(deviation);
+
+		if (deviation < best_deviation) {
+			best_fs = fsdiv;
+			best_div = div;
+			best_rate = actual;
+			best_deviation = deviation;
+		}
+
+		if (deviation == 0)
+			break;
+	}
+
+	printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n",
+	       best_fs, best_div, best_rate);
+
+	info->fs_div = best_fs;
+	info->clk_div = best_div;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate);
+
+int s3c_i2sv2_probe(struct platform_device *pdev,
+		    struct snd_soc_dai *dai,
+		    struct s3c_i2sv2_info *i2s,
+		    unsigned long base)
+{
+	struct device *dev = &pdev->dev;
+
+	i2s->dev = dev;
+
+	/* record our i2s structure for later use in the callbacks */
+	dai->private_data = i2s;
+
+	i2s->regs = ioremap(base, 0x100);
+	if (i2s->regs == NULL) {
+		dev_err(dev, "cannot ioremap registers\n");
+		return -ENXIO;
+	}
+
+	i2s->iis_pclk = clk_get(dev, "iis");
+	if (i2s->iis_pclk == NULL) {
+		dev_err(dev, "failed to get iis_clock\n");
+		iounmap(i2s->regs);
+		return -ENOENT;
+	}
+
+	clk_enable(i2s->iis_pclk);
+
+	s3c2412_snd_txctrl(i2s, 0);
+	s3c2412_snd_rxctrl(i2s, 0);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(s3c_i2sv2_probe);
+
+#ifdef CONFIG_PM
+static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
+{
+	struct s3c_i2sv2_info *i2s = to_info(dai);
+	u32 iismod;
+
+	if (dai->active) {
+		i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
+		i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
+		i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
+
+		/* some basic suspend checks */
+
+		iismod = readl(i2s->regs + S3C2412_IISMOD);
+
+		if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
+			pr_warning("%s: RXDMA active?\n", __func__);
+
+		if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
+			pr_warning("%s: TXDMA active?\n", __func__);
+
+		if (iismod & S3C2412_IISCON_IIS_ACTIVE)
+			pr_warning("%s: IIS active\n", __func__);
+	}
+
+	return 0;
+}
+
+static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
+{
+	struct s3c_i2sv2_info *i2s = to_info(dai);
+
+	pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
+		dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
+
+	if (dai->active) {
+		writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
+		writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
+		writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
+
+		writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
+		       i2s->regs + S3C2412_IISFIC);
+
+		ndelay(250);
+		writel(0x0, i2s->regs + S3C2412_IISFIC);
+	}
+
+	return 0;
+}
+#else
+#define s3c2412_i2s_suspend NULL
+#define s3c2412_i2s_resume  NULL
+#endif
+
+int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
+{
+	dai->ops.trigger = s3c2412_i2s_trigger;
+	dai->ops.hw_params = s3c2412_i2s_hw_params;
+	dai->ops.set_fmt = s3c2412_i2s_set_fmt;
+	dai->ops.set_clkdiv = s3c2412_i2s_set_clkdiv;
+
+	dai->suspend = s3c2412_i2s_suspend;
+	dai->resume = s3c2412_i2s_resume;
+
+	return snd_soc_register_dai(dai);
+}
+
+EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai);
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h
new file mode 100644
index 0000000..f66854a
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.h
@@ -0,0 +1,90 @@
+/* sound/soc/s3c24xx/s3c-i2s-v2.h
+ *
+ * ALSA Soc Audio Layer - S3C_I2SV2 I2S driver
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+*/
+
+/* This code is the core support for the I2S block found in a number of
+ * Samsung SoC devices which is unofficially named I2S-V2. Currently the
+ * S3C2412 and the S3C64XX series use this block to provide 1 or 2 I2S
+ * channels via configurable GPIO.
+ */
+
+#ifndef __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H
+#define __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H __FILE__
+
+#define S3C_I2SV2_DIV_BCLK	(1)
+#define S3C_I2SV2_DIV_RCLK	(2)
+#define S3C_I2SV2_DIV_PRESCALER	(3)
+
+/**
+ * struct s3c_i2sv2_info - S3C I2S-V2 information
+ * @dev: The parent device passed to use from the probe.
+ * @regs: The pointer to the device registe block.
+ * @master: True if the I2S core is the I2S bit clock master.
+ * @dma_playback: DMA information for playback channel.
+ * @dma_capture: DMA information for capture channel.
+ * @suspend_iismod: PM save for the IISMOD register.
+ * @suspend_iiscon: PM save for the IISCON register.
+ * @suspend_iispsr: PM save for the IISPSR register.
+ *
+ * This is the private codec state for the hardware associated with an
+ * I2S channel such as the register mappings and clock sources.
+ */
+struct s3c_i2sv2_info {
+	struct device	*dev;
+	void __iomem	*regs;
+
+	struct clk	*iis_pclk;
+	struct clk	*iis_cclk;
+	struct clk	*iis_clk;
+
+	unsigned char	 master;
+
+	struct s3c24xx_pcm_dma_params	*dma_playback;
+	struct s3c24xx_pcm_dma_params	*dma_capture;
+
+	u32		 suspend_iismod;
+	u32		 suspend_iiscon;
+	u32		 suspend_iispsr;
+};
+
+struct s3c_i2sv2_rate_calc {
+	unsigned int	clk_div;	/* for prescaler */
+	unsigned int	fs_div;		/* for root frame clock */
+};
+
+extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
+				   unsigned int *fstab,
+				   unsigned int rate, struct clk *clk);
+
+/**
+ * s3c_i2sv2_probe - probe for i2s device helper
+ * @pdev: The platform device supplied to the original probe.
+ * @dai: The ASoC DAI structure supplied to the original probe.
+ * @i2s: Our local i2s structure to fill in.
+ * @base: The base address for the registers.
+ */
+extern int s3c_i2sv2_probe(struct platform_device *pdev,
+			   struct snd_soc_dai *dai,
+			   struct s3c_i2sv2_info *i2s,
+			   unsigned long base);
+
+/**
+ * s3c_i2sv2_register_dai - register dai with soc core
+ * @dai: The snd_soc_dai structure to register
+ *
+ * Fill in any missing fields and then register the given dai with the
+ * soc core.
+ */
+extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai);
+
+#endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index f3fc0ab..1ca3cda 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/kernel.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -30,26 +31,16 @@
 #include <sound/soc.h>
 #include <mach/hardware.h>
 
-#include <linux/io.h>
-#include <asm/dma.h>
+#include <plat/regs-s3c2412-iis.h>
 
-#include <asm/plat-s3c24xx/regs-s3c2412-iis.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/audio.h>
+#include <plat/regs-gpio.h>
+#include <plat/audio.h>
 #include <mach/dma.h>
 
 #include "s3c24xx-pcm.h"
 #include "s3c2412-i2s.h"
 
 #define S3C2412_I2S_DEBUG 0
-#define S3C2412_I2S_DEBUG_CON 0
-
-#if S3C2412_I2S_DEBUG
-#define DBG(x...) printk(KERN_INFO x)
-#else
-#define DBG(x...) do { } while (0)
-#endif
 
 static struct s3c2410_dma_client s3c2412_dma_client_out = {
 	.name		= "I2S PCM Stereo out"
@@ -73,431 +64,7 @@
 	.dma_size	= 4,
 };
 
-struct s3c2412_i2s_info {
-	struct device	*dev;
-	void __iomem	*regs;
-	struct clk	*iis_clk;
-	struct clk	*iis_pclk;
-	struct clk	*iis_cclk;
-
-	u32		 suspend_iismod;
-	u32		 suspend_iiscon;
-	u32		 suspend_iispsr;
-};
-
-static struct s3c2412_i2s_info s3c2412_i2s;
-
-#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
-
-#if S3C2412_I2S_DEBUG_CON
-static void dbg_showcon(const char *fn, u32 con)
-{
-	printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d, RXFFULL=%d\n", fn,
-	       bit_set(con, S3C2412_IISCON_LRINDEX),
-	       bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY),
-	       bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY),
-	       bit_set(con, S3C2412_IISCON_TXFIFO_FULL),
-	       bit_set(con, S3C2412_IISCON_RXFIFO_FULL));
-
-	printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n",
-	       fn,
-	       bit_set(con, S3C2412_IISCON_TXDMA_PAUSE),
-	       bit_set(con, S3C2412_IISCON_RXDMA_PAUSE),
-	       bit_set(con, S3C2412_IISCON_TXCH_PAUSE),
-	       bit_set(con, S3C2412_IISCON_RXCH_PAUSE));
-	printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn,
-	       bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE),
-	       bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE),
-	       bit_set(con, S3C2412_IISCON_IIS_ACTIVE));
-}
-#else
-static inline void dbg_showcon(const char *fn, u32 con)
-{
-}
-#endif
-
-/* Turn on or off the transmission path. */
-static void s3c2412_snd_txctrl(int on)
-{
-	struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
-	void __iomem *regs = i2s->regs;
-	u32 fic, con, mod;
-
-	DBG("%s(%d)\n", __func__, on);
-
-	fic = readl(regs + S3C2412_IISFIC);
-	con = readl(regs + S3C2412_IISCON);
-	mod = readl(regs + S3C2412_IISMOD);
-
-	DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
-
-	if (on) {
-		con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
-		con &= ~S3C2412_IISCON_TXDMA_PAUSE;
-		con &= ~S3C2412_IISCON_TXCH_PAUSE;
-
-		switch (mod & S3C2412_IISMOD_MODE_MASK) {
-		case S3C2412_IISMOD_MODE_TXONLY:
-		case S3C2412_IISMOD_MODE_TXRX:
-			/* do nothing, we are in the right mode */
-			break;
-
-		case S3C2412_IISMOD_MODE_RXONLY:
-			mod &= ~S3C2412_IISMOD_MODE_MASK;
-			mod |= S3C2412_IISMOD_MODE_TXRX;
-			break;
-
-		default:
-			dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n");
-		}
-
-		writel(con, regs + S3C2412_IISCON);
-		writel(mod, regs + S3C2412_IISMOD);
-	} else {
-		/* Note, we do not have any indication that the FIFO problems
-		 * tha the S3C2410/2440 had apply here, so we should be able
-		 * to disable the DMA and TX without resetting the FIFOS.
-		 */
-
-		con |=  S3C2412_IISCON_TXDMA_PAUSE;
-		con |=  S3C2412_IISCON_TXCH_PAUSE;
-		con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
-
-		switch (mod & S3C2412_IISMOD_MODE_MASK) {
-		case S3C2412_IISMOD_MODE_TXRX:
-			mod &= ~S3C2412_IISMOD_MODE_MASK;
-			mod |= S3C2412_IISMOD_MODE_RXONLY;
-			break;
-
-		case S3C2412_IISMOD_MODE_TXONLY:
-			mod &= ~S3C2412_IISMOD_MODE_MASK;
-			con &= ~S3C2412_IISCON_IIS_ACTIVE;
-			break;
-
-		default:
-			dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n");
-		}
-
-		writel(mod, regs + S3C2412_IISMOD);
-		writel(con, regs + S3C2412_IISCON);
-	}
-
-	fic = readl(regs + S3C2412_IISFIC);
-	dbg_showcon(__func__, con);
-	DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
-}
-
-static void s3c2412_snd_rxctrl(int on)
-{
-	struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
-	void __iomem *regs = i2s->regs;
-	u32 fic, con, mod;
-
-	DBG("%s(%d)\n", __func__, on);
-
-	fic = readl(regs + S3C2412_IISFIC);
-	con = readl(regs + S3C2412_IISCON);
-	mod = readl(regs + S3C2412_IISMOD);
-
-	DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
-
-	if (on) {
-		con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
-		con &= ~S3C2412_IISCON_RXDMA_PAUSE;
-		con &= ~S3C2412_IISCON_RXCH_PAUSE;
-
-		switch (mod & S3C2412_IISMOD_MODE_MASK) {
-		case S3C2412_IISMOD_MODE_TXRX:
-		case S3C2412_IISMOD_MODE_RXONLY:
-			/* do nothing, we are in the right mode */
-			break;
-
-		case S3C2412_IISMOD_MODE_TXONLY:
-			mod &= ~S3C2412_IISMOD_MODE_MASK;
-			mod |= S3C2412_IISMOD_MODE_TXRX;
-			break;
-
-		default:
-			dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
-		}
-
-		writel(mod, regs + S3C2412_IISMOD);
-		writel(con, regs + S3C2412_IISCON);
-	} else {
-		/* See txctrl notes on FIFOs. */
-
-		con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
-		con |=  S3C2412_IISCON_RXDMA_PAUSE;
-		con |=  S3C2412_IISCON_RXCH_PAUSE;
-
-		switch (mod & S3C2412_IISMOD_MODE_MASK) {
-		case S3C2412_IISMOD_MODE_RXONLY:
-			con &= ~S3C2412_IISCON_IIS_ACTIVE;
-			mod &= ~S3C2412_IISMOD_MODE_MASK;
-			break;
-
-		case S3C2412_IISMOD_MODE_TXRX:
-			mod &= ~S3C2412_IISMOD_MODE_MASK;
-			mod |= S3C2412_IISMOD_MODE_TXONLY;
-			break;
-
-		default:
-			dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
-		}
-
-		writel(con, regs + S3C2412_IISCON);
-		writel(mod, regs + S3C2412_IISMOD);
-	}
-
-	fic = readl(regs + S3C2412_IISFIC);
-	DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
-}
-
-
-/*
- * Wait for the LR signal to allow synchronisation to the L/R clock
- * from the codec. May only be needed for slave mode.
- */
-static int s3c2412_snd_lrsync(void)
-{
-	u32 iiscon;
-	unsigned long timeout = jiffies + msecs_to_jiffies(5);
-
-	DBG("Entered %s\n", __func__);
-
-	while (1) {
-		iiscon = readl(s3c2412_i2s.regs + S3C2412_IISCON);
-		if (iiscon & S3C2412_IISCON_LRINDEX)
-			break;
-
-		if (timeout < jiffies) {
-			printk(KERN_ERR "%s: timeout\n", __func__);
-			return -ETIMEDOUT;
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Check whether CPU is the master or slave
- */
-static inline int s3c2412_snd_is_clkmaster(void)
-{
-	u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
-
-	DBG("Entered %s\n", __func__);
-
-	iismod &= S3C2412_IISMOD_MASTER_MASK;
-	return !(iismod == S3C2412_IISMOD_SLAVE);
-}
-
-/*
- * Set S3C2412 I2S DAI format
- */
-static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
-			       unsigned int fmt)
-{
-	u32 iismod;
-
-
-	DBG("Entered %s\n", __func__);
-
-	iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
-	DBG("hw_params r: IISMOD: %x \n", iismod);
-
-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-	case SND_SOC_DAIFMT_CBM_CFM:
-		iismod &= ~S3C2412_IISMOD_MASTER_MASK;
-		iismod |= S3C2412_IISMOD_SLAVE;
-		break;
-	case SND_SOC_DAIFMT_CBS_CFS:
-		iismod &= ~S3C2412_IISMOD_MASTER_MASK;
-		iismod |= S3C2412_IISMOD_MASTER_INTERNAL;
-		break;
-	default:
-		DBG("unknwon master/slave format\n");
-		return -EINVAL;
-	}
-
-	iismod &= ~S3C2412_IISMOD_SDF_MASK;
-
-	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_RIGHT_J:
-		iismod |= S3C2412_IISMOD_SDF_MSB;
-		break;
-	case SND_SOC_DAIFMT_LEFT_J:
-		iismod |= S3C2412_IISMOD_SDF_LSB;
-		break;
-	case SND_SOC_DAIFMT_I2S:
-		iismod |= S3C2412_IISMOD_SDF_IIS;
-		break;
-	default:
-		DBG("Unknown data format\n");
-		return -EINVAL;
-	}
-
-	writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD);
-	DBG("hw_params w: IISMOD: %x \n", iismod);
-	return 0;
-}
-
-static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
-				 struct snd_pcm_hw_params *params,
-				 struct snd_soc_dai *dai)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	u32 iismod;
-
-	DBG("Entered %s\n", __func__);
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_out;
-	else
-		rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_in;
-
-	/* Working copies of register */
-	iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
-	DBG("%s: r: IISMOD: %x\n", __func__, iismod);
-
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S8:
-		iismod |= S3C2412_IISMOD_8BIT;
-		break;
-	case SNDRV_PCM_FORMAT_S16_LE:
-		iismod &= ~S3C2412_IISMOD_8BIT;
-		break;
-	}
-
-	writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD);
-	DBG("%s: w: IISMOD: %x\n", __func__, iismod);
-	return 0;
-}
-
-static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
-			       struct snd_soc_dai *dai)
-{
-	int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
-	unsigned long irqs;
-	int ret = 0;
-
-	DBG("Entered %s\n", __func__);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		/* On start, ensure that the FIFOs are cleared and reset. */
-
-		writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH,
-		       s3c2412_i2s.regs + S3C2412_IISFIC);
-
-		/* clear again, just in case */
-		writel(0x0, s3c2412_i2s.regs + S3C2412_IISFIC);
-
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (!s3c2412_snd_is_clkmaster()) {
-			ret = s3c2412_snd_lrsync();
-			if (ret)
-				goto exit_err;
-		}
-
-		local_irq_save(irqs);
-
-		if (capture)
-			s3c2412_snd_rxctrl(1);
-		else
-			s3c2412_snd_txctrl(1);
-
-		local_irq_restore(irqs);
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		local_irq_save(irqs);
-
-		if (capture)
-			s3c2412_snd_rxctrl(0);
-		else
-			s3c2412_snd_txctrl(0);
-
-		local_irq_restore(irqs);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-exit_err:
-	return ret;
-}
-
-/* default table of all avaialable root fs divisors */
-static unsigned int s3c2412_iis_fs[] = { 256, 512, 384, 768, 0 };
-
-int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info,
-			  unsigned int *fstab,
-			  unsigned int rate, struct clk *clk)
-{
-	unsigned long clkrate = clk_get_rate(clk);
-	unsigned int div;
-	unsigned int fsclk;
-	unsigned int actual;
-	unsigned int fs;
-	unsigned int fsdiv;
-	signed int deviation = 0;
-	unsigned int best_fs = 0;
-	unsigned int best_div = 0;
-	unsigned int best_rate = 0;
-	unsigned int best_deviation = INT_MAX;
-
-
-	if (fstab == NULL)
-		fstab = s3c2412_iis_fs;
-
-	for (fs = 0;; fs++) {
-		fsdiv = s3c2412_iis_fs[fs];
-
-		if (fsdiv == 0)
-			break;
-
-		fsclk = clkrate / fsdiv;
-		div = fsclk / rate;
-
-		if ((fsclk % rate) > (rate / 2))
-			div++;
-
-		if (div <= 1)
-			continue;
-
-		actual = clkrate / (fsdiv * div);
-		deviation = actual - rate;
-
-		printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n",
-		       fsdiv, div, actual, deviation);
-
-		deviation = abs(deviation);
-
-		if (deviation < best_deviation) {
-			best_fs = fsdiv;
-			best_div = div;
-			best_rate = actual;
-			best_deviation = deviation;
-		}
-
-		if (deviation == 0)
-			break;
-	}
-
-	printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n",
-	       best_fs, best_div, best_rate);
-
-	info->fs_div = best_fs;
-	info->clk_div = best_div;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate);
+static struct s3c_i2sv2_info s3c2412_i2s;
 
 /*
  * Set S3C2412 Clock source
@@ -507,15 +74,17 @@
 {
 	u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
 
-	DBG("%s(%p, %d, %u, %d)\n", __func__, cpu_dai, clk_id,
+	pr_debug("%s(%p, %d, %u, %d)\n", __func__, cpu_dai, clk_id,
 	    freq, dir);
 
 	switch (clk_id) {
 	case S3C2412_CLKSRC_PCLK:
+		s3c2412_i2s.master = 1;
 		iismod &= ~S3C2412_IISMOD_MASTER_MASK;
 		iismod |= S3C2412_IISMOD_MASTER_INTERNAL;
 		break;
 	case S3C2412_CLKSRC_I2SCLK:
+		s3c2412_i2s.master = 0;
 		iismod &= ~S3C2412_IISMOD_MASTER_MASK;
 		iismod |= S3C2412_IISMOD_MASTER_EXTERNAL;
 		break;
@@ -527,74 +96,6 @@
 	return 0;
 }
 
-/*
- * Set S3C2412 Clock dividers
- */
-static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
-				  int div_id, int div)
-{
-	struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
-	u32 reg;
-
-	DBG("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div);
-
-	switch (div_id) {
-	case S3C2412_DIV_BCLK:
-		reg = readl(i2s->regs + S3C2412_IISMOD);
-		reg &= ~S3C2412_IISMOD_BCLK_MASK;
-		writel(reg | div, i2s->regs + S3C2412_IISMOD);
-
-		DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
-		break;
-
-	case S3C2412_DIV_RCLK:
-		if (div > 3) {
-			/* convert value to bit field */
-
-			switch (div) {
-			case 256:
-				div = S3C2412_IISMOD_RCLK_256FS;
-				break;
-
-			case 384:
-				div = S3C2412_IISMOD_RCLK_384FS;
-				break;
-
-			case 512:
-				div = S3C2412_IISMOD_RCLK_512FS;
-				break;
-
-			case 768:
-				div = S3C2412_IISMOD_RCLK_768FS;
-				break;
-
-			default:
-				return -EINVAL;
-			}
-		}
-
-		reg = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
-		reg &= ~S3C2412_IISMOD_RCLK_MASK;
-		writel(reg | div, i2s->regs + S3C2412_IISMOD);
-		DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
-		break;
-
-	case S3C2412_DIV_PRESCALER:
-		if (div >= 0) {
-			writel((div << 8) | S3C2412_IISPSR_PSREN,
-			       i2s->regs + S3C2412_IISPSR);
-		} else {
-			writel(0x0, i2s->regs + S3C2412_IISPSR);
-		}
-		DBG("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR));
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
 
 struct clk *s3c2412_get_iisclk(void)
 {
@@ -606,34 +107,30 @@
 static int s3c2412_i2s_probe(struct platform_device *pdev,
 			     struct snd_soc_dai *dai)
 {
-	DBG("Entered %s\n", __func__);
+	int ret;
 
-	s3c2412_i2s.dev = &pdev->dev;
+	pr_debug("Entered %s\n", __func__);
 
-	s3c2412_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
-	if (s3c2412_i2s.regs == NULL)
-		return -ENXIO;
+	ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS);
+	if (ret)
+		return ret;
 
-	s3c2412_i2s.iis_pclk = clk_get(&pdev->dev, "iis");
-	if (s3c2412_i2s.iis_pclk == NULL) {
-		DBG("failed to get iis_clock\n");
-		iounmap(s3c2412_i2s.regs);
-		return -ENODEV;
-	}
+	s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in;
+	s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
 
 	s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk");
 	if (s3c2412_i2s.iis_cclk == NULL) {
-		DBG("failed to get i2sclk clock\n");
+		pr_debug("failed to get i2sclk clock\n");
 		iounmap(s3c2412_i2s.regs);
 		return -ENODEV;
 	}
 
-	clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll"));
+	/* Set MPLL as the source for IIS CLK */
 
-	clk_enable(s3c2412_i2s.iis_pclk);
+	clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll"));
 	clk_enable(s3c2412_i2s.iis_cclk);
 
-	s3c2412_i2s.iis_clk = s3c2412_i2s.iis_pclk;
+	s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk;
 
 	/* Configure the I2S pins in correct mode */
 	s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK);
@@ -642,78 +139,22 @@
 	s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI);
 	s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO);
 
-	s3c2412_snd_txctrl(0);
-	s3c2412_snd_rxctrl(0);
-
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
-{
-	struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
-	u32 iismod;
-
-	if (dai->active) {
-		i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
-		i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
-		i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
-
-		/* some basic suspend checks */
-
-		iismod = readl(i2s->regs + S3C2412_IISMOD);
-
-		if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
-			pr_warning("%s: RXDMA active?\n", __func__);
-
-		if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
-			pr_warning("%s: TXDMA active?\n", __func__);
-
-		if (iismod & S3C2412_IISCON_IIS_ACTIVE)
-			pr_warning("%s: IIS active\n", __func__);
-	}
-
-	return 0;
-}
-
-static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
-{
-	struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
-
-	pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
-		dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
-
-	if (dai->active) {
-		writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
-		writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
-		writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
-
-		writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
-		       i2s->regs + S3C2412_IISFIC);
-
-		ndelay(250);
-		writel(0x0, i2s->regs + S3C2412_IISFIC);
-
-	}
-
-	return 0;
-}
-#else
-#define s3c2412_i2s_suspend NULL
-#define s3c2412_i2s_resume  NULL
-#endif /* CONFIG_PM */
-
 #define S3C2412_I2S_RATES \
 	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 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)
 
+static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
+	.set_sysclk	= s3c2412_i2s_set_sysclk,
+};
+
 struct snd_soc_dai s3c2412_i2s_dai = {
-	.name	= "s3c2412-i2s",
-	.id	= 0,
-	.probe	= s3c2412_i2s_probe,
-	.suspend = s3c2412_i2s_suspend,
-	.resume = s3c2412_i2s_resume,
+	.name		= "s3c2412-i2s",
+	.id		= 0,
+	.probe		= s3c2412_i2s_probe,
 	.playback = {
 		.channels_min	= 2,
 		.channels_max	= 2,
@@ -726,19 +167,13 @@
 		.rates		= S3C2412_I2S_RATES,
 		.formats	= SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,
 	},
-	.ops = {
-		.trigger	= s3c2412_i2s_trigger,
-		.hw_params	= s3c2412_i2s_hw_params,
-		.set_fmt	= s3c2412_i2s_set_fmt,
-		.set_clkdiv	= s3c2412_i2s_set_clkdiv,
-		.set_sysclk	= s3c2412_i2s_set_sysclk,
-	},
+	.ops = &s3c2412_i2s_dai_ops,
 };
 EXPORT_SYMBOL_GPL(s3c2412_i2s_dai);
 
 static int __init s3c2412_i2s_init(void)
 {
-	return snd_soc_register_dai(&s3c2412_i2s_dai);
+	return  s3c_i2sv2_register_dai(&s3c2412_i2s_dai);
 }
 module_init(s3c2412_i2s_init);
 
@@ -748,7 +183,6 @@
 }
 module_exit(s3c2412_i2s_exit);
 
-
 /* Module information */
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h
index aac08a2..92848e54 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.h
+++ b/sound/soc/s3c24xx/s3c2412-i2s.h
@@ -15,9 +15,11 @@
 #ifndef __SND_SOC_S3C24XX_S3C2412_I2S_H
 #define __SND_SOC_S3C24XX_S3C2412_I2S_H __FILE__
 
-#define S3C2412_DIV_BCLK	(1)
-#define S3C2412_DIV_RCLK	(2)
-#define S3C2412_DIV_PRESCALER	(3)
+#include "s3c-i2s-v2.h"
+
+#define S3C2412_DIV_BCLK	S3C_I2SV2_DIV_BCLK
+#define S3C2412_DIV_RCLK	S3C_I2SV2_DIV_RCLK
+#define S3C2412_DIV_PRESCALER	S3C_I2SV2_DIV_PRESCALER
 
 #define S3C2412_CLKSRC_PCLK	(0)
 #define S3C2412_CLKSRC_I2SCLK	(1)
@@ -26,13 +28,4 @@
 
 extern struct snd_soc_dai s3c2412_i2s_dai;
 
-struct s3c2412_rate_calc {
-	unsigned int	clk_div;	/* for prescaler */
-	unsigned int	fs_div;		/* for root frame clock */
-};
-
-extern int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info,
-				 unsigned int *fstab,
-				 unsigned int rate, struct clk *clk);
-
 #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index 5822d2d..3698f70 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -31,7 +31,7 @@
 #include <plat/regs-ac97.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
-#include <mach/audio.h>
+#include <plat/audio.h>
 #include <asm/dma.h>
 #include <mach/dma.h>
 
@@ -355,6 +355,16 @@
 		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
 		SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
 
+static struct snd_soc_dai_ops s3c2443_ac97_dai_ops = {
+	.hw_params	= s3c2443_ac97_hw_params,
+	.trigger	= s3c2443_ac97_trigger,
+};
+
+static struct snd_soc_dai_ops s3c2443_ac97_mic_dai_ops = {
+	.hw_params	= s3c2443_ac97_hw_mic_params,
+	.trigger	= s3c2443_ac97_mic_trigger,
+};
+
 struct snd_soc_dai s3c2443_ac97_dai[] = {
 {
 	.name = "s3c2443-ac97",
@@ -374,9 +384,7 @@
 		.channels_max = 2,
 		.rates = s3c2443_AC97_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.hw_params = s3c2443_ac97_hw_params,
-		.trigger = s3c2443_ac97_trigger},
+	.ops = &s3c2443_ac97_dai_ops,
 },
 {
 	.name = "pxa2xx-ac97-mic",
@@ -388,9 +396,7 @@
 		.channels_max = 1,
 		.rates = s3c2443_AC97_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.hw_params = s3c2443_ac97_hw_mic_params,
-		.trigger = s3c2443_ac97_mic_trigger,},
+	.ops = &s3c2443_ac97_mic_dai_ops,
 },
 };
 EXPORT_SYMBOL_GPL(s3c2443_ac97_dai);
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 6f4d439..cc06696 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -4,7 +4,7 @@
  * (c) 2006 Wolfson Microelectronics PLC.
  * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
  *
- * (c) 2004-2005 Simtec Electronics
+ * Copyright 2004-2005 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
  *	Ben Dooks <ben@simtec.co.uk>
  *
@@ -30,22 +30,15 @@
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
-#include <mach/audio.h>
+#include <plat/audio.h>
 #include <asm/dma.h>
 #include <mach/dma.h>
 
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-iis.h>
 
 #include "s3c24xx-pcm.h"
 #include "s3c24xx-i2s.h"
 
-#define S3C24XX_I2S_DEBUG 0
-#if S3C24XX_I2S_DEBUG
-#define DBG(x...) printk(KERN_DEBUG "s3c24xx-i2s: " x)
-#else
-#define DBG(x...)
-#endif
-
 static struct s3c2410_dma_client s3c24xx_dma_client_out = {
 	.name = "I2S PCM Stereo out"
 };
@@ -84,13 +77,13 @@
 	u32 iiscon;
 	u32 iismod;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
 	iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
 	iismod  = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
 
-	DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon);
+	pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon);
 
 	if (on) {
 		iisfcon |= S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE;
@@ -120,7 +113,7 @@
 		writel(iismod,  s3c24xx_i2s.regs + S3C2410_IISMOD);
 	}
 
-	DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon);
+	pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon);
 }
 
 static void s3c24xx_snd_rxctrl(int on)
@@ -129,13 +122,13 @@
 	u32 iiscon;
 	u32 iismod;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
 	iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
 	iismod  = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
 
-	DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon);
+	pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon);
 
 	if (on) {
 		iisfcon |= S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE;
@@ -165,7 +158,7 @@
 		writel(iismod,  s3c24xx_i2s.regs + S3C2410_IISMOD);
 	}
 
-	DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon);
+	pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon);
 }
 
 /*
@@ -177,7 +170,7 @@
 	u32 iiscon;
 	int timeout = 50; /* 5ms */
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	while (1) {
 		iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
@@ -197,7 +190,7 @@
  */
 static inline int s3c24xx_snd_is_clkmaster(void)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1;
 }
@@ -210,10 +203,10 @@
 {
 	u32 iismod;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
-	DBG("hw_params r: IISMOD: %lx \n", iismod);
+	pr_debug("hw_params r: IISMOD: %x \n", iismod);
 
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBM_CFM:
@@ -238,7 +231,7 @@
 	}
 
 	writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
-	DBG("hw_params w: IISMOD: %lx \n", iismod);
+	pr_debug("hw_params w: IISMOD: %x \n", iismod);
 	return 0;
 }
 
@@ -249,7 +242,7 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	u32 iismod;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out;
@@ -258,7 +251,7 @@
 
 	/* Working copies of register */
 	iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
-	DBG("hw_params r: IISMOD: %lx\n", iismod);
+	pr_debug("hw_params r: IISMOD: %x\n", iismod);
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S8:
@@ -276,7 +269,7 @@
 	}
 
 	writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
-	DBG("hw_params w: IISMOD: %lx\n", iismod);
+	pr_debug("hw_params w: IISMOD: %x\n", iismod);
 	return 0;
 }
 
@@ -285,7 +278,7 @@
 {
 	int ret = 0;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -327,7 +320,7 @@
 {
 	u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	iismod &= ~S3C2440_IISMOD_MPLL;
 
@@ -353,7 +346,7 @@
 {
 	u32 reg;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	switch (div_id) {
 	case S3C24XX_DIV_BCLK:
@@ -389,7 +382,7 @@
 static int s3c24xx_i2s_probe(struct platform_device *pdev,
 			     struct snd_soc_dai *dai)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
 	if (s3c24xx_i2s.regs == NULL)
@@ -397,7 +390,7 @@
 
 	s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis");
 	if (s3c24xx_i2s.iis_clk == NULL) {
-		DBG("failed to get iis_clock\n");
+		pr_err("failed to get iis_clock\n");
 		iounmap(s3c24xx_i2s.regs);
 		return -ENODEV;
 	}
@@ -421,7 +414,7 @@
 #ifdef CONFIG_PM
 static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
 	s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -435,7 +428,7 @@
 
 static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
 {
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 	clk_enable(s3c24xx_i2s.iis_clk);
 
 	writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
@@ -456,6 +449,14 @@
 	SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
 	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
+static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
+	.trigger	= s3c24xx_i2s_trigger,
+	.hw_params	= s3c24xx_i2s_hw_params,
+	.set_fmt	= s3c24xx_i2s_set_fmt,
+	.set_clkdiv	= s3c24xx_i2s_set_clkdiv,
+	.set_sysclk	= s3c24xx_i2s_set_sysclk,
+};
+
 struct snd_soc_dai s3c24xx_i2s_dai = {
 	.name = "s3c24xx-i2s",
 	.id = 0,
@@ -472,13 +473,7 @@
 		.channels_max = 2,
 		.rates = S3C24XX_I2S_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
-	.ops = {
-		.trigger = s3c24xx_i2s_trigger,
-		.hw_params = s3c24xx_i2s_hw_params,
-		.set_fmt = s3c24xx_i2s_set_fmt,
-		.set_clkdiv = s3c24xx_i2s_set_clkdiv,
-		.set_sysclk = s3c24xx_i2s_set_sysclk,
-	},
+	.ops = &s3c24xx_i2s_dai_ops,
 };
 EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai);
 
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 7c64d31..a9d68fa 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -4,7 +4,7 @@
  * (c) 2006 Wolfson Microelectronics PLC.
  * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
  *
- * (c) 2004-2005 Simtec Electronics
+ * Copyright 2004-2005 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
  *	Ben Dooks <ben@simtec.co.uk>
  *
@@ -29,17 +29,10 @@
 #include <asm/dma.h>
 #include <mach/hardware.h>
 #include <mach/dma.h>
-#include <mach/audio.h>
+#include <plat/audio.h>
 
 #include "s3c24xx-pcm.h"
 
-#define S3C24XX_PCM_DEBUG 0
-#if S3C24XX_PCM_DEBUG
-#define DBG(x...) printk(KERN_DEBUG "s3c24xx-pcm: " x)
-#else
-#define DBG(x...)
-#endif
-
 static const struct snd_pcm_hardware s3c24xx_pcm_hardware = {
 	.info			= SNDRV_PCM_INFO_INTERLEAVED |
 				    SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -84,16 +77,16 @@
 	dma_addr_t pos = prtd->dma_pos;
 	int ret;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	while (prtd->dma_loaded < prtd->dma_limit) {
 		unsigned long len = prtd->dma_period;
 
-		DBG("dma_loaded: %d\n", prtd->dma_loaded);
+		pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
 
 		if ((pos + len) > prtd->dma_end) {
 			len  = prtd->dma_end - pos;
-			DBG(KERN_DEBUG "%s: corrected dma len %ld\n",
+			pr_debug(KERN_DEBUG "%s: corrected dma len %ld\n",
 			       __func__, len);
 		}
 
@@ -119,7 +112,7 @@
 	struct snd_pcm_substream *substream = dev_id;
 	struct s3c24xx_runtime_data *prtd;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
 		return;
@@ -148,7 +141,7 @@
 	unsigned long totbytes = params_buffer_bytes(params);
 	int ret = 0;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	/* return if this is a bufferless transfer e.g.
 	 * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -161,14 +154,14 @@
 		/* prepare DMA */
 		prtd->params = dma;
 
-		DBG("params %p, client %p, channel %d\n", prtd->params,
+		pr_debug("params %p, client %p, channel %d\n", prtd->params,
 			prtd->params->client, prtd->params->channel);
 
 		ret = s3c2410_dma_request(prtd->params->channel,
 					  prtd->params->client, NULL);
 
 		if (ret < 0) {
-			DBG(KERN_ERR "failed to get dma channel\n");
+			printk(KERN_ERR "failed to get dma channel\n");
 			return ret;
 		}
 	}
@@ -196,7 +189,7 @@
 {
 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	/* TODO - do we need to ensure DMA flushed */
 	snd_pcm_set_runtime_buffer(substream, NULL);
@@ -214,7 +207,7 @@
 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
 	int ret = 0;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	/* return if this is a bufferless transfer e.g.
 	 * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -259,7 +252,7 @@
 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
 	int ret = 0;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	spin_lock(&prtd->lock);
 
@@ -297,7 +290,7 @@
 	unsigned long res;
 	dma_addr_t src, dst;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	spin_lock(&prtd->lock);
 	s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
@@ -309,7 +302,7 @@
 
 	spin_unlock(&prtd->lock);
 
-	DBG("Pointer %x %x\n", src, dst);
+	pr_debug("Pointer %x %x\n", src, dst);
 
 	/* we seem to be getting the odd error from the pcm library due
 	 * to out-of-bounds pointers. this is maybe due to the dma engine
@@ -330,7 +323,7 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct s3c24xx_runtime_data *prtd;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
 
@@ -349,10 +342,10 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct s3c24xx_runtime_data *prtd = runtime->private_data;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (!prtd)
-		DBG("s3c24xx_pcm_close called with prtd == NULL\n");
+		pr_debug("s3c24xx_pcm_close called with prtd == NULL\n");
 
 	kfree(prtd);
 
@@ -364,7 +357,7 @@
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
 				     runtime->dma_area,
@@ -390,7 +383,7 @@
 	struct snd_dma_buffer *buf = &substream->dma_buffer;
 	size_t size = s3c24xx_pcm_hardware.buffer_bytes_max;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	buf->dev.type = SNDRV_DMA_TYPE_DEV;
 	buf->dev.dev = pcm->card->dev;
@@ -409,7 +402,7 @@
 	struct snd_dma_buffer *buf;
 	int stream;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	for (stream = 0; stream < 2; stream++) {
 		substream = pcm->streams[stream].substream;
@@ -433,7 +426,7 @@
 {
 	int ret = 0;
 
-	DBG("Entered %s\n", __func__);
+	pr_debug("Entered %s\n", __func__);
 
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &s3c24xx_pcm_dmamask;
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c
index a0a4d183..8e79a41 100644
--- a/sound/soc/s3c24xx/s3c24xx_uda134x.c
+++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c
@@ -22,7 +22,7 @@
 #include <sound/s3c24xx_uda134x.h>
 #include <sound/uda134x.h>
 
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-iis.h>
 
 #include "s3c24xx-pcm.h"
 #include "s3c24xx-i2s.h"
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
new file mode 100644
index 0000000..33c5de7
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -0,0 +1,222 @@
+/* sound/soc/s3c24xx/s3c64xx-i2s.c
+ *
+ * ALSA SoC Audio Layer - S3C64XX I2S driver
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <plat/regs-s3c2412-iis.h>
+#include <plat/gpio-bank-d.h>
+#include <plat/gpio-bank-e.h>
+#include <plat/gpio-cfg.h>
+#include <plat/audio.h>
+
+#include <mach/map.h>
+#include <mach/dma.h>
+
+#include "s3c24xx-pcm.h"
+#include "s3c64xx-i2s.h"
+
+static struct s3c2410_dma_client s3c64xx_dma_client_out = {
+	.name		= "I2S PCM Stereo out"
+};
+
+static struct s3c2410_dma_client s3c64xx_dma_client_in = {
+	.name		= "I2S PCM Stereo in"
+};
+
+static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = {
+	[0] = {
+		.channel	= DMACH_I2S0_OUT,
+		.client		= &s3c64xx_dma_client_out,
+		.dma_addr	= S3C64XX_PA_IIS0 + S3C2412_IISTXD,
+		.dma_size	= 4,
+	},
+	[1] = {
+		.channel	= DMACH_I2S1_OUT,
+		.client		= &s3c64xx_dma_client_out,
+		.dma_addr	= S3C64XX_PA_IIS1 + S3C2412_IISTXD,
+		.dma_size	= 4,
+	},
+};
+
+static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_in[2] = {
+	[0] = {
+		.channel	= DMACH_I2S0_IN,
+		.client		= &s3c64xx_dma_client_in,
+		.dma_addr	= S3C64XX_PA_IIS0 + S3C2412_IISRXD,
+		.dma_size	= 4,
+	},
+	[1] = {
+		.channel	= DMACH_I2S1_IN,
+		.client		= &s3c64xx_dma_client_in,
+		.dma_addr	= S3C64XX_PA_IIS1 + S3C2412_IISRXD,
+		.dma_size	= 4,
+	},
+};
+
+static struct s3c_i2sv2_info s3c64xx_i2s[2];
+
+static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
+{
+	return cpu_dai->private_data;
+}
+
+static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
+				  int clk_id, unsigned int freq, int dir)
+{
+	struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+	u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
+
+	switch (clk_id) {
+	case S3C64XX_CLKSRC_PCLK:
+		iismod &= ~S3C64XX_IISMOD_IMS_SYSMUX;
+		break;
+
+	case S3C64XX_CLKSRC_MUX:
+		iismod |= S3C64XX_IISMOD_IMS_SYSMUX;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	writel(iismod, i2s->regs + S3C2412_IISMOD);
+
+	return 0;
+}
+
+
+unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *dai)
+{
+	struct s3c_i2sv2_info *i2s = to_info(dai);
+
+	return clk_get_rate(i2s->iis_cclk);
+}
+EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clockrate);
+
+static int s3c64xx_i2s_probe(struct platform_device *pdev,
+			     struct snd_soc_dai *dai)
+{
+	struct device *dev = &pdev->dev;
+	struct s3c_i2sv2_info *i2s;
+	int ret;
+
+	dev_dbg(dev, "%s: probing dai %d\n", __func__, pdev->id);
+
+	if (pdev->id < 0 || pdev->id > ARRAY_SIZE(s3c64xx_i2s)) {
+		dev_err(dev, "id %d out of range\n", pdev->id);
+		return -EINVAL;
+	}
+
+	i2s = &s3c64xx_i2s[pdev->id];
+
+	ret = s3c_i2sv2_probe(pdev, dai, i2s,
+			      pdev->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0);
+	if (ret)
+		return ret;
+
+	i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
+	i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
+
+	i2s->iis_cclk = clk_get(dev, "audio-bus");
+	if (IS_ERR(i2s->iis_cclk)) {
+		dev_err(dev, "failed to get audio-bus");
+		iounmap(i2s->regs);
+		return -ENODEV;
+	}
+
+	/* configure GPIO for i2s port */
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK);
+		s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI);
+		s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0);
+		break;
+	case 1:
+		s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK);
+		s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI);
+		s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0);
+	}
+
+	return 0;
+}
+
+
+#define S3C64XX_I2S_RATES \
+	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 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)
+
+#define S3C64XX_I2S_FMTS \
+	(SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE)
+
+static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = {
+	.set_sysclk	= s3c64xx_i2s_set_sysclk,	
+};
+
+struct snd_soc_dai s3c64xx_i2s_dai = {
+	.name		= "s3c64xx-i2s",
+	.id		= 0,
+	.probe		= s3c64xx_i2s_probe,
+	.playback = {
+		.channels_min	= 2,
+		.channels_max	= 2,
+		.rates		= S3C64XX_I2S_RATES,
+		.formats	= S3C64XX_I2S_FMTS,
+	},
+	.capture = {
+		.channels_min	= 2,
+		.channels_max	= 2,
+		.rates		= S3C64XX_I2S_RATES,
+		.formats	= S3C64XX_I2S_FMTS,
+	},
+	.ops = &s3c64xx_i2s_dai_ops,
+};
+EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
+
+static int __init s3c64xx_i2s_init(void)
+{
+	return  s3c_i2sv2_register_dai(&s3c64xx_i2s_dai);
+}
+module_init(s3c64xx_i2s_init);
+
+static void __exit s3c64xx_i2s_exit(void)
+{
+	snd_soc_unregister_dai(&s3c64xx_i2s_dai);
+}
+module_exit(s3c64xx_i2s_exit);
+
+/* Module information */
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("S3C64XX I2S SoC Interface");
+MODULE_LICENSE("GPL");
+
+
+
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
new file mode 100644
index 0000000..b7ffe3c
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.h
@@ -0,0 +1,31 @@
+/* sound/soc/s3c24xx/s3c64xx-i2s.h
+ *
+ * ALSA SoC Audio Layer - S3C64XX I2S driver
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@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.
+ */
+
+#ifndef __SND_SOC_S3C24XX_S3C64XX_I2S_H
+#define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__
+
+#include "s3c-i2s-v2.h"
+
+#define S3C64XX_DIV_BCLK	S3C_I2SV2_DIV_BCLK
+#define S3C64XX_DIV_RCLK	S3C_I2SV2_DIV_RCLK
+#define S3C64XX_DIV_PRESCALER	S3C_I2SV2_DIV_PRESCALER
+
+#define S3C64XX_CLKSRC_PCLK	(0)
+#define S3C64XX_CLKSRC_MUX	(1)
+
+extern struct snd_soc_dai s3c64xx_i2s_dai;
+
+extern unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *cpu_dai);
+
+#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index eab3183..41db75a 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -267,6 +267,10 @@
 #define AC97_FMTS	\
 	SNDRV_PCM_FMTBIT_S16_LE
 
+static struct snd_soc_dai_ops hac_dai_ops = {
+	.hw_params	= hac_hw_params,
+};
+
 struct snd_soc_dai sh4_hac_dai[] = {
 {
 	.name			= "HAC0",
@@ -284,9 +288,7 @@
 		.channels_min	= 2,
 		.channels_max	= 2,
 	},
-	.ops = {
-		.hw_params	= hac_hw_params,
-	},
+	.ops = &hac_dai_ops,
 },
 #ifdef CONFIG_CPU_SUBTYPE_SH7760
 {
@@ -305,9 +307,7 @@
 		.channels_min	= 2,
 		.channels_max	= 2,
 	},
-	.ops = {
-		.hw_params	= hac_hw_params,
-	},
+	.ops = &hac_dai_ops,
 
 },
 #endif
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index d1e5390..56fa087 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -336,6 +336,16 @@
 	 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE |	\
 	 SNDRV_PCM_FMTBIT_S32_LE  | SNDRV_PCM_FMTBIT_U32_LE)
 
+static struct snd_soc_dai_ops ssi_dai_ops = {
+	.startup	= ssi_startup,
+	.shutdown	= ssi_shutdown,
+	.trigger	= ssi_trigger,
+	.hw_params	= ssi_hw_params,
+	.set_sysclk	= ssi_set_sysclk,
+	.set_clkdiv	= ssi_set_clkdiv,
+	.set_fmt	= ssi_set_fmt,
+};
+
 struct snd_soc_dai sh4_ssi_dai[] = {
 {
 	.name			= "SSI0",
@@ -352,15 +362,7 @@
 		.channels_min	= 2,
 		.channels_max	= 8,
 	},
-	.ops = {
-		.startup	= ssi_startup,
-		.shutdown	= ssi_shutdown,
-		.trigger	= ssi_trigger,
-		.hw_params	= ssi_hw_params,
-		.set_sysclk	= ssi_set_sysclk,
-		.set_clkdiv	= ssi_set_clkdiv,
-		.set_fmt	= ssi_set_fmt,
-	},
+	.ops = &ssi_dai_ops,
 },
 #ifdef CONFIG_CPU_SUBTYPE_SH7760
 {
@@ -378,15 +380,7 @@
 		.channels_min	= 2,
 		.channels_max	= 8,
 	},
-	.ops = {
-		.startup	= ssi_startup,
-		.shutdown	= ssi_shutdown,
-		.trigger	= ssi_trigger,
-		.hw_params	= ssi_hw_params,
-		.set_sysclk	= ssi_set_sysclk,
-		.set_clkdiv	= ssi_set_clkdiv,
-		.set_fmt	= ssi_set_fmt,
-	},
+	.ops = &ssi_dai_ops,
 },
 #endif
 };
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ec3f8bb..6e710f7 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -133,8 +133,8 @@
 	mutex_lock(&pcm_mutex);
 
 	/* startup the audio subsystem */
-	if (cpu_dai->ops.startup) {
-		ret = cpu_dai->ops.startup(substream, cpu_dai);
+	if (cpu_dai->ops->startup) {
+		ret = cpu_dai->ops->startup(substream, cpu_dai);
 		if (ret < 0) {
 			printk(KERN_ERR "asoc: can't open interface %s\n",
 				cpu_dai->name);
@@ -150,8 +150,8 @@
 		}
 	}
 
-	if (codec_dai->ops.startup) {
-		ret = codec_dai->ops.startup(substream, codec_dai);
+	if (codec_dai->ops->startup) {
+		ret = codec_dai->ops->startup(substream, codec_dai);
 		if (ret < 0) {
 			printk(KERN_ERR "asoc: can't open codec %s\n",
 				codec_dai->name);
@@ -234,7 +234,7 @@
 		cpu_dai->capture.active = codec_dai->capture.active = 1;
 	cpu_dai->active = codec_dai->active = 1;
 	cpu_dai->runtime = runtime;
-	socdev->codec->active++;
+	card->codec->active++;
 	mutex_unlock(&pcm_mutex);
 	return 0;
 
@@ -247,8 +247,8 @@
 		platform->pcm_ops->close(substream);
 
 platform_err:
-	if (cpu_dai->ops.shutdown)
-		cpu_dai->ops.shutdown(substream, cpu_dai);
+	if (cpu_dai->ops->shutdown)
+		cpu_dai->ops->shutdown(substream, cpu_dai);
 out:
 	mutex_unlock(&pcm_mutex);
 	return ret;
@@ -264,7 +264,7 @@
 	struct snd_soc_card *card = container_of(work, struct snd_soc_card,
 						 delayed_work.work);
 	struct snd_soc_device *socdev = card->socdev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = card->codec;
 	struct snd_soc_dai *codec_dai;
 	int i;
 
@@ -319,7 +319,7 @@
 	struct snd_soc_platform *platform = card->platform;
 	struct snd_soc_dai *cpu_dai = machine->cpu_dai;
 	struct snd_soc_dai *codec_dai = machine->codec_dai;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = card->codec;
 
 	mutex_lock(&pcm_mutex);
 
@@ -340,11 +340,11 @@
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		snd_soc_dai_digital_mute(codec_dai, 1);
 
-	if (cpu_dai->ops.shutdown)
-		cpu_dai->ops.shutdown(substream, cpu_dai);
+	if (cpu_dai->ops->shutdown)
+		cpu_dai->ops->shutdown(substream, cpu_dai);
 
-	if (codec_dai->ops.shutdown)
-		codec_dai->ops.shutdown(substream, codec_dai);
+	if (codec_dai->ops->shutdown)
+		codec_dai->ops->shutdown(substream, codec_dai);
 
 	if (machine->ops && machine->ops->shutdown)
 		machine->ops->shutdown(substream);
@@ -387,7 +387,7 @@
 	struct snd_soc_platform *platform = card->platform;
 	struct snd_soc_dai *cpu_dai = machine->cpu_dai;
 	struct snd_soc_dai *codec_dai = machine->codec_dai;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = card->codec;
 	int ret = 0;
 
 	mutex_lock(&pcm_mutex);
@@ -408,16 +408,16 @@
 		}
 	}
 
-	if (codec_dai->ops.prepare) {
-		ret = codec_dai->ops.prepare(substream, codec_dai);
+	if (codec_dai->ops->prepare) {
+		ret = codec_dai->ops->prepare(substream, codec_dai);
 		if (ret < 0) {
 			printk(KERN_ERR "asoc: codec DAI prepare error\n");
 			goto out;
 		}
 	}
 
-	if (cpu_dai->ops.prepare) {
-		ret = cpu_dai->ops.prepare(substream, cpu_dai);
+	if (cpu_dai->ops->prepare) {
+		ret = cpu_dai->ops->prepare(substream, cpu_dai);
 		if (ret < 0) {
 			printk(KERN_ERR "asoc: cpu DAI prepare error\n");
 			goto out;
@@ -494,8 +494,8 @@
 		}
 	}
 
-	if (codec_dai->ops.hw_params) {
-		ret = codec_dai->ops.hw_params(substream, params, codec_dai);
+	if (codec_dai->ops->hw_params) {
+		ret = codec_dai->ops->hw_params(substream, params, codec_dai);
 		if (ret < 0) {
 			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
 				codec_dai->name);
@@ -503,8 +503,8 @@
 		}
 	}
 
-	if (cpu_dai->ops.hw_params) {
-		ret = cpu_dai->ops.hw_params(substream, params, cpu_dai);
+	if (cpu_dai->ops->hw_params) {
+		ret = cpu_dai->ops->hw_params(substream, params, cpu_dai);
 		if (ret < 0) {
 			printk(KERN_ERR "asoc: interface %s hw params failed\n",
 				cpu_dai->name);
@@ -526,12 +526,12 @@
 	return ret;
 
 platform_err:
-	if (cpu_dai->ops.hw_free)
-		cpu_dai->ops.hw_free(substream, cpu_dai);
+	if (cpu_dai->ops->hw_free)
+		cpu_dai->ops->hw_free(substream, cpu_dai);
 
 interface_err:
-	if (codec_dai->ops.hw_free)
-		codec_dai->ops.hw_free(substream, codec_dai);
+	if (codec_dai->ops->hw_free)
+		codec_dai->ops->hw_free(substream, codec_dai);
 
 codec_err:
 	if (machine->ops && machine->ops->hw_free)
@@ -553,7 +553,7 @@
 	struct snd_soc_platform *platform = card->platform;
 	struct snd_soc_dai *cpu_dai = machine->cpu_dai;
 	struct snd_soc_dai *codec_dai = machine->codec_dai;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = card->codec;
 
 	mutex_lock(&pcm_mutex);
 
@@ -570,11 +570,11 @@
 		platform->pcm_ops->hw_free(substream);
 
 	/* now free hw params for the DAI's  */
-	if (codec_dai->ops.hw_free)
-		codec_dai->ops.hw_free(substream, codec_dai);
+	if (codec_dai->ops->hw_free)
+		codec_dai->ops->hw_free(substream, codec_dai);
 
-	if (cpu_dai->ops.hw_free)
-		cpu_dai->ops.hw_free(substream, cpu_dai);
+	if (cpu_dai->ops->hw_free)
+		cpu_dai->ops->hw_free(substream, cpu_dai);
 
 	mutex_unlock(&pcm_mutex);
 	return 0;
@@ -591,8 +591,8 @@
 	struct snd_soc_dai *codec_dai = machine->codec_dai;
 	int ret;
 
-	if (codec_dai->ops.trigger) {
-		ret = codec_dai->ops.trigger(substream, cmd, codec_dai);
+	if (codec_dai->ops->trigger) {
+		ret = codec_dai->ops->trigger(substream, cmd, codec_dai);
 		if (ret < 0)
 			return ret;
 	}
@@ -603,8 +603,8 @@
 			return ret;
 	}
 
-	if (cpu_dai->ops.trigger) {
-		ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai);
+	if (cpu_dai->ops->trigger) {
+		ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai);
 		if (ret < 0)
 			return ret;
 	}
@@ -629,7 +629,7 @@
 	struct snd_soc_card *card = socdev->card;
 	struct snd_soc_platform *platform = card->platform;
 	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = card->codec;
 	int i;
 
 	/* Due to the resume being scheduled into a workqueue we could
@@ -645,8 +645,8 @@
 	/* mute any active DAC's */
 	for (i = 0; i < card->num_links; i++) {
 		struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
-		if (dai->ops.digital_mute && dai->playback.active)
-			dai->ops.digital_mute(dai, 1);
+		if (dai->ops->digital_mute && dai->playback.active)
+			dai->ops->digital_mute(dai, 1);
 	}
 
 	/* suspend all pcms */
@@ -705,7 +705,7 @@
 	struct snd_soc_device *socdev = card->socdev;
 	struct snd_soc_platform *platform = card->platform;
 	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = card->codec;
 	struct platform_device *pdev = to_platform_device(socdev->dev);
 	int i;
 
@@ -741,8 +741,8 @@
 	/* unmute any active DACs */
 	for (i = 0; i < card->num_links; i++) {
 		struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
-		if (dai->ops.digital_mute && dai->playback.active)
-			dai->ops.digital_mute(dai, 0);
+		if (dai->ops->digital_mute && dai->playback.active)
+			dai->ops->digital_mute(dai, 0);
 	}
 
 	for (i = 0; i < card->num_links; i++) {
@@ -982,8 +982,8 @@
 static int soc_new_pcm(struct snd_soc_device *socdev,
 	struct snd_soc_dai_link *dai_link, int num)
 {
-	struct snd_soc_codec *codec = socdev->codec;
 	struct snd_soc_card *card = socdev->card;
+	struct snd_soc_codec *codec = card->codec;
 	struct snd_soc_platform *platform = card->platform;
 	struct snd_soc_dai *codec_dai = dai_link->codec_dai;
 	struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
@@ -998,7 +998,7 @@
 
 	rtd->dai = dai_link;
 	rtd->socdev = socdev;
-	codec_dai->codec = socdev->codec;
+	codec_dai->codec = card->codec;
 
 	/* check client and interface hw capabilities */
 	sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name,
@@ -1048,9 +1048,8 @@
 }
 
 /* codec register dump */
-static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf)
+static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
 {
-	struct snd_soc_codec *codec = devdata->codec;
 	int i, step = 1, count = 0;
 
 	if (!codec->reg_cache_size)
@@ -1090,7 +1089,7 @@
 	struct device_attribute *attr, char *buf)
 {
 	struct snd_soc_device *devdata = dev_get_drvdata(dev);
-	return soc_codec_reg_show(devdata, buf);
+	return soc_codec_reg_show(devdata->card->codec, buf);
 }
 
 static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
@@ -1107,12 +1106,10 @@
 {
 	ssize_t ret;
 	struct snd_soc_codec *codec = file->private_data;
-	struct device *card_dev = codec->card->dev;
-	struct snd_soc_device *devdata = card_dev->driver_data;
 	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
-	ret = soc_codec_reg_show(devdata, buf);
+	ret = soc_codec_reg_show(codec, buf);
 	if (ret >= 0)
 		ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
 	kfree(buf);
@@ -1309,19 +1306,19 @@
  */
 int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
 {
-	struct snd_soc_codec *codec = socdev->codec;
 	struct snd_soc_card *card = socdev->card;
-	int ret = 0, i;
+	struct snd_soc_codec *codec = card->codec;
+	int ret, i;
 
 	mutex_lock(&codec->mutex);
 
 	/* register a sound card */
-	codec->card = snd_card_new(idx, xid, codec->owner, 0);
-	if (!codec->card) {
+	ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card);
+	if (ret < 0) {
 		printk(KERN_ERR "asoc: can't create sound card for codec %s\n",
 			codec->name);
 		mutex_unlock(&codec->mutex);
-		return -ENODEV;
+		return ret;
 	}
 
 	codec->card->dev = socdev->dev;
@@ -1355,8 +1352,8 @@
  */
 int snd_soc_init_card(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
 	struct snd_soc_card *card = socdev->card;
+	struct snd_soc_codec *codec = card->codec;
 	int ret = 0, i, ac97 = 0, err = 0;
 
 	for (i = 0; i < card->num_links; i++) {
@@ -1407,7 +1404,7 @@
 	if (err < 0)
 		printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
 
-	soc_init_codec_debugfs(socdev->codec);
+	soc_init_codec_debugfs(codec);
 	mutex_unlock(&codec->mutex);
 
 out:
@@ -1424,18 +1421,19 @@
  */
 void snd_soc_free_pcms(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 #ifdef CONFIG_SND_SOC_AC97_BUS
 	struct snd_soc_dai *codec_dai;
 	int i;
 #endif
 
 	mutex_lock(&codec->mutex);
-	soc_cleanup_codec_debugfs(socdev->codec);
+	soc_cleanup_codec_debugfs(codec);
 #ifdef CONFIG_SND_SOC_AC97_BUS
 	for (i = 0; i < codec->num_dai; i++) {
 		codec_dai = &codec->dai[i];
-		if (codec_dai->ac97_control && codec->ac97) {
+		if (codec_dai->ac97_control && codec->ac97 &&
+		    strcmp(codec->name, "AC97") != 0) {
 			soc_ac97_dev_unregister(codec);
 			goto free_card;
 		}
@@ -1498,6 +1496,37 @@
 EXPORT_SYMBOL_GPL(snd_soc_cnew);
 
 /**
+ * snd_soc_add_controls - add an array of controls to a codec.
+ * Convienience function to add a list of controls. Many codecs were
+ * duplicating this code.
+ *
+ * @codec: codec to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_controls(struct snd_soc_codec *codec,
+	const struct snd_kcontrol_new *controls, int num_controls)
+{
+	struct snd_card *card = codec->card;
+	int err, i;
+
+	for (i = 0; i < num_controls; i++) {
+		const struct snd_kcontrol_new *control = &controls[i];
+		err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL));
+		if (err < 0) {
+			dev_err(codec->dev, "%s: Failed to add %s\n",
+				codec->name, control->name);
+			return err;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_controls);
+
+/**
  * snd_soc_info_enum_double - enumerated double mixer info callback
  * @kcontrol: mixer control
  * @uinfo: control element information
@@ -2023,8 +2052,8 @@
 int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 	unsigned int freq, int dir)
 {
-	if (dai->ops.set_sysclk)
-		return dai->ops.set_sysclk(dai, clk_id, freq, dir);
+	if (dai->ops->set_sysclk)
+		return dai->ops->set_sysclk(dai, clk_id, freq, dir);
 	else
 		return -EINVAL;
 }
@@ -2043,8 +2072,8 @@
 int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
 	int div_id, int div)
 {
-	if (dai->ops.set_clkdiv)
-		return dai->ops.set_clkdiv(dai, div_id, div);
+	if (dai->ops->set_clkdiv)
+		return dai->ops->set_clkdiv(dai, div_id, div);
 	else
 		return -EINVAL;
 }
@@ -2062,8 +2091,8 @@
 int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
 	int pll_id, unsigned int freq_in, unsigned int freq_out)
 {
-	if (dai->ops.set_pll)
-		return dai->ops.set_pll(dai, pll_id, freq_in, freq_out);
+	if (dai->ops->set_pll)
+		return dai->ops->set_pll(dai, pll_id, freq_in, freq_out);
 	else
 		return -EINVAL;
 }
@@ -2078,8 +2107,8 @@
  */
 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-	if (dai->ops.set_fmt)
-		return dai->ops.set_fmt(dai, fmt);
+	if (dai->ops->set_fmt)
+		return dai->ops->set_fmt(dai, fmt);
 	else
 		return -EINVAL;
 }
@@ -2097,8 +2126,8 @@
 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
 	unsigned int mask, int slots)
 {
-	if (dai->ops.set_sysclk)
-		return dai->ops.set_tdm_slot(dai, mask, slots);
+	if (dai->ops->set_sysclk)
+		return dai->ops->set_tdm_slot(dai, mask, slots);
 	else
 		return -EINVAL;
 }
@@ -2113,8 +2142,8 @@
  */
 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
 {
-	if (dai->ops.set_sysclk)
-		return dai->ops.set_tristate(dai, tristate);
+	if (dai->ops->set_sysclk)
+		return dai->ops->set_tristate(dai, tristate);
 	else
 		return -EINVAL;
 }
@@ -2129,8 +2158,8 @@
  */
 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
 {
-	if (dai->ops.digital_mute)
-		return dai->ops.digital_mute(dai, mute);
+	if (dai->ops->digital_mute)
+		return dai->ops->digital_mute(dai, mute);
 	else
 		return -EINVAL;
 }
@@ -2183,6 +2212,9 @@
 	return 0;
 }
 
+static struct snd_soc_dai_ops null_dai_ops = {
+};
+
 /**
  * snd_soc_register_dai - Register a DAI with the ASoC core
  *
@@ -2197,6 +2229,9 @@
 	if (!dai->dev)
 		printk(KERN_WARNING "No device for DAI %s\n", dai->name);
 
+	if (!dai->ops)
+		dai->ops = &null_dai_ops;
+
 	INIT_LIST_HEAD(&dai->list);
 
 	mutex_lock(&client_mutex);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index a2f1da8..735903a 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -54,14 +54,15 @@
 static int dapm_up_seq[] = {
 	snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
 	snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac,
-	snd_soc_dapm_mixer, snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp,
-	snd_soc_dapm_spk, snd_soc_dapm_post
+	snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga,
+	snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
 };
+
 static int dapm_down_seq[] = {
 	snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
-	snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic,
-	snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
-	snd_soc_dapm_post
+	snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer,
+	snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias,
+	snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post
 };
 
 static int dapm_status = 1;
@@ -101,7 +102,8 @@
 {
 	switch (w->id) {
 	case snd_soc_dapm_switch:
-	case snd_soc_dapm_mixer: {
+	case snd_soc_dapm_mixer:
+	case snd_soc_dapm_mixer_named_ctl: {
 		int val;
 		struct soc_mixer_control *mc = (struct soc_mixer_control *)
 			w->kcontrols[i].private_value;
@@ -323,15 +325,32 @@
 			if (path->name != (char*)w->kcontrols[i].name)
 				continue;
 
-			/* add dapm control with long name */
-			name_len = 2 + strlen(w->name)
-				+ strlen(w->kcontrols[i].name);
+			/* add dapm control with long name.
+			 * for dapm_mixer this is the concatenation of the
+			 * mixer and kcontrol name.
+			 * for dapm_mixer_named_ctl this is simply the
+			 * kcontrol name.
+			 */
+			name_len = strlen(w->kcontrols[i].name) + 1;
+			if (w->id != snd_soc_dapm_mixer_named_ctl)
+				name_len += 1 + strlen(w->name);
+
 			path->long_name = kmalloc(name_len, GFP_KERNEL);
+
 			if (path->long_name == NULL)
 				return -ENOMEM;
 
-			snprintf(path->long_name, name_len, "%s %s",
-				 w->name, w->kcontrols[i].name);
+			switch (w->id) {
+			default:
+				snprintf(path->long_name, name_len, "%s %s",
+					 w->name, w->kcontrols[i].name);
+				break;
+			case snd_soc_dapm_mixer_named_ctl:
+				snprintf(path->long_name, name_len, "%s",
+					 w->kcontrols[i].name);
+				break;
+			}
+
 			path->long_name[name_len - 1] = '\0';
 
 			path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
@@ -503,6 +522,137 @@
 EXPORT_SYMBOL_GPL(dapm_reg_event);
 
 /*
+ * Scan a single DAPM widget for a complete audio path and update the
+ * power status appropriately.
+ */
+static int dapm_power_widget(struct snd_soc_codec *codec, int event,
+			     struct snd_soc_dapm_widget *w)
+{
+	int in, out, power_change, power, ret;
+
+	/* vmid - no action */
+	if (w->id == snd_soc_dapm_vmid)
+		return 0;
+
+	/* active ADC */
+	if (w->id == snd_soc_dapm_adc && w->active) {
+		in = is_connected_input_ep(w);
+		dapm_clear_walk(w->codec);
+		w->power = (in != 0) ? 1 : 0;
+		dapm_update_bits(w);
+		return 0;
+	}
+
+	/* active DAC */
+	if (w->id == snd_soc_dapm_dac && w->active) {
+		out = is_connected_output_ep(w);
+		dapm_clear_walk(w->codec);
+		w->power = (out != 0) ? 1 : 0;
+		dapm_update_bits(w);
+		return 0;
+	}
+
+	/* pre and post event widgets */
+	if (w->id == snd_soc_dapm_pre) {
+		if (!w->event)
+			return 0;
+
+		if (event == SND_SOC_DAPM_STREAM_START) {
+			ret = w->event(w,
+				       NULL, SND_SOC_DAPM_PRE_PMU);
+			if (ret < 0)
+				return ret;
+		} else if (event == SND_SOC_DAPM_STREAM_STOP) {
+			ret = w->event(w,
+				       NULL, SND_SOC_DAPM_PRE_PMD);
+			if (ret < 0)
+				return ret;
+		}
+		return 0;
+	}
+	if (w->id == snd_soc_dapm_post) {
+		if (!w->event)
+			return 0;
+
+		if (event == SND_SOC_DAPM_STREAM_START) {
+			ret = w->event(w,
+				       NULL, SND_SOC_DAPM_POST_PMU);
+			if (ret < 0)
+				return ret;
+		} else if (event == SND_SOC_DAPM_STREAM_STOP) {
+			ret = w->event(w,
+				       NULL, SND_SOC_DAPM_POST_PMD);
+			if (ret < 0)
+				return ret;
+		}
+		return 0;
+	}
+
+	/* all other widgets */
+	in = is_connected_input_ep(w);
+	dapm_clear_walk(w->codec);
+	out = is_connected_output_ep(w);
+	dapm_clear_walk(w->codec);
+	power = (out != 0 && in != 0) ? 1 : 0;
+	power_change = (w->power == power) ? 0 : 1;
+	w->power = power;
+
+	if (!power_change)
+		return 0;
+
+	/* call any power change event handlers */
+	if (w->event)
+		pr_debug("power %s event for %s flags %x\n",
+			 w->power ? "on" : "off",
+			 w->name, w->event_flags);
+
+	/* power up pre event */
+	if (power && w->event &&
+	    (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
+		ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* power down pre event */
+	if (!power && w->event &&
+	    (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
+		ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Lower PGA volume to reduce pops */
+	if (w->id == snd_soc_dapm_pga && !power)
+		dapm_set_pga(w, power);
+
+	dapm_update_bits(w);
+
+	/* Raise PGA volume to reduce pops */
+	if (w->id == snd_soc_dapm_pga && power)
+		dapm_set_pga(w, power);
+
+	/* power up post event */
+	if (power && w->event &&
+	    (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
+		ret = w->event(w,
+			       NULL, SND_SOC_DAPM_POST_PMU);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* power down post event */
+	if (!power && w->event &&
+	    (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
+		ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+/*
  * Scan each dapm widget for complete audio path.
  * A complete path is a route that has valid endpoints i.e.:-
  *
@@ -514,7 +664,7 @@
 static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
 {
 	struct snd_soc_dapm_widget *w;
-	int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power;
+	int i, c = 1, *seq = NULL, ret = 0;
 
 	/* do we have a sequenced stream event */
 	if (event == SND_SOC_DAPM_STREAM_START) {
@@ -525,135 +675,20 @@
 		seq = dapm_down_seq;
 	}
 
-	for(i = 0; i < c; i++) {
+	for (i = 0; i < c; i++) {
 		list_for_each_entry(w, &codec->dapm_widgets, list) {
 
 			/* is widget in stream order */
 			if (seq && seq[i] && w->id != seq[i])
 				continue;
 
-			/* vmid - no action */
-			if (w->id == snd_soc_dapm_vmid)
-				continue;
-
-			/* active ADC */
-			if (w->id == snd_soc_dapm_adc && w->active) {
-				in = is_connected_input_ep(w);
-				dapm_clear_walk(w->codec);
-				w->power = (in != 0) ? 1 : 0;
-				dapm_update_bits(w);
-				continue;
-			}
-
-			/* active DAC */
-			if (w->id == snd_soc_dapm_dac && w->active) {
-				out = is_connected_output_ep(w);
-				dapm_clear_walk(w->codec);
-				w->power = (out != 0) ? 1 : 0;
-				dapm_update_bits(w);
-				continue;
-			}
-
-			/* pre and post event widgets */
-			if (w->id == snd_soc_dapm_pre) {
-				if (!w->event)
-					continue;
-
-				if (event == SND_SOC_DAPM_STREAM_START) {
-					ret = w->event(w,
-						NULL, SND_SOC_DAPM_PRE_PMU);
-					if (ret < 0)
-						return ret;
-				} else if (event == SND_SOC_DAPM_STREAM_STOP) {
-					ret = w->event(w,
-						NULL, SND_SOC_DAPM_PRE_PMD);
-					if (ret < 0)
-						return ret;
-				}
-				continue;
-			}
-			if (w->id == snd_soc_dapm_post) {
-				if (!w->event)
-					continue;
-
-				if (event == SND_SOC_DAPM_STREAM_START) {
-					ret = w->event(w,
-						NULL, SND_SOC_DAPM_POST_PMU);
-					if (ret < 0)
-						return ret;
-				} else if (event == SND_SOC_DAPM_STREAM_STOP) {
-					ret = w->event(w,
-						NULL, SND_SOC_DAPM_POST_PMD);
-					if (ret < 0)
-						return ret;
-				}
-				continue;
-			}
-
-			/* all other widgets */
-			in = is_connected_input_ep(w);
-			dapm_clear_walk(w->codec);
-			out = is_connected_output_ep(w);
-			dapm_clear_walk(w->codec);
-			power = (out != 0 && in != 0) ? 1 : 0;
-			power_change = (w->power == power) ? 0: 1;
-			w->power = power;
-
-			if (!power_change)
-				continue;
-
-			/* call any power change event handlers */
-			if (w->event)
-				pr_debug("power %s event for %s flags %x\n",
-					 w->power ? "on" : "off",
-					 w->name, w->event_flags);
-
-			/* power up pre event */
-			if (power && w->event &&
-			    (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
-				ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
-				if (ret < 0)
-					return ret;
-			}
-
-			/* power down pre event */
-			if (!power && w->event &&
-			    (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
-				ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
-				if (ret < 0)
-					return ret;
-			}
-
-			/* Lower PGA volume to reduce pops */
-			if (w->id == snd_soc_dapm_pga && !power)
-				dapm_set_pga(w, power);
-
-			dapm_update_bits(w);
-
-			/* Raise PGA volume to reduce pops */
-			if (w->id == snd_soc_dapm_pga && power)
-				dapm_set_pga(w, power);
-
-			/* power up post event */
-			if (power && w->event &&
-			    (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
-				ret = w->event(w,
-					       NULL, SND_SOC_DAPM_POST_PMU);
-				if (ret < 0)
-					return ret;
-			}
-
-			/* power down post event */
-			if (!power && w->event &&
-			    (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
-				ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
-				if (ret < 0)
-					return ret;
-			}
+			ret = dapm_power_widget(codec, event, w);
+			if (ret != 0)
+				return ret;
 		}
 	}
 
-	return ret;
+	return 0;
 }
 
 #ifdef DEBUG
@@ -687,6 +722,7 @@
 		case snd_soc_dapm_adc:
 		case snd_soc_dapm_pga:
 		case snd_soc_dapm_mixer:
+		case snd_soc_dapm_mixer_named_ctl:
 			if (w->name) {
 				in = is_connected_input_ep(w);
 				dapm_clear_walk(w->codec);
@@ -760,6 +796,7 @@
 	int found = 0;
 
 	if (widget->id != snd_soc_dapm_mixer &&
+	    widget->id != snd_soc_dapm_mixer_named_ctl &&
 	    widget->id != snd_soc_dapm_switch)
 		return -ENODEV;
 
@@ -795,7 +832,7 @@
 	struct device_attribute *attr, char *buf)
 {
 	struct snd_soc_device *devdata = dev_get_drvdata(dev);
-	struct snd_soc_codec *codec = devdata->codec;
+	struct snd_soc_codec *codec = devdata->card->codec;
 	struct snd_soc_dapm_widget *w;
 	int count = 0;
 	char *state = "not set";
@@ -813,6 +850,7 @@
 		case snd_soc_dapm_adc:
 		case snd_soc_dapm_pga:
 		case snd_soc_dapm_mixer:
+		case snd_soc_dapm_mixer_named_ctl:
 			if (w->name)
 				count += sprintf(buf + count, "%s: %s\n",
 					w->name, w->power ? "On":"Off");
@@ -876,7 +914,7 @@
 }
 
 static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
-	char *pin, int status)
+				const char *pin, int status)
 {
 	struct snd_soc_dapm_widget *w;
 
@@ -991,6 +1029,7 @@
 		break;
 	case snd_soc_dapm_switch:
 	case snd_soc_dapm_mixer:
+	case snd_soc_dapm_mixer_named_ctl:
 		ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
 		if (ret != 0)
 			goto err;
@@ -1068,6 +1107,7 @@
 		switch(w->id) {
 		case snd_soc_dapm_switch:
 		case snd_soc_dapm_mixer:
+		case snd_soc_dapm_mixer_named_ctl:
 			dapm_new_mixer(codec, w);
 			break;
 		case snd_soc_dapm_mux:
@@ -1396,6 +1436,76 @@
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
 
 /**
+ * snd_soc_dapm_info_pin_switch - Info for a pin switch
+ *
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a pin switch control.
+ */
+int snd_soc_dapm_info_pin_switch(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;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
+
+/**
+ * snd_soc_dapm_get_pin_switch - Get information for a pin switch
+ *
+ * @kcontrol: mixer control
+ * @ucontrol: Value
+ */
+int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	const char *pin = (const char *)kcontrol->private_value;
+
+	mutex_lock(&codec->mutex);
+
+	ucontrol->value.integer.value[0] =
+		snd_soc_dapm_get_pin_status(codec, pin);
+
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
+
+/**
+ * snd_soc_dapm_put_pin_switch - Set information for a pin switch
+ *
+ * @kcontrol: mixer control
+ * @ucontrol: Value
+ */
+int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	const char *pin = (const char *)kcontrol->private_value;
+
+	mutex_lock(&codec->mutex);
+
+	if (ucontrol->value.integer.value[0])
+		snd_soc_dapm_enable_pin(codec, pin);
+	else
+		snd_soc_dapm_disable_pin(codec, pin);
+
+	snd_soc_dapm_sync(codec);
+
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
+
+/**
  * snd_soc_dapm_new_control - create new dapm control
  * @codec: audio codec
  * @widget: widget template
@@ -1527,8 +1637,8 @@
 int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
 				enum snd_soc_bias_level level)
 {
-	struct snd_soc_codec *codec = socdev->codec;
 	struct snd_soc_card *card = socdev->card;
+	struct snd_soc_codec *codec = socdev->card->codec;
 	int ret = 0;
 
 	if (card->set_bias_level)
@@ -1549,7 +1659,7 @@
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
-int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin)
+int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin)
 {
 	return snd_soc_dapm_set_pin(codec, pin, 1);
 }
@@ -1564,7 +1674,7 @@
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
-int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
+int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin)
 {
 	return snd_soc_dapm_set_pin(codec, pin, 0);
 }
@@ -1584,7 +1694,7 @@
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
-int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin)
+int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin)
 {
 	return snd_soc_dapm_set_pin(codec, pin, 0);
 }
@@ -1599,7 +1709,7 @@
  *
  * Returns 1 for connected otherwise 0.
  */
-int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin)
+int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin)
 {
 	struct snd_soc_dapm_widget *w;
 
@@ -1620,7 +1730,7 @@
  */
 void snd_soc_dapm_free(struct snd_soc_device *socdev)
 {
-	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec *codec = socdev->card->codec;
 
 	snd_soc_dapm_sys_remove(socdev->dev);
 	dapm_free_widgets(codec);
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
new file mode 100644
index 0000000..28346fb
--- /dev/null
+++ b/sound/soc/soc-jack.c
@@ -0,0 +1,267 @@
+/*
+ * soc-jack.c  --  ALSA SoC jack handling
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+
+/**
+ * snd_soc_jack_new - Create a new jack
+ * @card:  ASoC card
+ * @id:    an identifying string for this jack
+ * @type:  a bitmask of enum snd_jack_type values that can be detected by
+ *         this jack
+ * @jack:  structure to use for the jack
+ *
+ * Creates a new jack object.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ * On success jack will be initialised.
+ */
+int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
+		     struct snd_soc_jack *jack)
+{
+	jack->card = card;
+	INIT_LIST_HEAD(&jack->pins);
+
+	return snd_jack_new(card->codec->card, id, type, &jack->jack);
+}
+EXPORT_SYMBOL_GPL(snd_soc_jack_new);
+
+/**
+ * snd_soc_jack_report - Report the current status for a jack
+ *
+ * @jack:   the jack
+ * @status: a bitmask of enum snd_jack_type values that are currently detected.
+ * @mask:   a bitmask of enum snd_jack_type values that being reported.
+ *
+ * If configured using snd_soc_jack_add_pins() then the associated
+ * DAPM pins will be enabled or disabled as appropriate and DAPM
+ * synchronised.
+ *
+ * Note: This function uses mutexes and should be called from a
+ * context which can sleep (such as a workqueue).
+ */
+void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
+{
+	struct snd_soc_codec *codec = jack->card->codec;
+	struct snd_soc_jack_pin *pin;
+	int enable;
+	int oldstatus;
+
+	if (!jack) {
+		WARN_ON_ONCE(!jack);
+		return;
+	}
+
+	mutex_lock(&codec->mutex);
+
+	oldstatus = jack->status;
+
+	jack->status &= ~mask;
+	jack->status |= status;
+
+	/* The DAPM sync is expensive enough to be worth skipping */
+	if (jack->status == oldstatus)
+		goto out;
+
+	list_for_each_entry(pin, &jack->pins, list) {
+		enable = pin->mask & status;
+
+		if (pin->invert)
+			enable = !enable;
+
+		if (enable)
+			snd_soc_dapm_enable_pin(codec, pin->pin);
+		else
+			snd_soc_dapm_disable_pin(codec, pin->pin);
+	}
+
+	snd_soc_dapm_sync(codec);
+
+	snd_jack_report(jack->jack, status);
+
+out:
+	mutex_unlock(&codec->mutex);
+}
+EXPORT_SYMBOL_GPL(snd_soc_jack_report);
+
+/**
+ * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack
+ *
+ * @jack:  ASoC jack
+ * @count: Number of pins
+ * @pins:  Array of pins
+ *
+ * After this function has been called the DAPM pins specified in the
+ * pins array will have their status updated to reflect the current
+ * state of the jack whenever the jack status is updated.
+ */
+int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
+			  struct snd_soc_jack_pin *pins)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		if (!pins[i].pin) {
+			printk(KERN_ERR "No name for pin %d\n", i);
+			return -EINVAL;
+		}
+		if (!pins[i].mask) {
+			printk(KERN_ERR "No mask for pin %d (%s)\n", i,
+			       pins[i].pin);
+			return -EINVAL;
+		}
+
+		INIT_LIST_HEAD(&pins[i].list);
+		list_add(&(pins[i].list), &jack->pins);
+	}
+
+	/* Update to reflect the last reported status; canned jack
+	 * implementations are likely to set their state before the
+	 * card has an opportunity to associate pins.
+	 */
+	snd_soc_jack_report(jack, 0, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins);
+
+#ifdef CONFIG_GPIOLIB
+/* gpio detect */
+static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
+{
+	struct snd_soc_jack *jack = gpio->jack;
+	int enable;
+	int report;
+
+	if (gpio->debounce_time > 0)
+		mdelay(gpio->debounce_time);
+
+	enable = gpio_get_value(gpio->gpio);
+	if (gpio->invert)
+		enable = !enable;
+
+	if (enable)
+		report = gpio->report;
+	else
+		report = 0;
+
+	snd_soc_jack_report(jack, report, gpio->report);
+}
+
+/* irq handler for gpio pin */
+static irqreturn_t gpio_handler(int irq, void *data)
+{
+	struct snd_soc_jack_gpio *gpio = data;
+
+	schedule_work(&gpio->work);
+
+	return IRQ_HANDLED;
+}
+
+/* gpio work */
+static void gpio_work(struct work_struct *work)
+{
+	struct snd_soc_jack_gpio *gpio;
+
+	gpio = container_of(work, struct snd_soc_jack_gpio, work);
+	snd_soc_jack_gpio_detect(gpio);
+}
+
+/**
+ * snd_soc_jack_add_gpios - Associate GPIO pins with an ASoC jack
+ *
+ * @jack:  ASoC jack
+ * @count: number of pins
+ * @gpios: array of gpio pins
+ *
+ * This function will request gpio, set data direction and request irq
+ * for each gpio in the array.
+ */
+int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
+			struct snd_soc_jack_gpio *gpios)
+{
+	int i, ret;
+
+	for (i = 0; i < count; i++) {
+		if (!gpio_is_valid(gpios[i].gpio)) {
+			printk(KERN_ERR "Invalid gpio %d\n",
+				gpios[i].gpio);
+			ret = -EINVAL;
+			goto undo;
+		}
+		if (!gpios[i].name) {
+			printk(KERN_ERR "No name for gpio %d\n",
+				gpios[i].gpio);
+			ret = -EINVAL;
+			goto undo;
+		}
+
+		ret = gpio_request(gpios[i].gpio, gpios[i].name);
+		if (ret)
+			goto undo;
+
+		ret = gpio_direction_input(gpios[i].gpio);
+		if (ret)
+			goto err;
+
+		ret = request_irq(gpio_to_irq(gpios[i].gpio),
+				gpio_handler,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				jack->card->dev->driver->name,
+				&gpios[i]);
+		if (ret)
+			goto err;
+
+		INIT_WORK(&gpios[i].work, gpio_work);
+		gpios[i].jack = jack;
+	}
+
+	return 0;
+
+err:
+	gpio_free(gpios[i].gpio);
+undo:
+	snd_soc_jack_free_gpios(jack, i, gpios);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpios);
+
+/**
+ * snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack
+ *
+ * @jack:  ASoC jack
+ * @count: number of pins
+ * @gpios: array of gpio pins
+ *
+ * Release gpio and irq resources for gpio pins associated with an ASoC jack.
+ */
+void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
+			struct snd_soc_jack_gpio *gpios)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]);
+		gpio_free(gpios[i].gpio);
+		gpios[i].jack = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(snd_soc_jack_free_gpios);
+#endif	/* CONFIG_GPIOLIB */
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index f87933e..574af56 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -954,7 +954,8 @@
 	amd->regs = of_ioremap(&op->resource[0], 0,
 			       resource_size(&op->resource[0]), "amd7930");
 	if (!amd->regs) {
-		snd_printk("amd7930-%d: Unable to map chip registers.\n", dev);
+		snd_printk(KERN_ERR
+			   "amd7930-%d: Unable to map chip registers.\n", dev);
 		return -EIO;
 	}
 
@@ -962,7 +963,7 @@
 
 	if (request_irq(irq, snd_amd7930_interrupt,
 			IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) {
-		snd_printk("amd7930-%d: Unable to grab IRQ %d\n",
+		snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n",
 			   dev, irq);
 		snd_amd7930_free(amd);
 		return -EBUSY;
@@ -1018,9 +1019,10 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev_num], id[dev_num], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev_num], id[dev_num], THIS_MODULE, 0,
+			      &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "AMD7930");
 	strcpy(card->shortname, "Sun AMD7930");
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 41c3875..7d93fa7 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -1563,6 +1563,7 @@
 {
 	struct snd_card *card;
 	struct snd_cs4231 *chip;
+	int err;
 
 	*rcard = NULL;
 
@@ -1574,10 +1575,10 @@
 		return -ENOENT;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_cs4231));
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_cs4231), &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "CS4231");
 	strcpy(card->shortname, "Sun CS4231");
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 23ed6f0..af95ff1 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -2612,10 +2612,10 @@
 		return -ENODEV;
 	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_dbri));
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_dbri), &card);
+	if (err < 0)
+		return err;
 
 	strcpy(card->driver, "DBRI");
 	strcpy(card->shortname, "Sun DBRI");
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index 09802e8..4c7b051 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -965,12 +965,11 @@
 		return PTR_ERR(board->dac_clk);
 	}
 
-	retval = -ENOMEM;
-
 	/* Allocate "card" using some unused identifiers. */
 	snprintf(id, sizeof id, "at73c213_%d", board->ssc_id);
-	card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct snd_at73c213));
-	if (!card)
+	retval = snd_card_create(-1, id, THIS_MODULE,
+				 sizeof(struct snd_at73c213), &card);
+	if (retval < 0)
 		goto out;
 
 	chip = card->private_data;
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c
index 0a53914..ff0b2a8 100644
--- a/sound/synth/emux/emux_hwdep.c
+++ b/sound/synth/emux/emux_hwdep.c
@@ -24,25 +24,6 @@
 #include <asm/uaccess.h>
 #include "emux_voice.h"
 
-/*
- * open the hwdep device
- */
-static int
-snd_emux_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
-
-/*
- * close the device
- */
-static int
-snd_emux_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
 
 #define TMP_CLIENT_ID	0x1001
 
@@ -146,8 +127,6 @@
 	emu->hwdep = hw;
 	strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME);
 	hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE;
-	hw->ops.open = snd_emux_hwdep_open;
-	hw->ops.release = snd_emux_hwdep_release;
 	hw->ops.ioctl = snd_emux_hwdep_ioctl;
 	hw->exclusive = 1;
 	hw->private_data = emu;
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c
index 5c47b6c..87e4220 100644
--- a/sound/synth/emux/emux_oss.c
+++ b/sound/synth/emux/emux_oss.c
@@ -132,7 +132,7 @@
 	p = snd_emux_create_port(emu, tmpname, 32,
 				 1, &callback);
 	if (p == NULL) {
-		snd_printk("can't create port\n");
+		snd_printk(KERN_ERR "can't create port\n");
 		snd_emux_dec_count(emu);
 		mutex_unlock(&emu->register_mutex);
 		return -ENOMEM;
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index 335aa2c..ca5f7ef 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -74,15 +74,15 @@
 	emu->client = snd_seq_create_kernel_client(card, index,
 						   "%s WaveTable", emu->name);
 	if (emu->client < 0) {
-		snd_printk("can't create client\n");
+		snd_printk(KERN_ERR "can't create client\n");
 		return -ENODEV;
 	}
 
 	if (emu->num_ports < 0) {
-		snd_printk("seqports must be greater than zero\n");
+		snd_printk(KERN_WARNING "seqports must be greater than zero\n");
 		emu->num_ports = 1;
 	} else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) {
-		snd_printk("too many ports."
+		snd_printk(KERN_WARNING "too many ports."
 			   "limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS);
 		emu->num_ports = SNDRV_EMUX_MAX_PORTS;
 	}
@@ -100,7 +100,7 @@
 		p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS,
 					 0, &pinfo);
 		if (p == NULL) {
-			snd_printk("can't create port\n");
+			snd_printk(KERN_ERR "can't create port\n");
 			return -ENOMEM;
 		}
 
@@ -147,12 +147,12 @@
 
 	/* Allocate structures for this channel */
 	if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) {
-		snd_printk("no memory\n");
+		snd_printk(KERN_ERR "no memory\n");
 		return NULL;
 	}
 	p->chset.channels = kcalloc(max_channels, sizeof(struct snd_midi_channel), GFP_KERNEL);
 	if (p->chset.channels == NULL) {
-		snd_printk("no memory\n");
+		snd_printk(KERN_ERR "no memory\n");
 		kfree(p);
 		return NULL;
 	}
@@ -376,12 +376,12 @@
 			goto __error;
 		}
 		emu->vmidi[i] = rmidi;
-		//snd_printk("virmidi %d ok\n", i);
+		/* snd_printk(KERN_DEBUG "virmidi %d ok\n", i); */
 	}
 	return 0;
 
 __error:
-	//snd_printk("error init..\n");
+	/* snd_printk(KERN_DEBUG "error init..\n"); */
 	snd_emux_delete_virmidi(emu);
 	return -ENOMEM;
 }
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index 2cc6f6f..3e921b3 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -956,7 +956,8 @@
 	if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF)
 		emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED;
 	else
-		snd_printk("invalid voice for lock %d (state = %x)\n",
+		snd_printk(KERN_WARNING
+			   "invalid voice for lock %d (state = %x)\n",
 			   voice, emu->voices[voice].state);
 	spin_unlock_irqrestore(&emu->voice_lock, flags);
 }
@@ -973,7 +974,8 @@
 	if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED)
 		emu->voices[voice].state = SNDRV_EMUX_ST_OFF;
 	else
-		snd_printk("invalid voice for unlock %d (state = %x)\n",
+		snd_printk(KERN_WARNING
+			   "invalid voice for unlock %d (state = %x)\n",
 			   voice, emu->voices[voice].state);
 	spin_unlock_irqrestore(&emu->voice_lock, flags);
 }
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 36d53bd..63c8f45 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -133,7 +133,7 @@
 	int  rc;
 
 	if (count < (long)sizeof(patch)) {
-		snd_printk("patch record too small %ld\n", count);
+		snd_printk(KERN_ERR "patch record too small %ld\n", count);
 		return -EINVAL;
 	}
 	if (copy_from_user(&patch, data, sizeof(patch)))
@@ -143,15 +143,16 @@
 	data += sizeof(patch);
 
 	if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) {
-		snd_printk("'The wrong kind of patch' %x\n", patch.key);
+		snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key);
 		return -EINVAL;
 	}
 	if (count < patch.len) {
-		snd_printk("Patch too short %ld, need %d\n", count, patch.len);
+		snd_printk(KERN_ERR "Patch too short %ld, need %d\n",
+			   count, patch.len);
 		return -EINVAL;
 	}
 	if (patch.len < 0) {
-		snd_printk("poor length %d\n", patch.len);
+		snd_printk(KERN_ERR "poor length %d\n", patch.len);
 		return -EINVAL;
 	}
 
@@ -195,7 +196,8 @@
 	case SNDRV_SFNT_REMOVE_INFO:
 		/* patch must be opened */
 		if (!sflist->currsf) {
-			snd_printk("soundfont: remove_info: patch not opened\n");
+			snd_printk(KERN_ERR "soundfont: remove_info: "
+				   "patch not opened\n");
 			rc = -EINVAL;
 		} else {
 			int bank, instr;
@@ -531,7 +533,7 @@
 		return -EINVAL;
 
 	if (count < (long)sizeof(hdr)) {
-		printk("Soundfont error: invalid patch zone length\n");
+		printk(KERN_ERR "Soundfont error: invalid patch zone length\n");
 		return -EINVAL;
 	}
 	if (copy_from_user((char*)&hdr, data, sizeof(hdr)))
@@ -541,12 +543,14 @@
 	count -= sizeof(hdr);
 
 	if (hdr.nvoices <= 0 || hdr.nvoices >= 100) {
-		printk("Soundfont error: Illegal voice number %d\n", hdr.nvoices);
+		printk(KERN_ERR "Soundfont error: Illegal voice number %d\n",
+		       hdr.nvoices);
 		return -EINVAL;
 	}
 
 	if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) {
-		printk("Soundfont Error: patch length(%ld) is smaller than nvoices(%d)\n",
+		printk(KERN_ERR "Soundfont Error: "
+		       "patch length(%ld) is smaller than nvoices(%d)\n",
 		       count, hdr.nvoices);
 		return -EINVAL;
 	}
@@ -952,7 +956,7 @@
 	int rc;
 
 	if (count < (long)sizeof(patch)) {
-		snd_printk("patch record too small %ld\n", count);
+		snd_printk(KERN_ERR "patch record too small %ld\n", count);
 		return -EINVAL;
 	}
 	if (copy_from_user(&patch, data, sizeof(patch)))
@@ -1034,7 +1038,8 @@
 	/* panning position; -128 - 127 => 0-127 */
 	zone->v.pan = (patch.panning + 128) / 2;
 #if 0
-	snd_printk("gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n",
+	snd_printk(KERN_DEBUG
+		   "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n",
 		   (int)patch.base_freq, zone->v.rate_offset,
 		   zone->v.root, zone->v.tune, zone->v.low, zone->v.high);
 #endif
@@ -1068,7 +1073,8 @@
 		zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release);
 		zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);
 #if 0
-		snd_printk("gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n",
+		snd_printk(KERN_DEBUG
+			   "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n",
 			   zone->v.parm.volatkhld,
 			   zone->v.parm.voldcysus,
 			   zone->v.parm.volrelease,
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 4f0eac9..523aec1 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -48,7 +48,10 @@
 	    * Native Instruments Kore Controller
 	    * Native Instruments Kore Controller 2
 	    * Native Instruments Audio Kontrol 1
+	    * Native Instruments Audio 4 DJ
 	    * Native Instruments Audio 8 DJ
+	    * Native Instruments Guitar Rig Session I/O
+	    * Native Instruments Guitar Rig mobile
 
 	   To compile this driver as a module, choose M here: the module
 	   will be called snd-usb-caiaq.
diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c
index b3a6033..08d51e0 100644
--- a/sound/usb/caiaq/caiaq-audio.c
+++ b/sound/usb/caiaq/caiaq-audio.c
@@ -114,6 +114,7 @@
 	dev->output_panic = 0;
 	dev->first_packet = 1;
 	dev->streaming = 1;
+	dev->warned = 0;
 
 	for (i = 0; i < N_URBS; i++) {
 		ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC);
@@ -376,6 +377,9 @@
 
 		for (stream = 0; stream < dev->n_streams; stream++, i++) {
 			sub = dev->sub_capture[stream];
+			if (dev->input_panic)
+				usb_buf[i] = 0;
+
 			if (sub) {
 				struct snd_pcm_runtime *rt = sub->runtime;
 				char *audio_buf = rt->dma_area;
@@ -397,6 +401,9 @@
 	if (!dev->streaming)
 		return;
 
+	if (iso->actual_length < dev->bpp)
+		return;
+
 	switch (dev->spec.data_alignment) {
 	case 0:
 		read_in_urb_mode0(dev, urb, iso);
@@ -406,10 +413,11 @@
 		break;
 	}
 
-	if (dev->input_panic || dev->output_panic) {
+	if ((dev->input_panic || dev->output_panic) && !dev->warned) {
 		debug("streaming error detected %s %s\n", 
 				dev->input_panic ? "(input)" : "",
 				dev->output_panic ? "(output)" : "");
+		dev->warned = 1;
 	}
 }
 
@@ -638,9 +646,10 @@
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO):
-		dev->samplerates |= SNDRV_PCM_RATE_88200;
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE):
 		dev->samplerates |= SNDRV_PCM_RATE_192000;
-		break;
+		/* fall thru */
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
 		dev->samplerates |= SNDRV_PCM_RATE_88200;
 		break;
diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c
index ccd763d..e92c2bb 100644
--- a/sound/usb/caiaq/caiaq-control.c
+++ b/sound/usb/caiaq/caiaq-control.c
@@ -39,12 +39,12 @@
 	struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
 	int pos = kcontrol->private_value;
 	int is_intval = pos & CNT_INTVAL;
+	unsigned int id = dev->chip.usb_id;
 
 	uinfo->count = 1;
 	pos &= ~CNT_INTVAL;
 
-	if (dev->chip.usb_id ==
-		USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)
+	if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)
 		&& (pos == 0)) {
 		/* current input mode of A8DJ */
 		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -53,6 +53,15 @@
 		return 0;
 	}
 
+	if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)
+		&& (pos == 0)) {
+		/* current input mode of A4DJ */
+		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+		uinfo->value.integer.min = 0;
+		uinfo->value.integer.max = 1;
+		return 0;
+	}
+
 	if (is_intval) {
 		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 		uinfo->value.integer.min = 0;
@@ -73,6 +82,14 @@
 	struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
 	int pos = kcontrol->private_value;
 
+	if (dev->chip.usb_id ==
+		USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) {
+		/* A4DJ has only one control */
+		/* do not expose hardware input mode 0 */
+		ucontrol->value.integer.value[0] = dev->control_state[0] - 1;
+		return 0;
+	}
+
 	if (pos & CNT_INTVAL)
 		ucontrol->value.integer.value[0]
 			= dev->control_state[pos & ~CNT_INTVAL];
@@ -90,10 +107,20 @@
 	struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
 	int pos = kcontrol->private_value;
 
+	if (dev->chip.usb_id ==
+		USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) {
+		/* A4DJ has only one control */
+		/* do not expose hardware input mode 0 */
+		dev->control_state[0] = ucontrol->value.integer.value[0] + 1;
+		snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO,
+				dev->control_state, sizeof(dev->control_state));
+		return 1;
+	}
+
 	if (pos & CNT_INTVAL) {
 		dev->control_state[pos & ~CNT_INTVAL]
 			= ucontrol->value.integer.value[0];
-		snd_usb_caiaq_send_command(dev, EP1_CMD_DIMM_LEDS,
+		snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO,
 				dev->control_state, sizeof(dev->control_state));
 	} else {
 		if (ucontrol->value.integer.value[0])
@@ -243,10 +270,13 @@
 	{ "GND lift for TC Vinyl mode", 	24 + 0 		},
 	{ "GND lift for TC CD/Line mode", 	24 + 1 		},
 	{ "GND lift for phono mode", 		24 + 2 		},
-	{ "GND lift for TC Vinyl mode", 	24 + 3 		},
 	{ "Software lock", 			40 		}
 };
 
+static struct caiaq_controller a4dj_controller[] = {
+	{ "Current input mode",	0 | CNT_INTVAL 	}
+};
+
 static int __devinit add_controls(struct caiaq_controller *c, int num,
 				  struct snd_usb_caiaqdev *dev)
 {
@@ -295,6 +325,10 @@
 		ret = add_controls(a8dj_controller,
 			ARRAY_SIZE(a8dj_controller), dev);
 		break;
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
+		ret = add_controls(a4dj_controller,
+			ARRAY_SIZE(a4dj_controller), dev);
+		break;
 	}
 
 	return ret;
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index 41c36b0..cf573a9 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -42,15 +42,17 @@
 #endif
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.10");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.13");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
 			 "{Native Instruments, RigKontrol3},"
 			 "{Native Instruments, Kore Controller},"
 			 "{Native Instruments, Kore Controller 2},"
 			 "{Native Instruments, Audio Kontrol 1},"
+			 "{Native Instruments, Audio 4 DJ},"
 			 "{Native Instruments, Audio 8 DJ},"
-			 "{Native Instruments, Session I/O}}");
+			 "{Native Instruments, Session I/O},"
+			 "{Native Instruments, GuitarRig mobile}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
 static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
@@ -116,6 +118,16 @@
 		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
 		.idProduct =    USB_PID_SESSIONIO
 	},
+	{
+		.match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =    USB_PID_GUITARRIGMOBILE
+	},
+	{
+		.match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =    USB_PID_AUDIO4DJ
+	},
 	{ /* terminator */ }
 };
 
@@ -239,6 +251,8 @@
 		
 	if (dev->audio_parm_answer != 1) 
 		debug("unable to set the device's audio params\n");
+	else
+		dev->bpp = bpp;
 
 	return dev->audio_parm_answer == 1 ? 0 : -EINVAL;
 }
@@ -300,6 +314,12 @@
 		}
 
 		break;
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
+		/* Audio 4 DJ - default input mode to phono */
+		dev->control_state[0] = 2;
+		snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO,
+			dev->control_state, 1);
+		break;
 	}
 	
 	if (dev->spec.num_analog_audio_out +
@@ -336,9 +356,10 @@
 		log("Unable to set up control system (ret=%d)\n", ret);
 }
 
-static struct snd_card* create_card(struct usb_device* usb_dev)
+static int create_card(struct usb_device* usb_dev, struct snd_card **cardp)
 {
 	int devnum;
+	int err;
 	struct snd_card *card;
 	struct snd_usb_caiaqdev *dev;
 
@@ -347,12 +368,12 @@
 			break;
 
 	if (devnum >= SNDRV_CARDS)
-		return NULL;
+		return -ENODEV;
 
-	card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, 
-					sizeof(struct snd_usb_caiaqdev));
-	if (!card)
-		return NULL;
+	err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, 
+			      sizeof(struct snd_usb_caiaqdev), &card);
+	if (err < 0)
+		return err;
 
 	dev = caiaqdev(card);
 	dev->chip.dev = usb_dev;
@@ -362,7 +383,8 @@
 	spin_lock_init(&dev->spinlock);
 	snd_card_set_dev(card, &usb_dev->dev);
 
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 static int __devinit init_card(struct snd_usb_caiaqdev *dev)
@@ -441,10 +463,10 @@
 	struct snd_card *card;
 	struct usb_device *device = interface_to_usbdev(intf);
 	
-	card = create_card(device);
+	ret = create_card(device, &card);
 	
-	if (!card)
-		return -ENOMEM;
+	if (ret < 0)
+		return ret;
 			
 	usb_set_intfdata(intf, card);
 	ret = init_card(caiaqdev(card));
diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h
index ab56e73..4cce1ad 100644
--- a/sound/usb/caiaq/caiaq-device.h
+++ b/sound/usb/caiaq/caiaq-device.h
@@ -10,8 +10,10 @@
 #define USB_PID_KORECONTROLLER	0x4711
 #define USB_PID_KORECONTROLLER2	0x4712
 #define USB_PID_AK1		0x0815
+#define USB_PID_AUDIO4DJ	0x0839
 #define USB_PID_AUDIO8DJ	0x1978
 #define USB_PID_SESSIONIO	0x1915
+#define USB_PID_GUITARRIGMOBILE	0x0d8d
 
 #define EP1_BUFSIZE 64
 #define CAIAQ_USB_STR_LEN 0xff
@@ -87,9 +89,9 @@
 	int audio_out_buf_pos[MAX_STREAMS];
 	int period_in_count[MAX_STREAMS];
 	int period_out_count[MAX_STREAMS];
-	int input_panic, output_panic;
+	int input_panic, output_panic, warned;
 	char *audio_in_buf, *audio_out_buf;
-	unsigned int samplerates;
+	unsigned int samplerates, bpp;
 
 	struct snd_pcm_substream *sub_playback[MAX_STREAMS];
 	struct snd_pcm_substream *sub_capture[MAX_STREAMS];
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 19e3745..c2db0f9 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -107,7 +107,7 @@
 #define MAX_PACKS_HS	(MAX_PACKS * 8)	/* in high speed mode */
 #define MAX_URBS	8
 #define SYNC_URBS	4	/* always four urbs for sync */
-#define MIN_PACKS_URB	1	/* minimum 1 packet per urb */
+#define MAX_QUEUE	24	/* try not to exceed this queue length, in ms */
 
 struct audioformat {
 	struct list_head list;
@@ -525,7 +525,7 @@
 /*
  * Prepare urb for streaming before playback starts or when paused.
  *
- * We don't have any data, so we send a frame of silence.
+ * We don't have any data, so we send silence.
  */
 static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
 				       struct snd_pcm_runtime *runtime,
@@ -537,13 +537,13 @@
 
 	offs = 0;
 	urb->dev = ctx->subs->dev;
-	urb->number_of_packets = subs->packs_per_ms;
-	for (i = 0; i < subs->packs_per_ms; ++i) {
+	for (i = 0; i < ctx->packets; ++i) {
 		counts = snd_usb_audio_next_packet_size(subs);
 		urb->iso_frame_desc[i].offset = offs * stride;
 		urb->iso_frame_desc[i].length = counts * stride;
 		offs += counts;
 	}
+	urb->number_of_packets = ctx->packets;
 	urb->transfer_buffer_length = offs * stride;
 	memset(urb->transfer_buffer,
 	       subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
@@ -1034,9 +1034,9 @@
 static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes,
 			       unsigned int rate, unsigned int frame_bits)
 {
-	unsigned int maxsize, n, i;
+	unsigned int maxsize, i;
 	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-	unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms;
+	unsigned int urb_packs, total_packs, packs_per_ms;
 
 	/* calculate the frequency in 16.16 format */
 	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -1070,8 +1070,7 @@
 	subs->packs_per_ms = packs_per_ms;
 
 	if (is_playback) {
-		urb_packs = nrpacks;
-		urb_packs = max(urb_packs, (unsigned int)MIN_PACKS_URB);
+		urb_packs = max(nrpacks, 1);
 		urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
 	} else
 		urb_packs = 1;
@@ -1079,7 +1078,7 @@
 
 	/* decide how many packets to be used */
 	if (is_playback) {
-		unsigned int minsize;
+		unsigned int minsize, maxpacks;
 		/* determine how small a packet can be */
 		minsize = (subs->freqn >> (16 - subs->datainterval))
 			  * (frame_bits >> 3);
@@ -1092,8 +1091,13 @@
 		total_packs = (total_packs + packs_per_ms - 1)
 				& ~(packs_per_ms - 1);
 		/* we need at least two URBs for queueing */
-		if (total_packs < 2 * MIN_PACKS_URB * packs_per_ms)
-			total_packs = 2 * MIN_PACKS_URB * packs_per_ms;
+		if (total_packs < 2 * packs_per_ms) {
+			total_packs = 2 * packs_per_ms;
+		} else {
+			/* and we don't want too long a queue either */
+			maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
+			total_packs = min(total_packs, maxpacks);
+		}
 	} else {
 		total_packs = MAX_URBS * urb_packs;
 	}
@@ -1102,31 +1106,11 @@
 		/* too much... */
 		subs->nurbs = MAX_URBS;
 		total_packs = MAX_URBS * urb_packs;
-	}
-	n = total_packs;
-	for (i = 0; i < subs->nurbs; i++) {
-		npacks[i] = n > urb_packs ? urb_packs : n;
-		n -= urb_packs;
-	}
-	if (subs->nurbs <= 1) {
+	} else if (subs->nurbs < 2) {
 		/* too little - we need at least two packets
 		 * to ensure contiguous playback/capture
 		 */
 		subs->nurbs = 2;
-		npacks[0] = (total_packs + 1) / 2;
-		npacks[1] = total_packs - npacks[0];
-	} else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) {
-		/* the last packet is too small.. */
-		if (subs->nurbs > 2) {
-			/* merge to the first one */
-			npacks[0] += npacks[subs->nurbs - 1];
-			subs->nurbs--;
-		} else {
-			/* divide to two */
-			subs->nurbs = 2;
-			npacks[0] = (total_packs + 1) / 2;
-			npacks[1] = total_packs - npacks[0];
-		}
 	}
 
 	/* allocate and initialize data urbs */
@@ -1134,7 +1118,8 @@
 		struct snd_urb_ctx *u = &subs->dataurb[i];
 		u->index = i;
 		u->subs = subs;
-		u->packets = npacks[i];
+		u->packets = (i + 1) * total_packs / subs->nurbs
+			- i * total_packs / subs->nurbs;
 		u->buffer_size = maxsize * u->packets;
 		if (subs->fmt_type == USB_FORMAT_TYPE_II)
 			u->packets++; /* for transfer delimiter */
@@ -1292,14 +1277,14 @@
 		if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
 					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
-			snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
+			snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
 				   dev->devnum, iface, fmt->altsetting, rate, ep);
 			return err;
 		}
 		if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
 					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
-			snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
+			snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
 				   dev->devnum, iface, fmt->altsetting, ep);
 			return 0; /* some devices don't support reading */
 		}
@@ -1431,9 +1416,11 @@
 	subs->cur_audiofmt = fmt;
 
 #if 0
-	printk("setting done: format = %d, rate = %d..%d, channels = %d\n",
+	printk(KERN_DEBUG
+	       "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",
+	printk(KERN_DEBUG
+	       "  datapipe = 0x%0x, syncpipe = 0x%0x\n",
 	       subs->datapipe, subs->syncpipe);
 #endif
 
@@ -1468,7 +1455,7 @@
 	channels = params_channels(hw_params);
 	fmt = find_format(subs, format, rate, channels);
 	if (!fmt) {
-		snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n",
+		snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n",
 			   format, rate, channels);
 		return -EINVAL;
 	}
@@ -1795,7 +1782,7 @@
 			if (rates[f->format] && rates[f->format] != f->rates)
 				goto __out;
 		}
-		channels[f->format] |= (1 << f->channels);
+		channels[f->format] |= 1 << (f->channels - 1);
 		rates[f->format] |= f->rates;
 		/* needs knot? */
 		if (f->rates & SNDRV_PCM_RATE_KNOT)
@@ -1822,7 +1809,7 @@
 			continue;
 		for (i = 0; i < 32; i++) {
 			if (f->rates & (1 << i))
-				channels[i] |= (1 << f->channels);
+				channels[i] |= 1 << (f->channels - 1);
 		}
 	}
 	cmaster = 0;
@@ -1919,7 +1906,7 @@
 	 * in the current code assume the 1ms period.
 	 */
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
-				     1000 * MIN_PACKS_URB,
+				     1000,
 				     /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
 
 	err = check_hw_params_convention(subs);
@@ -2160,7 +2147,7 @@
 		fp = list_entry(p, struct audioformat, list);
 		snd_iprintf(buffer, "  Interface %d\n", fp->iface);
 		snd_iprintf(buffer, "    Altset %d\n", fp->altsetting);
-		snd_iprintf(buffer, "    Format: 0x%x\n", fp->format);
+		snd_iprintf(buffer, "    Format: %#x\n", fp->format);
 		snd_iprintf(buffer, "    Channels: %d\n", fp->channels);
 		snd_iprintf(buffer, "    Endpoint: %d %s (%s)\n",
 			    fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
@@ -2180,7 +2167,7 @@
 			snd_iprintf(buffer, "\n");
 		}
 		// snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
-		// snd_iprintf(buffer, "    EP Attribute = 0x%x\n", fp->attributes);
+		// snd_iprintf(buffer, "    EP Attribute = %#x\n", fp->attributes);
 	}
 }
 
@@ -2621,7 +2608,7 @@
 		fp->format = SNDRV_PCM_FORMAT_MPEG;
 		break;
 	default:
-		snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected.  processed as MPEG.\n",
+		snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected.  processed as MPEG.\n",
 			   chip->dev->devnum, fp->iface, fp->altsetting, format);
 		fp->format = SNDRV_PCM_FORMAT_MPEG;
 		break;
@@ -2819,7 +2806,7 @@
 			continue;
 		}
 
-		snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, altno, fp->endpoint);
+		snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
 		err = add_audio_endpoint(chip, stream, fp);
 		if (err < 0) {
 			kfree(fp->rate_table);
@@ -3466,10 +3453,10 @@
 		return -ENXIO;
 	}
 
-	card = snd_card_new(index[idx], id[idx], THIS_MODULE, 0);
-	if (card == NULL) {
+	err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card);
+	if (err < 0) {
 		snd_printk(KERN_ERR "cannot create card instance %d\n", idx);
-		return -ENOMEM;
+		return err;
 	}
 
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
@@ -3766,7 +3753,7 @@
 
 static int __init snd_usb_audio_init(void)
 {
-	if (nrpacks < MIN_PACKS_URB || nrpacks > MAX_PACKS) {
+	if (nrpacks < 1 || nrpacks > MAX_PACKS) {
 		printk(KERN_WARNING "invalid nrpacks value.\n");
 		return -EINVAL;
 	}
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 00397c8..ecb58e7 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -66,6 +66,7 @@
 	{ USB_ID(0x041e, 0x3000), 0, 1, 2, 1,  18, 0x0013 }, /* Extigy       */
 	{ USB_ID(0x041e, 0x3020), 2, 1, 6, 6,  18, 0x0013 }, /* Audigy 2 NX  */
 	{ USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
+	{ USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
 };
 
 struct usb_mixer_interface {
@@ -78,7 +79,6 @@
 
 	/* Sound Blaster remote control stuff */
 	const struct rc_config *rc_cfg;
-	unsigned long rc_hwdep_open;
 	u32 rc_code;
 	wait_queue_head_t rc_waitq;
 	struct urb *rc_urb;
@@ -110,6 +110,8 @@
 	const struct usbmix_selector_map *selector_map;
 };
 
+#define MAX_CHANNELS	10	/* max logical channels */
+
 struct usb_mixer_elem_info {
 	struct usb_mixer_interface *mixer;
 	struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
@@ -120,6 +122,8 @@
 	int channels;
 	int val_type;
 	int min, max, res;
+	int cached;
+	int cache_val[MAX_CHANNELS];
 	u8 initialized;
 };
 
@@ -181,8 +185,6 @@
 	USB_PROC_DCR_RELEASE = 6,
 };
 
-#define MAX_CHANNELS	10	/* max logical channels */
-
 
 /*
  * manual mapping of mixer names
@@ -219,7 +221,10 @@
 	for (p = state->map; p->id; p++) {
 		if (p->id == unitid && ! p->name &&
 		    (! control || ! p->control || control == p->control)) {
-			// printk("ignored control %d:%d\n", unitid, control);
+			/*
+			printk(KERN_DEBUG "ignored control %d:%d\n",
+			       unitid, control);
+			*/
 			return 1;
 		}
 	}
@@ -376,11 +381,35 @@
 }
 
 /* channel = 0: master, 1 = first channel */
-static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value)
+static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
+				  int channel, int *value)
 {
 	return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value);
 }
 
+static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
+			     int channel, int index, int *value)
+{
+	int err;
+
+	if (cval->cached & (1 << channel)) {
+		*value = cval->cache_val[index];
+		return 0;
+	}
+	err = get_cur_mix_raw(cval, channel, value);
+	if (err < 0) {
+		if (!cval->mixer->ignore_ctl_error)
+			snd_printd(KERN_ERR "cannot get current value for "
+				   "control %d ch %d: err = %d\n",
+				   cval->control, channel, err);
+		return err;
+	}
+	cval->cached |= 1 << channel;
+	cval->cache_val[index] = *value;
+	return 0;
+}
+
+
 /*
  * set a mixer value
  */
@@ -412,9 +441,17 @@
 	return set_ctl_value(cval, SET_CUR, validx, value);
 }
 
-static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value)
+static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
+			     int index, int value)
 {
-	return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value);
+	int err;
+	err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel,
+			    value);
+	if (err < 0)
+		return err;
+	cval->cached |= 1 << channel;
+	cval->cache_val[index] = value;
+	return 0;
 }
 
 /*
@@ -718,7 +755,7 @@
 		if (cval->min + cval->res < cval->max) {
 			int last_valid_res = cval->res;
 			int saved, test, check;
-			get_cur_mix_value(cval, minchn, &saved);
+			get_cur_mix_raw(cval, minchn, &saved);
 			for (;;) {
 				test = saved;
 				if (test < cval->max)
@@ -726,8 +763,8 @@
 				else
 					test -= cval->res;
 				if (test < cval->min || test > cval->max ||
-				    set_cur_mix_value(cval, minchn, test) ||
-				    get_cur_mix_value(cval, minchn, &check)) {
+				    set_cur_mix_value(cval, minchn, 0, test) ||
+				    get_cur_mix_raw(cval, minchn, &check)) {
 					cval->res = last_valid_res;
 					break;
 				}
@@ -735,7 +772,7 @@
 					break;
 				cval->res *= 2;
 			}
-			set_cur_mix_value(cval, minchn, saved);
+			set_cur_mix_value(cval, minchn, 0, saved);
 		}
 
 		cval->initialized = 1;
@@ -775,35 +812,25 @@
 	struct usb_mixer_elem_info *cval = kcontrol->private_data;
 	int c, cnt, val, err;
 
+	ucontrol->value.integer.value[0] = cval->min;
 	if (cval->cmask) {
 		cnt = 0;
 		for (c = 0; c < MAX_CHANNELS; c++) {
-			if (cval->cmask & (1 << c)) {
-				err = get_cur_mix_value(cval, c + 1, &val);
-				if (err < 0) {
-					if (cval->mixer->ignore_ctl_error) {
-						ucontrol->value.integer.value[0] = cval->min;
-						return 0;
-					}
-					snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err);
-					return err;
-				}
-				val = get_relative_value(cval, val);
-				ucontrol->value.integer.value[cnt] = val;
-				cnt++;
-			}
+			if (!(cval->cmask & (1 << c)))
+				continue;
+			err = get_cur_mix_value(cval, c + 1, cnt, &val);
+			if (err < 0)
+				return cval->mixer->ignore_ctl_error ? 0 : err;
+			val = get_relative_value(cval, val);
+			ucontrol->value.integer.value[cnt] = val;
+			cnt++;
 		}
+		return 0;
 	} else {
 		/* master channel */
-		err = get_cur_mix_value(cval, 0, &val);
-		if (err < 0) {
-			if (cval->mixer->ignore_ctl_error) {
-				ucontrol->value.integer.value[0] = cval->min;
-				return 0;
-			}
-			snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err);
-			return err;
-		}
+		err = get_cur_mix_value(cval, 0, 0, &val);
+		if (err < 0)
+			return cval->mixer->ignore_ctl_error ? 0 : err;
 		val = get_relative_value(cval, val);
 		ucontrol->value.integer.value[0] = val;
 	}
@@ -820,34 +847,28 @@
 	if (cval->cmask) {
 		cnt = 0;
 		for (c = 0; c < MAX_CHANNELS; c++) {
-			if (cval->cmask & (1 << c)) {
-				err = get_cur_mix_value(cval, c + 1, &oval);
-				if (err < 0) {
-					if (cval->mixer->ignore_ctl_error)
-						return 0;
-					return err;
-				}
-				val = ucontrol->value.integer.value[cnt];
-				val = get_abs_value(cval, val);
-				if (oval != val) {
-					set_cur_mix_value(cval, c + 1, val);
-					changed = 1;
-				}
-				get_cur_mix_value(cval, c + 1, &val);
-				cnt++;
+			if (!(cval->cmask & (1 << c)))
+				continue;
+			err = get_cur_mix_value(cval, c + 1, cnt, &oval);
+			if (err < 0)
+				return cval->mixer->ignore_ctl_error ? 0 : err;
+			val = ucontrol->value.integer.value[cnt];
+			val = get_abs_value(cval, val);
+			if (oval != val) {
+				set_cur_mix_value(cval, c + 1, cnt, val);
+				changed = 1;
 			}
+			cnt++;
 		}
 	} else {
 		/* master channel */
-		err = get_cur_mix_value(cval, 0, &oval);
-		if (err < 0 && cval->mixer->ignore_ctl_error)
-			return 0;
+		err = get_cur_mix_value(cval, 0, 0, &oval);
 		if (err < 0)
-			return err;
+			return cval->mixer->ignore_ctl_error ? 0 : err;
 		val = ucontrol->value.integer.value[0];
 		val = get_abs_value(cval, val);
 		if (val != oval) {
-			set_cur_mix_value(cval, 0, val);
+			set_cur_mix_value(cval, 0, 0, val);
 			changed = 1;
 		}
 	}
@@ -1706,7 +1727,8 @@
 		break;
 	/* live24ext: 4 = line-in jack */
 	case 3:	/* hp-out jack (may actuate Mute) */
-		if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
+		if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+		    mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
 			snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
 		break;
 	default:
@@ -1797,24 +1819,6 @@
 	wake_up(&mixer->rc_waitq);
 }
 
-static int snd_usb_sbrc_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
-	struct usb_mixer_interface *mixer = hw->private_data;
-
-	if (test_and_set_bit(0, &mixer->rc_hwdep_open))
-		return -EBUSY;
-	return 0;
-}
-
-static int snd_usb_sbrc_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
-	struct usb_mixer_interface *mixer = hw->private_data;
-
-	clear_bit(0, &mixer->rc_hwdep_open);
-	smp_mb__after_clear_bit();
-	return 0;
-}
-
 static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf,
 				     long count, loff_t *offset)
 {
@@ -1867,9 +1871,8 @@
 	hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
 	hwdep->private_data = mixer;
 	hwdep->ops.read = snd_usb_sbrc_hwdep_read;
-	hwdep->ops.open = snd_usb_sbrc_hwdep_open;
-	hwdep->ops.release = snd_usb_sbrc_hwdep_release;
 	hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
+	hwdep->exclusive = 1;
 
 	mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!mixer->rc_urb)
@@ -1956,8 +1959,9 @@
 	int i, err;
 
 	for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
-		if (i > 1 &&  /* Live24ext has 2 LEDs only */
-			mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
+		if (i > 1 && /* Live24ext has 2 LEDs only */
+			(mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+			 mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
 			break; 
 		err = snd_ctl_add(mixer->chip->card,
 				  snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
@@ -1994,7 +1998,8 @@
 	snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
 	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
 		jacks = jacks_audigy2nx;
-	else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
+	else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+		 mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
 		jacks = jacks_live24ext;
 	else
 		return;
@@ -2044,7 +2049,8 @@
 		goto _error;
 
 	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
-	    mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) {
+	    mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+	    mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
 		struct snd_info_entry *entry;
 
 		if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index d755be0..3e5d66c 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -261,6 +261,22 @@
 	{} /* terminator */
 };
 
+static struct usbmix_name_map scratch_live_map[] = {
+	/* 1: IT Line 1 (USB streaming) */
+	/* 2: OT Line 1 (Speaker) */
+	/* 3: IT Line 1 (Line connector) */
+	{ 4, "Line 1 In" }, /* FU */
+	/* 5: OT Line 1 (USB streaming) */
+	/* 6: IT Line 2 (USB streaming) */
+	/* 7: OT Line 2 (Speaker) */
+	/* 8: IT Line 2 (Line connector) */
+	{ 9, "Line 2 In" }, /* FU */
+	/* 10: OT Line 2 (USB streaming) */
+	/* 11: IT Mic (Line connector) */
+	/* 12: OT Mic (USB streaming) */
+	{ 0 } /* terminator */
+};
+
 /*
  * Control map entries
  */
@@ -285,6 +301,11 @@
 		.map = live24ext_map,
 	},
 	{
+		.id = USB_ID(0x041e, 0x3048),
+		.map = audigy2nx_map,
+		.selector_map = audigy2nx_selectors,
+	},
+	{
 		/* Hercules DJ Console (Windows Edition) */
 		.id = USB_ID(0x06f8, 0xb000),
 		.ignore_ctl_error = 1,
@@ -311,6 +332,11 @@
 		.id = USB_ID(0x0ccd, 0x0028),
 		.map = aureon_51_2_map,
 	},
+	{
+		.id = USB_ID(0x13e5, 0x0001),
+		.map = scratch_live_map,
+		.ignore_ctl_error = 1,
+	},
 	{ 0 } /* terminator */
 };
 
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 5d8ef09..647ef50 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -39,6 +39,16 @@
 	.idProduct = prod, \
 	.bInterfaceClass = USB_CLASS_VENDOR_SPEC
 
+/* Creative/Toshiba Multimedia Center SB-0500 */
+{
+	USB_DEVICE(0x041e, 0x3048),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.vendor_name = "Toshiba",
+		.product_name = "SB-0500",
+		.ifnum = QUIRK_NO_INTERFACE
+	}
+},
+
 /* Creative/E-Mu devices */
 {
 	USB_DEVICE(0x041e, 0x3010),
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 73e59f4..98276aa 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -478,19 +478,21 @@
 	return true;
 }
 
-static struct snd_card *usx2y_create_card(struct usb_device *device)
+static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
 {
 	int		dev;
 	struct snd_card *card;
+	int err;
+
 	for (dev = 0; dev < SNDRV_CARDS; ++dev)
 		if (enable[dev] && !snd_us122l_card_used[dev])
 			break;
 	if (dev >= SNDRV_CARDS)
-		return NULL;
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct us122l));
-	if (!card)
-		return NULL;
+		return -ENODEV;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct us122l), &card);
+	if (err < 0)
+		return err;
 	snd_us122l_card_used[US122L(card)->chip.index = dev] = 1;
 
 	US122L(card)->chip.dev = device;
@@ -509,46 +511,57 @@
 		US122L(card)->chip.dev->devnum
 		);
 	snd_card_set_dev(card, &device->dev);
-	return card;
+	*cardp = card;
+	return 0;
 }
 
-static void *us122l_usb_probe(struct usb_interface *intf,
-			      const struct usb_device_id *device_id)
+static int us122l_usb_probe(struct usb_interface *intf,
+			    const struct usb_device_id *device_id,
+			    struct snd_card **cardp)
 {
 	struct usb_device *device = interface_to_usbdev(intf);
-	struct snd_card *card = usx2y_create_card(device);
+	struct snd_card *card;
+	int err;
 
-	if (!card)
-		return NULL;
+	err = usx2y_create_card(device, &card);
+	if (err < 0)
+		return err;
 
-	if (!us122l_create_card(card) ||
-	    snd_card_register(card) < 0) {
+	if (!us122l_create_card(card)) {
 		snd_card_free(card);
-		return NULL;
+		return -EINVAL;
+	}
+
+	err = snd_card_register(card);
+	if (err < 0) {
+		snd_card_free(card);
+		return err;
 	}
 
 	usb_get_dev(device);
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 static int snd_us122l_probe(struct usb_interface *intf,
 			    const struct usb_device_id *id)
 {
 	struct snd_card *card;
+	int err;
+
 	snd_printdd(KERN_DEBUG"%p:%i\n",
 		    intf, intf->cur_altsetting->desc.bInterfaceNumber);
 	if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
 		return 0;
 
-	card = us122l_usb_probe(usb_get_intf(intf), id);
-
-	if (card) {
-		usb_set_intfdata(intf, card);
-		return 0;
+	err = us122l_usb_probe(usb_get_intf(intf), id, &card);
+	if (err < 0) {
+		usb_put_intf(intf);
+		return err;
 	}
 
-	usb_put_intf(intf);
-	return -EIO;
+	usb_set_intfdata(intf, card);
+	return 0;
 }
 
 static void snd_us122l_disconnect(struct usb_interface *intf)
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
index 1558a5c..4af8740 100644
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -30,9 +30,6 @@
 #include "usbusx2y.h"
 #include "usX2Yhwdep.h"
 
-int usX2Y_hwdep_pcm_new(struct snd_card *card);
-
-
 static int snd_us428ctls_vm_fault(struct vm_area_struct *area,
 				  struct vm_fault *vmf)
 {
@@ -106,16 +103,6 @@
 }
 
 
-static int snd_usX2Y_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
-static int snd_usX2Y_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
 static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw,
 				      struct snd_hwdep_dsp_status *info)
 {
@@ -267,8 +254,6 @@
 
 	hw->iface = SNDRV_HWDEP_IFACE_USX2Y;
 	hw->private_data = usX2Y(card);
-	hw->ops.open = snd_usX2Y_hwdep_open;
-	hw->ops.release = snd_usX2Y_hwdep_release;
 	hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status;
 	hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load;
 	hw->ops.mmap = snd_us428ctls_mmap;
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index 70b9635..24393da 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -557,7 +557,7 @@
 		s->idle_insize -= max_diff - max_diff_0;
 		s->idle_insize += urb_size - s->period_size;
 		if (s->idle_insize < 0) {
-			snd_printk("%i %i %i\n",
+			snd_printk(KERN_WARNING "%i %i %i\n",
 				   s->idle_insize, urb_size, s->period_size);
 			return;
 		} else if (s->idle_insize == 0) {
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index 11639bd..5ce0da2 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -227,9 +227,9 @@
 	
 	if (usX2Y->US04) {
 		if (0 == usX2Y->US04->submitted)
-			do
+			do {
 				err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC);
-			while (!err && usX2Y->US04->submitted < usX2Y->US04->len);
+			} while (!err && usX2Y->US04->submitted < usX2Y->US04->len);
 	} else
 		if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) {
 			if (us428ctls->p4outLast != us428ctls->p4outSent) {
@@ -333,18 +333,21 @@
 	{ /* terminator */ }
 };
 
-static struct snd_card *usX2Y_create_card(struct usb_device *device)
+static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
 {
 	int		dev;
 	struct snd_card *	card;
+	int err;
+
 	for (dev = 0; dev < SNDRV_CARDS; ++dev)
 		if (enable[dev] && !snd_usX2Y_card_used[dev])
 			break;
 	if (dev >= SNDRV_CARDS)
-		return NULL;
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct usX2Ydev));
-	if (!card)
-		return NULL;
+		return -ENODEV;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct usX2Ydev), &card);
+	if (err < 0)
+		return err;
 	snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1;
 	card->private_free = snd_usX2Y_card_private_free;
 	usX2Y(card)->chip.dev = device;
@@ -362,26 +365,36 @@
 		usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum
 		);
 	snd_card_set_dev(card, &device->dev);
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 
-static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *intf, const struct usb_device_id *device_id)
+static int usX2Y_usb_probe(struct usb_device *device,
+			   struct usb_interface *intf,
+			   const struct usb_device_id *device_id,
+			   struct snd_card **cardp)
 {
 	int		err;
 	struct snd_card *	card;
+
+	*cardp = NULL;
 	if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 ||
 	    (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 &&
 	     le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 &&
-	     le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428) ||
-	    !(card = usX2Y_create_card(device)))
-		return NULL;
+	     le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428))
+		return -EINVAL;
+
+	err = usX2Y_create_card(device, &card);
+	if (err < 0)
+		return err;
 	if ((err = usX2Y_hwdep_new(card, device)) < 0  ||
 	    (err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
-		return NULL;
+		return err;
 	}
-	return card;
+	*cardp = card;
+	return 0;
 }
 
 /*
@@ -389,13 +402,14 @@
  */
 static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
-	void *chip;
-	chip = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id);
-	if (chip) {
-		usb_set_intfdata(intf, chip);
-		return 0;
-	} else
-		return -EIO;
+	struct snd_card *card;
+	int err;
+
+	err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card);
+	if (err < 0)
+		return err;
+	dev_set_drvdata(&intf->dev, card);
+	return 0;
 }
 
 static void snd_usX2Y_disconnect(struct usb_interface *intf)
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.h b/sound/usb/usx2y/usx2yhwdeppcm.h
index c3382fd..9c4fb84 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.h
+++ b/sound/usb/usx2y/usx2yhwdeppcm.h
@@ -18,3 +18,5 @@
 	volatile unsigned captured_iso_frames;
 	int capture_iso_start;
 };
+
+int usX2Y_hwdep_pcm_new(struct snd_card *card);